Archived

This topic is now archived and is closed to further replies.

mimicing DX::"Flexible Vertex Format"

This topic is 5375 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

Hello! I''m trying to mimic the Flexible Vertex Format of DirectX. It''s when you write your own Vertex struct that has 3 floats for xyz and one float for diffuse, and just say to DX "I''ve used XYZ coords and (actually bitwise OR) DIFFUSE color info". Example from the SDK: // Lightweight, untransformed vertex for lit, untextured, // Gouraud-shaded content. dwFVF = ( D3DFVF_XYZ | D3DFVF_DIFFUSE ); I''d really like to make a struct that works kinda like that. I''m going for a creational method - "I want to specify XYZ and color". And I''ll get a struct with that and nothing else (so I don''t waste memory). Subclassing isn''t really an option here... since the combinations are to many Has anyone tried this? Or have any tuts/articles on it? I''m trying to do it in C++. It''s not gonna be used for vertices, but something similar. But in either case, it''s (according to myself) very educational? Thanx! "No lies of sugar can sweeten the sournes of reality" }+TITANIUM+{ A.K.A. DXnewbie[onMIRC]

Share this post


Link to post
Share on other sites
Ok.... gonna be long

What you can do is following : Dependent on a given structure description, you could create a memory buffer that has exactly the size you need.

It's quite similar to the VertexDeclarator in DirectX. To keep it a little bit shorter, I cut some of the possible member functions.

A structure to describe a flexible vertex format consists of different components of different size. There are : Position, Normal, Diffuse color, Specular color, texture coordinate, weight info etc etc.

So we define the different components of my structure :


enum EVertexComponent
{
EVC_UNKNOWN = 0,
EVC_POSITION,
EVC_NORMAL,
EVC_DIFFCOLOR,
...
};


Each of these components can contain a given number of floats, shorts and bytes, we have to find a structure that describes the link between the VertexComponent and the size of the data for this component.

So we define the different possible data sizes :


enum EVertexComponentType
{
EVCT_UNKNOWN = 0,
EVCT_FLOAT1,
EVCT_FLOAT2,
EVCT_FLOAT3,
EVCT_FLOAT4,
EVCT_COLOR,
...
};


Now that we have defined these two describing components, we have to create a structure that can contain any combination :


struct SVertexComponent
{
EVertexComponent m_eComponent;
EVertexComponentType m_eType;

// Constructor.
SVertexComponent( EVertexComponent _eComponent,
EVertexComponentType m_eType )
{
m_eComponent = _eComponent;
m_eType = _eType;
};

// Helper functions.
unsigned int GetComponentSize()
{
unsigned int uResult = 0;
switch ( m_eType )
{
case EVCT_FLOAT1:
{
uResult = sizeof(float);
break;
}
case EVCT_FLOAT2:
{
uResult = sizeof(float)*2;
break;
}
case EVCT_FLOAT3:
{
uResult = sizeof(float)*3;
break;
}
case EVCT_FLOAT4:
{
uResult = sizeof(float)*4;
break;
}

// etc etc etc
}

return uResult;
};
}


So far so good. This enables us to completely describe a flexible vertex format. We know have to create some kind of structure that can hold and create ie. a ShaderDeclarator (DirectX).

Such a structure can look like this :


struct SShaderDeclarator
{
unsigned int m_uNrComponents;
SVertexComponent *m_pComponents;

// Constructor.
SShaderDeclarator(unsigned int _uNrComponents, const SVertexComponent *m_pComponents )
{
// Copy the components.
};

// Functions.
unsigned int GetVertexSize()
{
unsigned int uResult = 0;
for ( unsigned int u=0 ; u < m_uNrComponents; u++ )
{
uResult += m_pComponents[u].GetComponentSize();
}

return uResult;
};
};


Voila, we have all we need. You can now use it like this :


SVertexComponent oComponents[3];
oComponents[0] = SVertexComponent( EVC_POSITION, EVCT_FLOAT3 );
oComponents[1] = SVertexComponent( EVC_NORMAL, EVCT_FLOAT3 );
oComponents[2] = SVertexComponent( EVC_TEXTURE, EVCT_FLOAT2 );

SShaderDeclarator oDeclarator( 3, oComponents );

// Get the size of one vertex.
unsigned int uVertexSize = oDeclarator.GetVertexSize();

// Create a buffer for 1000 vertices.
BYTE* pBuffer = new BYTE[uVertexSize*1000];


pBuffer has now exactly the size of 1000 vertices containing a position, a normal and a 2D texture coordinate.

You can now access it by accessing directly the buffer. The stride from one vertex to the next is the size of the vertex.

If you want to access the texture coordinates to alter them, you can do this (using the above example).


unsigned int uTextureOffset = oComponents[0].GetComponentSize() + oComponents[1].GetComponentSize();

float *pTextureCoords = (float*)&pBuffer[uTextureOffset];
pTextureCoords[0] = 0.001f;
pTextureCoords[1] = 0.005f;


You get the idea for the rest.

Kind regards,
Metron

[edited by - Metron on March 26, 2003 1:45:08 PM]

[edited by - Metron on March 26, 2003 1:48:50 PM]

Share this post


Link to post
Share on other sites
Hi there!

Thanx for the quick responce! :D I''ll be reading it again tomorrow, just gave it a quick look tonight.

I got the "creation" part kinda figuered out, but I thought I''d be using std::vector<> since it can work kinda lika a memory pool.

It''s the "using" part that has me pondering. Think of a Update() for a struct that has that flexible members. It would be one big switch() for everything, right?.. Every frame, every particle (let''s say 1000particles). That''s alot of switching... Is that a performance loss I''ll be noticing?

"No lies of sugar can sweeten the sournes of reality"

}+TITANIUM+{ A.K.A. DXnewbie[onMIRC]

Share this post


Link to post
Share on other sites
The question is : In what kind your structures will they be flexible and would you want them to change on every frame ?

The problem you see is : If I want to change the position, the coloring and the texture coordinate of every single particle in my system, I''ll have to determine on every frame for every particle how to access the data.

The answer is : NO, you haven''t.

First of all, you should only put into one buffer particles that have the same structure (ie. position, color, texture). Like that you can be sure that DirectX or OpenGL can make use of vertexbuffer efficiently. Trying to put different particle structures into the same buffer simply doesn''t work.

Once you''ve realized this, you can imagine a system that holds the offset parameters for the parts you want to change.

Changing the data is then quite simple : To jump from one vertex to the next, just add the vertex stride (GetVertexSize()). This can be calculated when you create your particle system so that you don''t do it on every frame. I''m not gonna do your work (since you want to learn something) but it could look like this :


Init()
{
// Create components list and shader declarator

// Get the vertex size and store it in a member var
m_uVertexStride = m_pDecl->GetVertexSize();

// Calculate the offset to the parts to influence.
// Set not to change part offsets to some kind of
// NO_CHANGE_VALUE (ie. 0xffffffff)
m_uPosOffset = 0; // <- Always 0 !!!
m_uColorOffset = m_oComponents[0].GetComponentSize();
m_uTextureOffset = NO_CHANGE_VALUE;
}

Update()
{
BYTE* pRover = m_pData;
int iCount = 0;
while ( iCount < m_uVertices )
{
// Influence position ?
if ( NO_CHANGE_VALUE != m_uPosOffset )
{
// Change the position.
}

// Influence the color ?
if ( NO_CHANGE_VALUE != m_uColorOffset )
{
// Calculate the data pointer.
DWORD *pColorData = pRover+m_uColorOffset;

// Change the color.
*PColorData = 0xffff0000;
}

// All other changeable parts...
// ...
// ...

// Go to next vertex.
pRover += m_uVertexStride;
iCount++;
}
}


This should be quite fast and not to hard to implement ( did the above out of my head ). BTW you will more likely notice the push of the data into a vertex buffer and the actual rendering than the update of your particles (unless you have some really weired physics going on; we had implemented particles influenced by wind and other physics and didn''t notice any big performance hit).

Kind regards,
Metron

Share this post


Link to post
Share on other sites