Sign in to follow this  
Shamino

OpenGL My OGL Render Class

Recommended Posts

Shamino    100
Here we go! Its the birth of a render class, very incredibly simple, only sends a quad to the renderer and then, renders it. Renderer.h
#include <vector>
#include "Vector3.h"

using namespace std;

struct	BasicQuad
{
	Vector3 P1, P2, P3, P4;
	int	Texture;//Index into gpTextureManager
};

std::vector<BasicQuad*>	mBasicQuads;



class GLRenderer
{
public:
	GLRenderer()
	{

	}

	
	void	AddBasicQuadToRenderer(float P1X,float  P1Y,float	P1Z,
								   float P2X,float	P2Y,float	P2Z,
								   float P3X,float	P3Y,float	P3Z,
								   float P4X,float	P4Y,float	P4Z,
								   int	Texture)
	{
		BasicQuad	*pData = new	BasicQuad;
		pData->P1	=	Vector3(P1X,P1Y,P1Z);
		pData->P2	=	Vector3(P2X,P2Y,P2Z);
		pData->P3	=	Vector3(P3X,P3Y,P3Z);
		pData->P4	=	Vector3(P4X,P4Y,P4Z);
		pData->Texture	=	Texture;
		mBasicQuads.push_back(pData);
	}


	void RenderBasicQuads();
};
Renderer.cpp
#include <windows.h>
#include <gl\gl.h>			// Header File For The OpenGL32 Library
#include <gl\glu.h>			// Header File For The GLu32 Library
#include <gl\glaux.h>		// Header File For The Glaux Library
#include "Renderer.h"

void GLRenderer::RenderBasicQuads()
{
	if(!mBasicQuads.size())
	return;

	glDisable(GL_LIGHTING);
	glDisable(GL_BLEND);

	BasicQuad	*	pTemp;

	std::vector<BasicQuad*>::iterator	ptr;
	
	for(ptr = mBasicQuads.begin(); ptr != mBasicQuads.end(); ptr++)
	{
		pTemp	=	*ptr;
		
		glBegin(GL_QUADS);//Cannot be brought out of loop due to bindtexture call
	
		glVertex3f(pTemp->P1.x,pTemp->P1.y,pTemp->P1.z);
		
		glVertex3f(pTemp->P2.x,pTemp->P2.y,pTemp->P2.z);
		
		glVertex3f(pTemp->P3.x,pTemp->P3.y,pTemp->P3.z);
		
		glVertex3f(pTemp->P4.x,pTemp->P4.y,pTemp->P4.z);

		glEnd();
	}
	delete pTemp;
}
and my lil vector3 class, proves very useful :d Vector3.h
class Vector3
{
public:
 float x, y, z;

  Vector3()
  {
  }

  Vector3(float x, float y, float z);

// And so on
};
Any comments? suggestions? etc?

Share this post


Link to post
Share on other sites
Endar    668

  • Use triangles because you can draw anything with triangles, and you'll have to add it eventually. So, you might as well just have it draw only triangles.

  • If you're changing it to triangles, you'll need to add texture coords to your class.

  • Initialize 'pTemp' to NULL inside "RenderBasicQuads". It's not strictly necessary for this code since you assign it at the beginning of every loop iteration, but get into the habit, else you'll forget and wonder why there's an invalid memory access at 0x92739838 instead of 0x00000000, which is much easier to debug.

  • You haven't actually added the call to glBindTexture inside "RenderBasicQuads".

  • You haven't included a call to glTexCoords (or whatever its called) to specify the texture coords for each vertex.

  • Have the function "AddBasicQuadToRenderer" actually take a BasicQuad object, or 3 Vector3 objects and the texID, or whatever object type you'll be using, else you'll accidently swap a single parameter and be looking for it for hours.

  • With the "delete pTemp;" statment inside "RenderBasicQuads", it will effectively delete the memory allocated for BasicQuad object for the last element in the list, but won't delete the list element, therefore causing memory access problems the next time you try to access the list element, because the pointer in the list element is still pointing to what is now an invalid memory address to access. I'm guessing that it's not what you're trying to do.

  • Your list of things to be rendered should be kept inside the GLRenderer list. If a class has functionality, but no data members, make the functions static so you don't have to bother actually creating an object which has no data, just to run the functions.

  • If you're not turning off/on any features like lighting, blending, just put the glDisable function calls in the same function where you initialize OpenGL. It's wasteful and just might make your rendering slower (don't quote me on this), calling these two every time you render.

  • In "AddBasicQuadToRenderer", instead of assigning every data member yourself (points 1,2,3,4 and texID), just make it an overloaded assignment operator for the BasicQuad class. Because if you end up changing the BasicQuad class you'll have to re-write the "AddBasicQuadToRenderer" code every time you make a small change. With the overloaded operator in the BasicQuad class, you just have to change the BasicQuad code, which you'll already be doing. Otherwise you'll find yourself having to re-write 50 lines of code all over the place when you make add an integer to a struct or class.


It's late here. Please let me know if I got any of this wrong.

[Edited by - Endar on November 24, 2005 6:49:37 AM]

Share this post


Link to post
Share on other sites
Endar    668
Did you also know that class and struct are almost exactly the same thing?

So when you have a struct, you can add constructors, functions and overloaded operators to it. I have a couple of things like this, where, even though all the data members are all public, I have functions and operators to make things simpler and the code more readable.

That's really all the suggestions I have for the moment. I hope I helped.

Share this post


Link to post
Share on other sites
Shamino    100
About overloading the basic quad structure, I can overload an addition operator to just add it to the function instead of writing in the parameters myself? That is nifty...

Share this post


Link to post
Share on other sites
Endar    668
Quote:
Original post by Shamino
About overloading the basic quad structure, I can overload an addition operator to just add it to the function instead of writing in the parameters myself? That is nifty...


I have no idea what you mean.

When I was talking about overloading for the BasicQuad struct I was talking about something like this:


struct BasicQuad
{
Vector3 P1, P2, P3, P4;
int Texture;


BasicQuad(const BasicQuad& b)
{
P1 = b.P1;
P2 = b.P2;
P3 = b.P3;
P4 = b.P4;
Texture = b.Texture;
}

BasicQuad& operator=(const BasicQuad& b)
{
if( &b != this ){
P1 = b.P1;
P2 = b.P2;
P3 = b.P3;
P4 = b.P4;
Texture = b.Texture;
}
return *this;
}
};


// blah

void AddBasicQuadToRenderer(const BasicQuad& b)
{
// this
BasicQuad *pData = new BasicQuad;
(*pData) = b;

// OR this
BasicQuad *pData = new BasicQuad(b);


// then add to the vector
mBasicQuads.push_back(pData);
}




See? Also, don't overload operators if it doesn't make sense. I mean, if you can look at an operator and the types on either side and instantly know what it does, even if you haven't seen the code before, then it's right. If you have to think for a second, chances are that it doens't belong and should have a proper function.

Share this post


Link to post
Share on other sites
Shamino    100
Maybe i said overload and shouldn't have, thats exactly what I ment....


Throw the object in the parameters instead of having 30 million floats.... Looks much more effient than my code... But I don't have much use for my Vector3 class now do i ?

Share this post


Link to post
Share on other sites
Endar    668
In the code that you have there? Not really. But keep it in there and keep building it up, because for anything more complex you will use it.

You'll need it to do the dot product, cross product, have all the common overloaded operators (+,-,/,+=,-=,/= etc). It'll probably end up hidden inside a vertex class, which would be something like this:


class Vertex
{
public:

Vector3 pos; // position
Vector3 normal; // normal
float u,v; // texture coords


// functions
};



So don't throw it away, or even consider stopping using it. As you get onto more complex things, pretty much anything more complex than what you have right now, you'll need it. It's one of the major building blocks of anything 3d graphics related.

Share this post


Link to post
Share on other sites
Endar    668
I did the same. In fact, it was the first thing that I wrote that I still use.

It's small enough to be mostly finished in a couple of days/week. If you don't know about vector math you learn a lot by reading the resources that you use to write it.

Share this post


Link to post
Share on other sites
Shamino    100
Main goals are as follows: Switch to tri's, make it so AddBasicTriToRenderer takes a tri object, instead of 80 parameters, and fix ptemp de-allocation

Share this post


Link to post
Share on other sites
Endar    668
Looks good. As you gain more experience, you'll find different and better ways of doing things, but that's pretty good for a start up. [smile]

Share this post


Link to post
Share on other sites
Shamino    100
So like this :D


#include <vector>
#include "Vector3.h"

using namespace std;

struct BasicTri
{
Vector3 P1, P2, P3;
int Texture;


BasicTri(const BasicTri& t)
{
P1 = t.P1;
P2 = t.P2;
P3 = t.P3;
Texture = t.Texture;
}

BasicTri& operator=(const BasicTri& t)
{
if( &t != this ){
P1 = t.P1;
P2 = t.P2;
P3 = t.P3;
Texture = t.Texture;
}
return *this;
}
};

std::vector<BasicTri*> mBasicTri;


void AddBasicTriToRenderer(const BasicTri& t)
{
BasicTri *pData = new BasicTri(t);

// then add to the vector
mBasicTri.push_back(pData);
}

Share this post


Link to post
Share on other sites
Shamino    100
Founda few unoptimized issues with your code, replaced it with...


#include <vector>
#include "Vector3.h"

using namespace std;

struct BasicTri
{
Vector3 P1, P2, P3;
int Texture;


BasicTri(const BasicTri& t)
{
P1 = t.P1;
P2 = t.P2;
P3 = t.P3;
Texture = t.Texture;
}

BasicTri& operator=(const BasicTri& t)
{
if( &t != this ){
P1 = t.P1;
P2 = t.P2;
P3 = t.P3;
Texture = t.Texture;
}
return *this;
}
};

std::vector<BasicTri*> mBasicTri;


void AddBasicTriToRenderer(BasicTri* t)
{
// then add to the vector
mBasicTri.push_back(t);
}


With your AddBasicTriToRenderer function you created a new triangle when you didnt need to.. i'll show you


void AddBasicTriToRenderer(const BasicTri& t)
{

BasicTri *pData = new BasicTri(t);


// then add to the vector
mBasicTri.push_back(pData);
}


Is now this

void AddBasicTriToRenderer(BasicTri* t)
{

// then add to the vector
mBasicTri.push_back(t);
}




Share this post


Link to post
Share on other sites
Endar    668
Quote:
Original post by Shamino

void AddBasicTriToRenderer(const BasicTri& t)
{

BasicTri *pData = new BasicTri(t);


// then add to the vector
mBasicTri.push_back(pData);
}


Is now this

void AddBasicTriToRenderer(BasicTri* t)
{

// then add to the vector
mBasicTri.push_back(t);
}


Fair enough, if you want to do it that way, but that means that you have to pay attention and every time you add a tri to the list, you need to make sure that you create it on the heap before passing the pointer to the function. If you forget, and you pass in an address from the stack, you'll have problems when that memory is overwritten and used for something else in your program, or when you delete all the list elements, you'll get a very strange error that basically means that you tried to delete some stack memory. But, if you think you can remember to create a new one in memory before passing the point in, I have absolutely no issue with it. [smile]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Partner Spotlight

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now