Jump to content

  • Log In with Google      Sign In   
  • Create Account


Need a design advice on a Mesh Class


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 13 January 2014 - 10:43 AM

The OpenGL Context that I'm coding it's instance based, so owns OpenGL Objects (shaders, programs, textures).

I think that the code it's very redundant since the context creates the Mesh Buffer.

In that case why I can't store the Mesh in a Struct and just call Mesh.buffer = GLContext.CreateBuffer?

 

My Mesh class follows:

 

class Mesh {

public:

std::vector<Vertex> vertex;

std::vector<unsigned int> index;

GraphicsBuffer* buffer; //a wrapper for GL vertex/index buffers

 

void CreateBuffer(GLContext& context) //looks like DX methods for creating Vertex/Index Buffer

{

  buffer = context.CreateBuffer(*this);

}

 

};

 

I know that this violates the OOP but it's very very redundant.


Edited by irlanrobson, 13 January 2014 - 01:32 PM.


Sponsor:

#2 apatriarca   Crossbones+   -  Reputation: 1649

Like
1Likes
Like

Posted 13 January 2014 - 10:53 AM

If Context::CreateBuffer calls Mesh::CreateBuffer you have an infinite loop. This is in my opinion the main reason to avoid doing that.



#3 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 13 January 2014 - 11:00 AM

If Context::CreateBuffer calls Mesh::CreateBuffer you have an infinite loop. This is in my opinion the main reason to avoid doing that.

The GLContext returns a MeshBuffer* which is stored in a std::vector<MeshBuffer*> inside the context.


Edited by irlanrobson, 13 January 2014 - 05:47 PM.


#4 L. Spiro   Crossbones+   -  Reputation: 13268

Like
2Likes
Like

Posted 15 January 2014 - 11:40 PM

I’ve already covered this in detail.

 

A mesh does not manage an OpenGL object of any kind directly.

A vertex buffer class manages an OpenGL VBO.

An index buffer class manages an OpenGL IBO.

 

A mesh brings these 2 things together without knowing what OpenGL is.

 

 

Your suggestion is severely flawed in that the mesh knows what a context is and the context knows what a mesh is.

The context should have absolutely no idea what a mesh is.

Vertex buffers and index buffers live inside the graphics module, but meshes and models live above that.

A mesh knows what graphics are, not the other way around.

Let the mesh make its own vertices and indices via the CVertexBuffer and CIndexBuffer classes that wrap around GLuint VBO/IBO ID’s.

 

 

L. Spiro


It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#5 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 16 January 2014 - 08:19 AM

I’ve already covered this in detail.

 

A mesh does not manage an OpenGL object of any kind directly.

A vertex buffer class manages an OpenGL VBO.

An index buffer class manages an OpenGL IBO.

 

A mesh brings these 2 things together without knowing what OpenGL is.

 

 

Your suggestion is severely flawed in that the mesh knows what a context is and the context knows what a mesh is.

The context should have absolutely no idea what a mesh is.

Vertex buffers and index buffers live inside the graphics module, but meshes and models live above that.

A mesh knows what graphics are, not the other way around.

Let the mesh make its own vertices and indices via the CVertexBuffer and CIndexBuffer classes that wrap around GLuint VBO/IBO ID’s.

 

 

L. Spiro

 

Always helpful LS.Spiro. Now becomes:

class VertexBuffer; 
class IndexBuffer; 

//Mesh.h 
class Mesh { //the context manages the buffers 
public: 
Mesh() : vbuffer(0), ibuffer(0) 
{ 
} 
void GenBuffers(GLContext& context) //inside cpp file 
{ 
context.GenVertexBuffer(vertex, vbuffer); 
context.GenIndexBuffer(index, ibuffer); 
} 
void DrawBuffers(GLContext& context) //inside cpp file 
{ 
context.DrawBuffersIndexed(vbuffer, ibuffer, index.size()); //index count 
} 

private: 
std::vector<Vertex> vertex; 
std::vector<unsigned int> index; 
VertexBuffer* vbuffer; 
IndexBuffer* ibuffer; 
}; 

struct VertexBuffer { 
GLuint vbo; 
}; 
struct IndexBuffer { 
GLuint ibo; 
};

Edited by irlanrobson, 16 January 2014 - 08:32 AM.


#6 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 16 January 2014 - 08:58 AM

I’ve already covered this in detail.

 

A mesh does not manage an OpenGL object of any kind directly.

A vertex buffer class manages an OpenGL VBO.

An index buffer class manages an OpenGL IBO.

 

A mesh brings these 2 things together without knowing what OpenGL is.

 

 

Your suggestion is severely flawed in that the mesh knows what a context is and the context knows what a mesh is.

The context should have absolutely no idea what a mesh is.

Vertex buffers and index buffers live inside the graphics module, but meshes and models live above that.

A mesh knows what graphics are, not the other way around.

Let the mesh make its own vertices and indices via the CVertexBuffer and CIndexBuffer classes that wrap around GLuint VBO/IBO ID’s.

 

 

L. Spiro

 
I'm confused with one thing. In the post you made you said that VertexBuffer has vertex data and a VBO.
If a physics system needs to acess vertex data for compute AABBs (eg.) it will via vertex buffer and not the mesh itself?
I understand that that vertex data type it's a very specific thing for the graphics context, but the physics system will not have acess to vertex data until the buffer is created in that case.
 
One more thing. In the old topic you said that the only thing a VB has is vertex data and shouldn't be hardcoded. That makes sense but my point of view is:
 
If a VertexBuffer is suposed to have positions, normals, binormals and texture coordinates. The class should be the following:
 
class VertexBuffer {
(...) //vao, vbo etc...

std::vector<Vector3> position;
std::vector<Vector3> uv;
std::vector<Vector3> normal;
std::vector<Vector3> binormal;
};

or better:

class BaseVertex {
public:
position;
uv;
normal;
};

class OtherVertex : public BaseVertex {
public:
binormal;
tangent;
};

Edited by irlanrobson, 16 January 2014 - 03:03 PM.


#7 L. Spiro   Crossbones+   -  Reputation: 13268

Like
3Likes
Like

Posted 17 January 2014 - 05:57 AM

Currently I don’t have time to respond in full to all points that need to be addressed, but the 2 major issues can be addressed briefly.
 
#1:

If a physics system needs to acess vertex data for compute AABBs (eg.) it will via vertex buffer and not the mesh itself?

The AABB will have already been computed offline during the creation of your custom model format. It has nothing to do with vertex buffers. Again, vertex buffers are related to graphics and graphics only, no other sub-system. If any other sub-system is involved, a local CPU copy of the vertices is used, not a vertex buffer.

#2:

If a VertexBuffer is suposed to have positions, normals, binormals and texture coordinates. The class should be the following:

And what about all the 2D HUD elements that have only a position and UV?
Any combination of any set of attributes can be used to create a vertex buffer. That is why we never use structures to create vertex buffer elements. Your wrapper should work the way graphics API’s work. Let the user decide what is inside the vertex buffer and at what offsets, and give them a structure to fill out that you can translate into something your graphics API can use.


L. Spiro

Edited by L. Spiro, 17 January 2014 - 05:58 AM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#8 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 17 January 2014 - 08:52 AM

Currently I don’t have time to respond in full to all points that need to be addressed, but the 2 major issues can be addressed briefly.
 
#1:

If a physics system needs to acess vertex data for compute AABBs (eg.) it will via vertex buffer and not the mesh itself?

The AABB will have already been computed offline during the creation of your custom model format. It has nothing to do with vertex buffers. Again, vertex buffers are related to graphics and graphics only, no other sub-system. If any other sub-system is involved, a local CPU copy of the vertices is used, not a vertex buffer.

#2:

If a VertexBuffer is suposed to have positions, normals, binormals and texture coordinates. The class should be the following:

And what about all the 2D HUD elements that have only a position and UV?
Any combination of any set of attributes can be used to create a vertex buffer. That is why we never use structures to create vertex buffer elements. Your wrapper should work the way graphics API’s work. Let the user decide what is inside the vertex buffer and at what offsets, and give them a structure to fill out that you can translate into something your graphics API can use.


L. Spiro

 

1# Understood. I'll use a copy of the vertex data.
2# This approach looks similar of a Vertex Layout (used in DX11). So I'm emulating DirectX 11 in OpenGL. I'll create a Vertex Layout structure and pass to the vertex buffer creation.


#9 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 17 January 2014 - 09:08 AM

Currently I don’t have time to respond in full to all points that need to be addressed, but the 2 major issues can be addressed briefly.
 
#1:

If a physics system needs to acess vertex data for compute AABBs (eg.) it will via vertex buffer and not the mesh itself?

The AABB will have already been computed offline during the creation of your custom model format. It has nothing to do with vertex buffers. Again, vertex buffers are related to graphics and graphics only, no other sub-system. If any other sub-system is involved, a local CPU copy of the vertices is used, not a vertex buffer.

#2:

If a VertexBuffer is suposed to have positions, normals, binormals and texture coordinates. The class should be the following:

And what about all the 2D HUD elements that have only a position and UV?
Any combination of any set of attributes can be used to create a vertex buffer. That is why we never use structures to create vertex buffer elements. Your wrapper should work the way graphics API’s work. Let the user decide what is inside the vertex buffer and at what offsets, and give them a structure to fill out that you can translate into something your graphics API can use.


L. Spiro

 

 
That's my perspective:
 
struct VertexInfo {
GLuint index;
GLint size;
(...) pointer to data etc...
};


mesh.CreateVertexBuffer(ContextGL& context)
{
VertexAttribute vinfo;
(...) fill info
context.CreateVertexBuffer(vbuffer, vinfo);
}


#10 L. Spiro   Crossbones+   -  Reputation: 13268

Like
1Likes
Like

Posted 17 January 2014 - 02:16 PM

You are getting closer, but one of the things I wanted to say that I didn’t have time to say before is in regards to passing an OpenGL context around all the time.

Are you going to call ::wglMakeCurrent() (or similar) on every single OpenGL call? That is the only reason the vertex buffer would need you to pass a context into it; it is the only relevant function that can be called related to the context. If that is how you want to emulate object-oriented programming, you would be calling ::wglMakeCurrent() for every single call, including ::glEnable() etc.

Why do you need more than one context anyway? Even if you have multiple “renderer” instances a single context is enough. You don’t need more than one context to do object-oriented OpenGL programming, and even if you did the object you would be passing around would be some kind of more-generalized class such as “Renderer” or something above and beyond “ContextGL”.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#11 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 17 January 2014 - 03:23 PM

You are getting closer, but one of the things I wanted to say that I didn’t have time to say before is in regards to passing an OpenGL context around all the time.

Are you going to call ::wglMakeCurrent() (or similar) on every single OpenGL call? That is the only reason the vertex buffer would need you to pass a context into it; it is the only relevant function that can be called related to the context. If that is how you want to emulate object-oriented programming, you would be calling ::wglMakeCurrent() for every single call, including ::glEnable() etc.

Why do you need more than one context anyway? Even if you have multiple “renderer” instances a single context is enough. You don’t need more than one context to do object-oriented OpenGL programming, and even if you did the object you would be passing around would be some kind of more-generalized class such as “Renderer” or something above and beyond “ContextGL”.


L. Spiro

All my Wrappers for OpenGL Objects (Shaders, Textures, VB, IB) lives in the Context, and these objects manage the lifetime by themselves but the ContextGL that delete them. When the context creates a VBO, it puts the vbo in a std::vector<VertexBuffer*> for delete them when gets destroyed.

 

One thing that I didn't said is that the ContextGL was doing the Rendering stuff (but it's just temporary since the "Single Responsability Principle" it's a must).

 

Okay... What I've undestand from your perspective is that (since my context was doing the rendering job) the context is a Renderer and inside the Renderer is where the Wrapped Objects lives.



#12 Irlan   Members   -  Reputation: 1460

Like
0Likes
Like

Posted 17 January 2014 - 03:44 PM

Here is my code with the correction: 

class RendererGL {
public:
	RendererGL();
	~RendererGL();

	void SetViewport(int x, int y, int w, int h);

	void CreateTexture(Texture2D** texture);
	void CreateVertexBuffer(const ArrayInfo& ainfo, const std::vector<VertexInfo>& vinfo, VertexBuffer** buffer);
	void CreateIndexBuffer(const std::vector<unsigned int>& index, IndexBuffer** buffer);
	void CreateShader(Shader** shader);
	void CreateProgram(const std::vector<Shader>& shader, ShaderProgram** program);

	void RenderBuffers(VertexBuffer* vbuffer, IndexBuffer* ibuffer);
//private: //tmp
	ShaderProgram* program;
  
	std::map<std::string, Texture2D> texture;	
	std::map<std::string, Shader> shader;
        //more objects
};

Edited by irlanrobson, 17 January 2014 - 03:49 PM.


#13 L. Spiro   Crossbones+   -  Reputation: 13268

Like
2Likes
Like

Posted 18 January 2014 - 01:21 PM

If there is a need for textures to be managed, they should be managed by a class designed to manage textures.
Same goes for shaders. I don’t know what you are doing here but your maps look like primitive managers.

Even if managers are associated with the renderer instance, they should still be separate classes that are members of the renderer. Keep their implementations separate and modular.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS