Difference between revisions of "Code Snippets"
From Horde3D Wiki
(Snippets!) |
(Added example to help with custom OpenGL.) |
||
(3 intermediate revisions by one other user not shown) | |||
Line 4: | Line 4: | ||
---- | ---- | ||
+ | |||
+ | ===Using Custom GL Code After Horde3D=== | ||
+ | Horde3D has a bad habbit of messing with the OpenGL states after it is finished, so it is necessary with a few third party libraries to make sure that the OpenGL state is at its default settings before rendering. Here is an example using CEGUI. It is assumed you can logically piece together what the main loop would look like. | ||
+ | |||
+ | {{CppSourceCode| | ||
+ | description = Custom OpenGL after Horde3D.| | ||
+ | code = | ||
+ | <source lang="cpp" line ="1"> | ||
+ | void Engine::InitializeRenderer() | ||
+ | { | ||
+ | glPushAttrib(GL_ALL_ATTRIB_BITS); // save default attributes | ||
+ | |||
+ | LOG("Initializing rendering engine...",INFO); | ||
+ | if(!h3dInit()) | ||
+ | { | ||
+ | LOG("Error initializing Horde3D. Aborting.",FATAL); | ||
+ | Kill(); | ||
+ | } | ||
+ | LOG("Running the game.",INFO); | ||
+ | |||
+ | glClearDepth(1.f); | ||
+ | glClearColor(0.f, 0.f, 0.5f, 0.f); | ||
+ | glEnable(GL_DEPTH_TEST); | ||
+ | } | ||
+ | |||
+ | void Engine::FinalizeRenderer() | ||
+ | { | ||
+ | if(stage) | ||
+ | { | ||
+ | h3dRender(active_camera); | ||
+ | } | ||
+ | h3dFinalizeFrame(); | ||
+ | // attributes here are now messed up | ||
+ | } | ||
+ | |||
+ | void Engine::FinalizeGUI() | ||
+ | { | ||
+ | glPopAttrib(); // pop back to default state since horde3d messed with the states. | ||
+ | |||
+ | CEGUI::System::getSingleton().renderGUI(); | ||
+ | |||
+ | glPushAttrib(GL_ALL_ATTRIB_BITS); // save the default state again before going back to Horde3D | ||
+ | } | ||
+ | </source> | ||
+ | }} | ||
Line 9: | Line 54: | ||
The following is similar but different to the [[Procedurally generated geometry tutorial]] | The following is similar but different to the [[Procedurally generated geometry tutorial]] | ||
{{CppSourceCode| | {{CppSourceCode| | ||
− | description=Building a 2D grid of | + | description=Building a 2D grid of quads| |
code= | code= | ||
<source lang="cpp" line="1"> | <source lang="cpp" line="1"> | ||
Line 19: | Line 64: | ||
//This example splits the screen up into groups of 16 pixels, and create a quad for each group. | //This example splits the screen up into groups of 16 pixels, and create a quad for each group. | ||
int quadSize = 16; | int quadSize = 16; | ||
− | |||
int quadsH = (appWidth +quadSize-1) / quadSize;//divide by 16, rounding up | int quadsH = (appWidth +quadSize-1) / quadSize;//divide by 16, rounding up | ||
int quadsV = (appHeight+quadSize-1) / quadSize; | int quadsV = (appHeight+quadSize-1) / quadSize; | ||
Line 25: | Line 69: | ||
− | int version = 5; | + | int version = 5;//This is the current version of the GEO format (at the time of writing). |
− | int numJoints = 0;//I don't have code below for writing joints | + | |
+ | 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) | //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 = 8; | ||
− | int numVertexStreams = 2; | + | int numVertexStreams = 2;//I'm just using position + tex-coord |
− | int numVertices = quads * 4; | + | |
+ | 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. | ||
+ | |||
+ | //These are all "magic numbers" that horde uses to interpret the data streams | ||
int vertPositionID = 0; | int vertPositionID = 0; | ||
int vertNormalID = 1; | int vertNormalID = 1; | ||
Line 48: | Line 98: | ||
int texCoordElementSize = sizeof(float)*2; | int texCoordElementSize = sizeof(float)*2; | ||
int texCoord2ElementSize = sizeof(float)*2; | int texCoord2ElementSize = sizeof(float)*2; | ||
− | |||
− | |||
batchStart = 0; | batchStart = 0; | ||
Line 56: | Line 104: | ||
vertREnd = numVertices-1; | vertREnd = numVertices-1; | ||
− | //! int vertDataSize = positionElementSize+normalElementSize+tangentElementSize+biTangentElementSize+jointIndexElementSize+jointWeightElementSize+texCoordElementSize+texCoord2ElementSize; | + | //! int vertDataSize = positionElementSize+normalElementSize+ |
+ | //! tangentElementSize+biTangentElementSize+ | ||
+ | //! jointIndexElementSize+jointWeightElementSize+ | ||
+ | //! texCoordElementSize+texCoord2ElementSize; | ||
int vertDataSize = positionElementSize+texCoordElementSize; | int vertDataSize = positionElementSize+texCoordElementSize; | ||
Line 71: | Line 122: | ||
memcpy( &data[written], d, size ); written += size; ASSERT( written <= fileSize ); | memcpy( &data[written], d, size ); written += size; ASSERT( written <= fileSize ); | ||
+ | //First write the header | ||
WRITE_DATA( "H3DG", sizeof(char)*4 ); | WRITE_DATA( "H3DG", sizeof(char)*4 ); | ||
WRITE_DATA( &version, sizeof(int) ); | WRITE_DATA( &version, sizeof(int) ); | ||
+ | |||
+ | //Joint data would go here, if I had any | ||
WRITE_DATA( &numJoints, sizeof(int) ); | WRITE_DATA( &numJoints, sizeof(int) ); | ||
+ | |||
+ | //Then write the vertex-stream header | ||
WRITE_DATA( &numVertexStreams, sizeof(int) ); | WRITE_DATA( &numVertexStreams, sizeof(int) ); | ||
WRITE_DATA( &numVertices, sizeof(int) ); | WRITE_DATA( &numVertices, sizeof(int) ); | ||
Line 215: | Line 271: | ||
int dataSize = 0; | int dataSize = 0; | ||
char* data = 0; | char* data = 0; | ||
− | + | ScreenGridMesh( data, dataSize, batchStart, batchCount, vertRStart, vertREnd ); | |
bool loadedData = h3dLoadResource( gridGeo, data, dataSize ); | bool loadedData = h3dLoadResource( gridGeo, data, dataSize ); | ||
delete [] lensBlurData; | delete [] lensBlurData; |
Latest revision as of 20:55, 18 October 2010
What is this page?
This page of the wiki is a sharing zone for rough Horde example code.
Using Custom GL Code After Horde3D
Horde3D has a bad habbit of messing with the OpenGL states after it is finished, so it is necessary with a few third party libraries to make sure that the OpenGL state is at its default settings before rendering. Here is an example using CEGUI. It is assumed you can logically piece together what the main loop would look like.
Custom OpenGL after Horde3D. |
void Engine::InitializeRenderer()
{
glPushAttrib(GL_ALL_ATTRIB_BITS); // save default attributes
LOG("Initializing rendering engine...",INFO);
if(!h3dInit())
{
LOG("Error initializing Horde3D. Aborting.",FATAL);
Kill();
}
LOG("Running the game.",INFO);
glClearDepth(1.f);
glClearColor(0.f, 0.f, 0.5f, 0.f);
glEnable(GL_DEPTH_TEST);
}
void Engine::FinalizeRenderer()
{
if(stage)
{
h3dRender(active_camera);
}
h3dFinalizeFrame();
// attributes here are now messed up
}
void Engine::FinalizeGUI()
{
glPopAttrib(); // pop back to default state since horde3d messed with the states.
CEGUI::System::getSingleton().renderGUI();
glPushAttrib(GL_ALL_ATTRIB_BITS); // save the default state again before going back to Horde3D
} |
More procedurally generated content code
The following is similar but different to the Procedurally generated geometry tutorial
Building a 2D grid of quads |
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 quadsH = (appWidth +quadSize-1) / quadSize;//divide by 16, rounding up
int quadsV = (appHeight+quadSize-1) / quadSize;
int quads = quadsH*quadsV;
int version = 5;//This is the current version of the GEO format (at the time of writing).
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.
//These are all "magic numbers" that horde uses to interpret the data streams
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;
ScreenGridMesh( 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 ); |