• Advertisement
Sign in to follow this  

Polygon class c++

This topic is 3444 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hy. I'm tring to create a good and fast c++ class for drawing polygons. The problem is this: Where create the load methods for fill the poly class as sample from a collada file? In the class? Is fast fill the poly class with method for add material,texture or vertex? And .. another question : Is better to inherith from the base class poly and create a texturepoly class ,or a materialpolyclass ad ex? thanks

Share this post


Link to post
Share on other sites
Advertisement
You should probably split your polygon class into multiple different classes. You could have a different class for loading your polygon data and drawing it.

Most file formats (e.g. collada, .obj, etc) give you the polygon data (vertex coordinate, normal vector, texture coordinates, tangent vectors, etc.) in a "planar" format (similar to planar image formats), so that you have a pair of data and indices for each vertex attribute, so that you have (vertexdata:vertex indices, normal data: normal indices, ...).

On the other hand, graphics API's usually want interlaved data, a pair of interleaved vertex data and indices there, eg (v0,n0), (v1,n1), (v2,n2): (i0, i1, i2), where v# are vertex coordinates, n# are normal vectors and i# are indices to these interleaved vertices.

For example, a textured cube has 8 vertices, 6 normal vectors and 4 texture coordinates. When these are interleaved, they will form 24 different vertices.

You can write separate classes for different vertex data representations and write a conversion algorithm from one format to the other.

You can then upload the data to vertex buffers and draw it efficiently. You can delete the original data if you don't need it any more.

Mesh data also varies in vertex formats. If you want to support multiple vertex formats you probably want store that with your mesh data.

Texture, material and other properties are better stored elsewhere.

It's probably not a good idea to write a basic mesh super class and extend as different properties are added. Better try to make small classes and combine them with a has-a relationship.

This is what I currently have:

class PlanarVertexData
{
class Plane
{
vector<float> data;
vector<short> indices;
}
List<Plane> planes;
VertexFormat format;
}

class InterleavedVertexData
{
vector<float> data;
vector<short> indices;
VertexFormat format;
}

class VertexView
{
VertexBuffer data;
IndexBuffer indices;
VertexFormat format;

VertexView(InterleavedVertexData data)
{
// upload data to vertex buffers
}

void draw(int firstIndex, int numIndices);
}


class MeshObject
{
class Element
{
List<Texture*> textures;
Material material;
int firstIndex, numIndices;
}

VertexView vertexView;
List<Element> elements;

void draw()
{
setupVertexFormat(vertexView.format);
for element in elements:
setupTextureUnits(element.textures);
setupMaterial(element.material);
vertexView.draw(element.firstIndex, element.numIndices);
}
}


Hope this gives you an idea how to get going.
-Riku

Share this post


Link to post
Share on other sites
Very Thanks Riku.

But I dont understand what are different vertex data representations ,sorry for my english.
You know a books or tutorial on this argument(c++ in graphics programming)?

[Edited by - giugio on August 1, 2008 5:46:09 AM]

Share this post


Link to post
Share on other sites
and another question:
I must implement a draw function for draw wireframe , one for draw selected and so on.
I need to implement 2 or more draw function in the poly class?
Thanks.

Share this post


Link to post
Share on other sites
What do you use? DirectX or OpenGL?
And Wireframe Mode can be achieved by setting a simple state like
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Don't know how to do this in DirectX :D.
regards.

Share this post


Link to post
Share on other sites
I don't really know a good tutorial on the subject, but once you study different mesh data formats and drawing with vertex and index buffers, I'm sure you can figure out what's the deal. Meshes are usually stored in the planar format because it's more space efficient and easier to edit while graphics API's use interleaved format for most efficient drawing.

For wireframe drawing, you can either use your graphics API's drawing functions (e.g. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) or whatever it was) or do another drawing function that draws line loops or similar. You may need another index buffer for this.

-Riku

Share this post


Link to post
Share on other sites
hy.
a user ask me this...
Quote:

My question was: if you draw using vertex arrays (which is also the default in Direct3D), how can you use more than one index array? As far as I know, this is impossible and you have to use one index buffer for all the vertices, normals, texture coordinates, etc...

Jeroen


this is the post:
http://www.gamedev.net/community/forums/topic.asp?topic_id=501821

"how can you use more than one index array"
what means use more than one index array?
wy?

Share this post


Link to post
Share on other sites
As riku said, when it comes to actually passing your data to the graphics API in the form of a vertex buffer, you can only do it as one big interleaved array (so Vertex Position1, Normal1, TextCoord1; Vertex Position2, Normal2, Texcoord2; and so on...) and then you can only have ONE index buffer.

Many data formats like Collada store the information in multiple separate arrays, like :

-VertexPosition1, VertexPosition2, VertexPosition3,...
-Normal1, Normal2, Normal3,...
-TexCoord1, TexCoord2, TexCoord3,...

and then you have one index buffer per array.

So for drawing collada geometry with DirectX or OpenGL, you need to convert the data from one format to the other.

Share this post


Link to post
Share on other sites
Hy again.
I have to refactoring my code because i would use VBO and lists.
The poligon class must be rewritten.
I could have only an interleaved array in the polygon class.
"Could" because i wite a collada importer , that fill a polygonData class with vertex,normals,colors and texture array.
In the collada importer i do all in sequential mode:
1)import vertex and store in vetexes array
2)import normals and store in normals array
3)import colors and store in colorsArray

4)now i set the indexes:the collada importer return me the data in this mode:
IndexVertexX,IndexVertexY,IndexVertexZ,IndexNormal1,IndexColor1 ecc...
now i must load from the arrays( 1)vetexes array, 2)normals array, 3)colorsArray ) the:
VertexX,VertexY,VertexZ,Normal1,Color1 ecc...
and create only the interleaved array for VBO and lists in the class polygondata
but where i put the vertexData( 1)vetexes array, 2)normals array, 3)colorsArray ) ? in the polygonData?or in the importer?
if i put all in the polygon data i have redundant information(arrays 1 2 and 3 and the Interleaved array for VBO).
Then i suppose that could be put in the importer , and when the importer has do his work can be deleted.
is done?
Thanks.

Share this post


Link to post
Share on other sites
What do you mean with "VertexX,VertexY,VertexZ" but "Normal1" when speaking of indices? Are there really a single index per vertex position scalar component?

I recently had a similar problem. I have a TriMesh class that manages an array of vertex positions, an array of vertex normals, and so on, and an array for indices for each attribute, i.e. an array for indices into the position array, an array of indices into the normal array, and so on.

Each position or normal or whatever attribute exists only once in its belonging array. So the attribute array are typically of different lenghtes. All index arrays are of the same length, since each entry stands for a corner of a triangular face.

The job to do was hence to assemble vertices from the vertex attributes but so that a combination of indices only produces a new vertex if it hasn't occured already earlier, else the previous occurance has to be reused.

Is that the problem you're facing?

I've solved this by allocating a hash table of the length of the index arrays (i.e. an entry for each corner of the mesh), compute a hash value from the indices, use a look-up into the table whether there was a vertex index computed already earlier, and re-use it if so, otherwise I allocate a new index and use that. Here "using" means to push it onto the vertex index array what gives the index VBO data later. To keep things simple, I use linear probing if collisions occur. After computing the vertex indices, I use it together with the attribute arrays to assemble the vertex data VBO itself.

The result isn't optimal w.r.t. vertex caching yet, but it is nevertheless memory optimal. The temporary computations need an additional array of 2 or 4 bytes per corner only.

Share this post


Link to post
Share on other sites
I'm not understand: why you need to eliminate the vertexes that appear more than once?
for fast drawing or for memory allocation?

If is for fast, why is faster this procedure?

Share this post


Link to post
Share on other sites
It is not mainly to reduce memory consumption. The whole concept of the post-T&L cache consists of avoiding to transform and light the same vertex more than once, i.e. to run the vertex shader program on the same vertex more than once. Therefore it makes totally sense to ensure to re-use vertices where possible, but not to push the same vertex data a second time throught the vertex shader.

Therefore it is best to ensure that every used combination of vertex attributes occurs exactly once in the vertex data VBO. Without this, vertex indices would have no sense at all.

Share this post


Link to post
Share on other sites
Thanks haegarr.
I'm not understand :
But the in the VBO i have to pass one point at once with the attributes,for 3 times if i have a triangular Mesh.
If i have a point that is repeated i must pass it in anywhere or i can save the memory and the time?
if I have:

if (m_useVertexArrays)
{
for (int i = 0; i < m_numStrips; ++i)
{
glDrawElements(GL_TRIANGLE_STRIP, m_vertsPerStrip, GL_UNSIGNED_INT,
&m_indexArray[i * m_vertsPerStrip]);
}
}


If i have a triangle that have a shared vertex and i dont pass it two time in the Interleaved array the triangle is dont closed.
isn't so '?

Share this post


Link to post
Share on other sites
Remember back the discussion whether to use GL_TRIANGLE_STRIP or else GL_TRIANGLES (i.e. lists). I'll use lists in the following.

Assume you have 4 vertices in your vertex data VBO, consisting of the attributes position, normal, and a texture tuple, and assembled in an interleaved structure. That may look like
{ v0, v1, v2, v3 }
Your index array then may look like
{ 0, 1, 2, 2, 3, 0 }

Invoked with GL_TRIANGLES, you get a triangle with the vertices 0, 1, 2 and another one with 2, 3, 0. Although you have 6 corners (2 triangles with 3 corners per triangle), you need only 4 vertices, since 2 vertices are shared. Due to the 6 corners, you have 6 indices.

The shared indices are obviously 0 and 2. When the rendering happens, the GPU fetches index 0, 1, and 2, sees that the belonging vertices are not in the post-T&L cache and hence fetches them from the memory (I neglect the input cache here for simplicity). Next, it fetches indices 2, 3, and 0 and sees that vertices with index 2 and 0 are already (and still) in the post-T&L cache, and hence re-uses them together with the freshly fetched vertex 3.

So only 4 vertex fetches and shader program runs are done to render faces with 6 corners. That is the sense of the post-T&L cache.

Now consider that the post-T&L cache has only a limited space. Not more than N vertices can be cached. That means that, if new vertices are coming in, old vertices must be dropped from the cache. If any of the previously dropped vertices will be used later again, it is not available from the cache any more, and hence need to be processed totally once more.

An example: Assume that the cache can store 3 vertices. From the VBOs described above, vertices 0, 1, and 2 are coming in, processed by the vertex program, and then stored in the cache. The cache is hence filled up. Next, vertex 2 is requested. Okay, is available from the cache. Next, vertex 3 is requested; it is not available, hence it is fetched, processed and stored into the cache. But the cache was already full, so one of the vertices must be dropped. Lets assume its vertex 0, so that the cache may contain vertices 1, 2, and 3 now. Next, vertex 0 is requested. Unfortunately we have dropped vertex 0 just before, so it need to be fetched again from memory, and need to be processed by the vertex program. Then it is store, so that the cache may contain vertices 2, 3, and 0.


Not totally related to the current question, but to another one of your threads: From the above you can see that another sequence of vertex indices, namely
{ 0, 1, 2, 0, 2, 3 }
would be better suited for this example, since there were no cache misses when rendering. Guaranteeing that this better suited order is available is just the job of the mentioned vertex index optimization. (Perhaps under consideration of other contraints, like CW ordering inside a triangle.)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement