Code Snippets
From Horde3D Wiki
What is this page?
This page of the wiki is a sharing zone for rough Horde example code.
More procedurally generated content code
The following is similar but different to the Procedurally generated geometry tutorial
Building a 2D grid of points |
void ScreenGridMesh( char*& data, int& fileSize, int& batchStart, int& batchCount, int& vertRStart, int& vertREnd )
{
extern int appWidth;
extern int appHeight;
//This example splits the screen up into groups of 16 pixels, and create a quad for each group.
int quadSize = 16;
int quadSizeHalf = quadSize/2;
int quadsH = (appWidth +quadSize-1) / quadSize;//divide by 16, rounding up
int quadsV = (appHeight+quadSize-1) / quadSize;
int quads = quadsH*quadsV;
int version = 5;
int numJoints = 0;//I don't have code below for writing joints...
int numMorphTargets = 0;//...or morph targets
//The lines that begin with //! or /*! could be used if you want a more complete vertex format (i.e. normal/binormal/tangent/joints/etc)
//! int numVertexStreams = 8;
int numVertexStreams = 2;//I'm just using position + tex-coord
int numVertices = quads * 4;// I'm making 4 verts per quad
int numTriangleIndices = quads * 6;//Each quad is 2 triangles. Each triangle is made up of 3 verts, so I need 6 indices to describe each quad.
int vertPositionID = 0;
int vertNormalID = 1;
int vertTangentID = 2;
int vertBiTangentID = 3;
int vertJointIndexID = 4;
int vertJointWeightID = 5;
int vertTexCoordID = 6;
int vertTexCoord2ID = 7;
int positionElementSize = sizeof(float)*3;
int normalElementSize = sizeof(short)*3;
int tangentElementSize = sizeof(short)*3;
int biTangentElementSize= sizeof(short)*3;
int jointIndexElementSize = sizeof(char)*4;
int jointWeightElementSize = sizeof(char)*4;
int texCoordElementSize = sizeof(float)*2;
int texCoord2ElementSize = sizeof(float)*2;
batchStart = 0;
batchCount = numTriangleIndices;
vertRStart = 0;
vertREnd = numVertices-1;
//! int vertDataSize = positionElementSize+normalElementSize+
tangentElementSize+biTangentElementSize+
jointIndexElementSize+jointWeightElementSize+
texCoordElementSize+texCoord2ElementSize;
int vertDataSize = positionElementSize+texCoordElementSize;
int quadDataSize = vertDataSize*4 + sizeof(int)*6;
//! fileSize = sizeof(char)*4 + sizeof(int)*22 + quadDataSize*quads;
fileSize = sizeof(char)*4 + sizeof(int)*10 + quadDataSize*quads;
data = new char[fileSize];
int written = 0;
#define ASSERT( c ) \
if( !(c) ) { printf( "ASSERTION FAILED: %s\n", #c ); breakPlz(); }
#define WRITE_DATA( d, size ) \
memcpy( &data[written], d, size ); written += size; ASSERT( written <= fileSize );
//First write the header
WRITE_DATA( "H3DG", sizeof(char)*4 );
WRITE_DATA( &version, sizeof(int) );
//Joint data would go here, if I had any
WRITE_DATA( &numJoints, sizeof(int) );
//Then write the vertex-stream header
WRITE_DATA( &numVertexStreams, sizeof(int) );
WRITE_DATA( &numVertices, sizeof(int) );
//I'm making quads in this example, so all my loops are going to create 4 pieces of each data.
//To begin with I write the positions:
WRITE_DATA( &vertPositionID, sizeof(int) );
WRITE_DATA( &positionElementSize, sizeof(int) );
for( int y=0; y<quadsV; ++y )
{
for( int x=0; x<quadsH; ++x )
{
float positionA[3] = { ((x+0.0f)/(float)quadsH)*2.0f-1.0f, ((y+0.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
float positionB[3] = { ((x+1.0f)/(float)quadsH)*2.0f-1.0f, ((y+0.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
float positionC[3] = { ((x+1.0f)/(float)quadsH)*2.0f-1.0f, ((y+1.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
float positionD[3] = { ((x+0.0f)/(float)quadsH)*2.0f-1.0f, ((y+1.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
WRITE_DATA( positionA, sizeof(float)*3 );
WRITE_DATA( positionB, sizeof(float)*3 );
WRITE_DATA( positionC, sizeof(float)*3 );
WRITE_DATA( positionD, sizeof(float)*3 );
}
}
/*!
//Normals/binormals/tangents should be floats in the 0-1 range, and then multiplied by 32767 and cast to 'short'. This is a form of compression.
WRITE_DATA( &vertNormalID, sizeof(int) );
WRITE_DATA( &normalElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
short n[] = { 0, 0, 32767 };
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
}
WRITE_DATA( &vertTangentID, sizeof(int) );
WRITE_DATA( &tangentElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
short n[] = { 0, 32767, 0 };
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
}
WRITE_DATA( &vertBiTangentID, sizeof(int) );
WRITE_DATA( &biTangentElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
short n[] = { 32767, 0, 0 };
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
WRITE_DATA( n, sizeof(short)*3 );
}
//Each vertex can be influenced by 4 joints - the joint IDs are written here
WRITE_DATA( &vertJointIndexID, sizeof(int) );
WRITE_DATA( &jointIndexElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
char j[] = { 0, 0, 0, 0 };
WRITE_DATA( j, sizeof(char)*4 );
WRITE_DATA( j, sizeof(char)*4 );
WRITE_DATA( j, sizeof(char)*4 );
WRITE_DATA( j, sizeof(char)*4 );
}
//The 'percent' (out of 255, not out of 100) that each of the above joints influences the vertex:
WRITE_DATA( &vertJointWeightID, sizeof(int) );
WRITE_DATA( &jointWeightElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
ASSERT( sizeof(char) == 1 )
char j[] = { 255, 0, 0, 0 };
WRITE_DATA( j, sizeof(char)*4 );
WRITE_DATA( j, sizeof(char)*4 );
WRITE_DATA( j, sizeof(char)*4 );
WRITE_DATA( j, sizeof(char)*4 );
}
*/
//Tex-coords are pairs of floats
WRITE_DATA( &vertTexCoordID, sizeof(int) );
WRITE_DATA( &texCoordElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
float uvTl[] = { 0.0f, 1.0f };
float uvBl[] = { 0.0f, 0.0f };
float uvBr[] = { 1.0f, 0.0f };
float uvTr[] = { 1.0f, 1.0f };
WRITE_DATA( uvTl, sizeof(float)*2 );
WRITE_DATA( uvBl, sizeof(float)*2 );
WRITE_DATA( uvBr, sizeof(float)*2 );
WRITE_DATA( uvTr, sizeof(float)*2 );
}
/*!
//You can have a second set of tex-coords if you want
WRITE_DATA( &vertTexCoord2ID, sizeof(int) );
WRITE_DATA( &texCoord2ElementSize, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
float uvTl[] = { 0.0f, 1.0f };
float uvBl[] = { 0.0f, 0.0f };
float uvBr[] = { 1.0f, 0.0f };
float uvTr[] = { 1.0f, 1.0f };
WRITE_DATA( uvTl, sizeof(float)*2 );
WRITE_DATA( uvBl, sizeof(float)*2 );
WRITE_DATA( uvBr, sizeof(float)*2 );
WRITE_DATA( uvTr, sizeof(float)*2 );
}*/
//Finally, time for the index buffer
WRITE_DATA( &numTriangleIndices, sizeof(int) );
for( int i=0; i!=quads; ++i )
{
int base = i * 4;
int a = base, b = base+1, c = base+2, d=base+2, e=base+3, f=base;
WRITE_DATA( &a, sizeof(int) );
WRITE_DATA( &b, sizeof(int) );
WRITE_DATA( &c, sizeof(int) );
WRITE_DATA( &d, sizeof(int) );
WRITE_DATA( &e, sizeof(int) );
WRITE_DATA( &f, sizeof(int) );
}
//Morph targets would go here, if I had any
WRITE_DATA( &numMorphTargets, sizeof(int) );
ASSERT( written == fileSize );//ensure we didn't over/under-use the buffer
} |
Example Usage |
// Build a geo
H3DRes gridGeo = h3dAddResource( H3DResTypes::Geometry, "runtime/blahBlah.geo", H3DResFlags::NoQuery );
int batchStart = 0, batchCount = 0, vertRStart = 0, vertREnd = 0;
{
int dataSize = 0;
char* data = 0;
BuildLensBlurMesh( data, dataSize, batchStart, batchCount, vertRStart, vertREnd );
bool loadedData = h3dLoadResource( gridGeo, data, dataSize );
delete [] lensBlurData;
}
// Load a material
H3DRes material = h3dAddResource( H3DResTypes::Material, "materials/grid.material.xml", 0 );
h3dutLoadResourcesFromDisk( _contentDir.c_str() );
// Create a model/mesh from the procedural geo
H3DNode model = h3dAddModelNode( H3DRootNode, "MyModel", gridGeo );
H3DNode mesh = h3dAddMeshNode( model, "MyMesh", material, batchStart, batchCount, vertRStart, vertREnd ); |