@ Ian T I have the source but it has been converted to gdk. I no longer have the dbp source as I have pretty much scrapped that project in favor of a different terrain system anyways you can salvage the project for this code. Just convert it back to dbp code and it will work great for you.
#include "Project Terrain_dba.h"
//***** Definitions ***********************************************************
// ===========
//***** Constants *************************************************************
// =========
//***** Structures ************************************************************
// ==========
//***** Functions *************************************************************
// =========
int __main__ ();
void updatenormals ( int index );
void update_ground ( int obj, float obj_pos_x_flt, float obj_pos_z_flt );
float get_ground_y ( float cx_flt, float cy_flt, int memblock );
void smooth_normals ( int xx, int percent );
int make_memblock_grid ( int id, float x_width_flt, float z_width_flt, int x_segments, int z_segments );
int make_memblock_triangle ( int id, int mem_start, float xpos1_flt, float ypos1_flt, float zpos1_flt, float xpos2_flt, float ypos2_flt, float zpos2_flt, float xpos3_flt, float ypos3_flt, float zpos3_flt, int u1, int v1, int u2, int v2, int u3, int v3 );
int make_memblock_meshheader ( int id, int numverts );
//***** Variables *************************************************************
// =========
int mem_location = 0;
int mem_pos = 0;
//***** '__main__' ************************************************************
//+**** ========== ************************************************************
int __main__ ()
{
float start_time_flt = 0;
int sw = 0;
int sh = 0;
int columnsx = 0;
int rowsz = 0;
int height_map = 0;
int color_map = 0;
int detail_map = 0;
int p_x = 0;
int p_z = 0;
float floatheightvalue_flt = 0;
int s = 0;
float floatheightvalue1_flt = 0;
float floatheightvalue2_flt = 0;
float floatheightvalue3_flt = 0;
float floatheightvalue4_flt = 0;
float height_flt = 0;
int v = 0;
int chunk = 0;
float contrast_flt = 0;
float vertscale_flt = 0;
int xx = 0;
int x = 0;
int z = 0;
int a = 0;
int land_scale = 0;
float load_time_flt = 0;
// Project: Project Terrain
// Created: 1/1/2008 6:12:51 PM
// ***** Main Source File *****
start_time_flt = dbTimer();
//set display mode 1280,1024,32
dbLoadDLL( (char *)( (string)"user32.dll" ).c_str(), 1 );
sw = dbCallDLL_( 1, (char *)( (string)"GetSystemMetrics" ).c_str(), 0 );
sh = dbCallDLL_( 1, (char *)( (string)"GetSystemMetrics" ).c_str(), 1 );
dbDeleteDLL( 1 );
dbSetDisplayMode( sw, sh, 32, 0 );
dbSetGlobalCollisionOff();
dbSetNormalizationOn();
dbSyncOn();
dbSyncRate( 60 );
columnsx = 1000;
rowsz = 1000;
height_map = 200;
color_map = 201;
detail_map = 400;
dbLoadImage( (char *)( (string)"detail.tga" ).c_str(), detail_map );
dbLoadImage( (char *)( (string)"map.png" ).c_str(), height_map );
dbLoadImage( (char *)( (string)"color.png" ).c_str(), color_map );
//load image "heightmap.png", height_map
//load image "colormap.png", color_map
dbMakeMemblockFromImage( height_map, height_map );
dbMakeMemblock( 100, columnsx * rowsz * 4 );
// set initial height value
for ( p_x = 0; p_x <= 999; p_x++ ) {
for ( p_z = 0; p_z <= 999; p_z++ ) {
//read value from byte heightmap
floatheightvalue_flt = get_ground_y( p_x, p_z, 200 );
//write intropolated value to float memblock
dbWriteMemblockFloat( 100, ( p_x + ( columnsx * p_z ) ) * 4, floatheightvalue_flt );
}
}
// smooth float memblock terrain heights
for ( p_x = 1; p_x <= 998; p_x++ ) {
for ( p_z = 1; p_z <= 998; p_z++ ) {
for ( s = 1; s <= 2; s++ ) {
//get for heights and interpolate the values
floatheightvalue1_flt = dbMemblockFloat( 100, ( p_x + 1 + ( columnsx * p_z ) ) * 4 );
floatheightvalue2_flt = dbMemblockFloat( 100, ( p_x + ( columnsx * p_z - 1 ) ) * 4 );
floatheightvalue3_flt = dbMemblockFloat( 100, ( p_x - 1 + ( columnsx * p_z ) ) * 4 );
floatheightvalue4_flt = dbMemblockFloat( 100, ( p_x + ( columnsx * p_z + 1 ) ) * 4 );
height_flt = ( floatheightvalue1_flt + floatheightvalue2_flt + floatheightvalue3_flt + floatheightvalue4_flt ) / 4.0;
//write new values to memblock
dbWriteMemblockFloat( 100, ( p_x + ( columnsx * p_z ) ) * 4, height_flt );
}
}
}
// return value is size of memblock in bytes, params are object ID,x width, z width, x units, z units
mem_pos = make_memblock_grid( 1, 100, 100, 10, 10 );
//convert back to dbp native 274 format as this will give an overall speed gain
dbConvertObjectFVF( 1, 274 );
v = dbMakeVector4( 11 );
dbLoadEffect( (char *)( (string)"GG Blended Bump Mapping Shader v4.fx" ).c_str(), 1, 0 );
dbLoadImage( (char *)( (string)"grass1.png" ).c_str(), 301 );
dbLoadImage( (char *)( (string)"rocky_cliff_t.png" ).c_str(), 302 );
dbLoadImage( (char *)( (string)"sand1.png" ).c_str(), 303 );
dbLoadImage( (char *)( (string)"gravel1.png" ).c_str(), 304 );
dbLoadImage( (char *)( (string)"RoadMap.png" ).c_str(), 305 );
dbLoadImage( (char *)( (string)"sandstone.png" ).c_str(), 306 );
chunk = 1;
dbTextureObject( chunk, 0, 301 ); // first detail map
dbTextureObject( chunk, 1, 302 ); // second detail map
dbTextureObject( chunk, 2, 303 ); // third detail map
dbTextureObject( chunk, 3, 304 ); // fourth detail map
dbTextureObject( chunk, 4, 305 ); // first normal map
dbTextureObject( chunk, 5, 306 ); // second normal map
dbSetObjectEffect( chunk, 1 );
contrast_flt = 2.0;
vertscale_flt = 0.014;
dbSetEffectConstantFloat( 1, (char *)( (string)"contrast" ).c_str(), contrast_flt );
dbSetEffectConstantFloat( 1, (char *)( (string)"vertScale" ).c_str(), vertscale_flt );
dbSetVector4( 11, 14, 14, 1, 1 );
dbSetEffectConstantVector( 1, (char *)( (string)"UVTiling" ).c_str(), 11 );
//make and position the limbs for the mesh
for ( xx = 100; xx <= 199; xx++ ) {
dbCloneObject( xx, 1, 1 );
dbPositionObject( xx, x, 0, z );
x += 100;
// ERROR : 'if x => 1000'
x = 0;
z += 100;
}
// set normals and height data
update_ground( xx, dbObjectPositionX( xx ), dbObjectPositionZ( xx ) );
//set object normals xx
updatenormals( xx );
smooth_normals( xx, 50 );
//Set Blend Mapping On xx, 0, color_map, 0,2
//Set Blend Mapping On xx, 1, detail_map, 0,4
}
//delete unused object
dbDeleteObject( 1 );
//convert to multi-limb mesh object
for ( xx = 101; xx <= 199; xx++ ) {
dbMakeMeshFromObject( xx, xx );
a = a + 1;
dbAddLimb( 100, a, xx );
dbOffsetLimb( 100, a, dbObjectPositionX( xx ), 0, dbObjectPositionZ( xx ) );
dbDeleteObject( xx );
dbDeleteMesh( xx );
}
chunk = 100;
dbTextureObject( chunk, 0, 301 ); // first detail map
dbTextureObject( chunk, 1, 302 ); // second detail map
dbTextureObject( chunk, 2, 303 ); // third detail map
dbTextureObject( chunk, 3, 304 ); // fourth detail map
dbTextureObject( chunk, 4, 305 ); // first normal map
dbTextureObject( chunk, 5, 306 ); // second normal map
dbSetObjectEffect( chunk, 1 );
contrast_flt = 2.0;
vertscale_flt = 0.014;
dbSetEffectConstantFloat( 1, (char *)( (string)"contrast" ).c_str(), contrast_flt );
dbSetEffectConstantFloat( 1, (char *)( (string)"vertScale" ).c_str(), vertscale_flt );
dbSetVector4( 11, 14, 14, 1, 1 );
dbSetEffectConstantVector( 1, (char *)( (string)"UVTiling" ).c_str(), 11 );
land_scale = 1;
dbScaleObject( 100, land_scale * 100, land_scale * 100, land_scale * 100 );
dbSetObjectRadius( 100, -1 );
//Set Blend Mapping On 100,0, color_map, 0,2
//Set Blend Mapping On 100,1, detail_map, 0,4
dbPositionCamera( 100, 0, 100 );
load_time_flt = dbTimer() - start_time_flt;
while ( 1 ) {
dbControlCameraUsingArrowKeys( 0, 2, 4 );
dbText( 0, 0, (char *)( (string)"Use Arrow Keys to Move" ).c_str() );
dbText( 0, 10, (char *)( (string)"Total Polys on screen: " + __db_str( dbStr( dbStatistic( 1 ) ) ) ).c_str() );
dbText( 0, 20, (char *)( (string)"FPS: " + __db_str( dbStr( dbScreenFPS() ) ) ).c_str() );
dbText( 0, 30, (char *)( (string)"Cam X Pos: " + __db_str( dbStr( p_x ) ) ).c_str() );
dbText( 0, 40, (char *)( (string)"Cam Y Pos: " + __db_str( dbStr( height_flt ) ) ).c_str() );
dbText( 0, 50, (char *)( (string)"Cam Z Pos: " + __db_str( dbStr( p_z ) ) ).c_str() );
dbText( 0, 60, (char *)( (string)"Load time: " + __db_str( dbStr( load_time_flt ) ) ).c_str() );
dbText( 0, 70, (char *)( (string)"Space Key = sync rate 0: " ).c_str() );
dbText( 0, 80, (char *)( (string)"Shift Key = sync rate 60: " ).c_str() );
if ( dbSpaceKey() == 1 ) {
dbSyncRate( 0 );
}
if ( dbShiftKey() == 1 ) {
dbSyncRate( 60 );
}
p_x = dbCameraPositionX() / land_scale;
p_z = dbCameraPositionZ() / land_scale;
if ( p_x > 0 && p_x < 1000 ) {
if ( p_z > 0 && p_z < 1000 ) {
floatheightvalue1_flt = dbMemblockFloat( 100, ( p_x + 3 + ( columnsx * p_z ) ) * 4 );
floatheightvalue2_flt = dbMemblockFloat( 100, ( p_x + ( columnsx * p_z - 3 ) ) * 4 );
floatheightvalue3_flt = dbMemblockFloat( 100, ( p_x - 3 + ( columnsx * p_z ) ) * 4 );
floatheightvalue4_flt = dbMemblockFloat( 100, ( p_x + ( columnsx * p_z + 3 ) ) * 4 );
height_flt = ( floatheightvalue1_flt + floatheightvalue2_flt + floatheightvalue3_flt + floatheightvalue4_flt ) / 4.0;
height_flt = height_flt * land_scale;
}
}
dbPositionCamera( dbCameraPositionX(), height_flt + 10, dbCameraPositionZ() );
dbFastSync();
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//`memblock mesh creation
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
return 0;
}
//***** 'updatenormals' *******************************************************
//+**** =============== *******************************************************
void updatenormals ( int index )
{
int limb = 0;
int j = 0;
float p1x_flt = 0;
float p1y_flt = 0;
float p1z_flt = 0;
float p2x_flt = 0;
float p2y_flt = 0;
float p2z_flt = 0;
float p3x_flt = 0;
float p3y_flt = 0;
float p3z_flt = 0;
int null = 0;
float tempnormx_flt = 0;
float tempnormy_flt = 0;
float tempnormz_flt = 0;
limb = 0;
dbLockVertexDataForLimb( index, limb, 2 );
for ( j = 0; ( ( 3 ) > 0 ) ? ( j <= dbGetVertexDataVertexCount() - 1 ) : ( j >= dbGetVertexDataVertexCount() - 1 ); j += 3 ) {
//acuire vert positions
p1x_flt = dbGetVertexDataPositionX( j );
p1y_flt = dbGetVertexDataPositionY( j );
p1z_flt = dbGetVertexDataPositionZ( j );
p2x_flt = dbGetVertexDataPositionX( j + 1 );
p2y_flt = dbGetVertexDataPositionY( j + 1 );
p2z_flt = dbGetVertexDataPositionZ( j + 1 );
p3x_flt = dbGetVertexDataPositionX( j + 2 );
p3y_flt = dbGetVertexDataPositionY( j + 2 );
p3z_flt = dbGetVertexDataPositionZ( j + 2 );
null = dbMakeVector3( 1 );
null = dbMakeVector3( 2 );
null = dbMakeVector3( 3 );
// -- calculate the two directional vectors for the adj and opp edges...
dbSetVector3( 1, p1x_flt, p1y_flt, p1z_flt );
dbSetVector3( 2, p2x_flt, p2y_flt, p2z_flt );
dbSetVector3( 3, p3x_flt, p3y_flt, p3z_flt );
dbSubtractVector3( 2, 2, 1 );
dbSubtractVector3( 3, 3, 1 ); // -- vector 3 and 1 are now directional vectors
dbNormalizeVector3( 2, 2 ); // -- normalize em
dbNormalizeVector3( 3, 3 );
dbCrossProductVector3( 1, 2, 3 ); // -- use the origin vector (1) to store the face normal
dbNormalizeVector3( 1, 1 );
//save normals (all 3 verts have same normals)
tempnormx_flt = dbXVector3( 1 );
tempnormy_flt = dbYVector3( 1 );
tempnormz_flt = dbZVector3( 1 );
null = dbDeleteVector3( 1 );
null = dbDeleteVector3( 2 );
null = dbDeleteVector3( 3 );
dbSetVertexDataNormals( j, tempnormx_flt, tempnormy_flt, tempnormz_flt );
dbSetVertexDataNormals( j + 1, tempnormx_flt, tempnormy_flt, tempnormz_flt );
dbSetVertexDataNormals( j + 2, tempnormx_flt, tempnormy_flt, tempnormz_flt );
}
dbUnlockVertexData();
}
//***** 'update_ground' *******************************************************
//+**** =============== *******************************************************
void update_ground ( int obj, float obj_pos_x_flt, float obj_pos_z_flt )
{
int image_size = 0;
int memblock = 0;
int limb = 0;
int a = 0;
float x_flt = 0;
float z_flt = 0;
float ground_x_flt = 0;
float ground_z_flt = 0;
float height_flt = 0;
int p_x = 0;
int p_z = 0;
int columnsx = 0;
float floatheightvalue1_flt = 0;
float floatheightvalue2_flt = 0;
float floatheightvalue3_flt = 0;
float floatheightvalue4_flt = 0;
float u_data_flt = 0;
float v_data_flt = 0;
float u_data_old_flt = 0;
float v_data_old_flt = 0;
image_size = dbGetImageWidth( 200 );
memblock = 200;
limb = 0;
dbLockVertexDataForLimb( obj, limb, 2 );
for ( a = 0; a <= dbGetVertexDataVertexCount() - 1; a++ ) {
x_flt = dbGetVertexDataPositionX( a ) + obj_pos_x_flt;
z_flt = dbGetVertexDataPositionZ( a ) + obj_pos_z_flt;
ground_x_flt = x_flt;
ground_z_flt = z_flt;
// set the initial height
height_flt = get_ground_y( ground_x_flt, ground_z_flt, memblock );
// now set the smoothing height
p_x = int( ground_x_flt );
p_z = int( ground_z_flt );
columnsx = 1000;
if ( p_x > 0 && p_x < 1000 ) {
if ( p_z > 0 && p_z < 1000 ) {
floatheightvalue1_flt = dbMemblockFloat( 100, ( p_x + 1 + ( columnsx * p_z ) ) * 4 );
floatheightvalue2_flt = dbMemblockFloat( 100, ( p_x + ( columnsx * p_z - 1 ) ) * 4 );
floatheightvalue3_flt = dbMemblockFloat( 100, ( p_x - 1 + ( columnsx * p_z ) ) * 4 );
floatheightvalue4_flt = dbMemblockFloat( 100, ( p_x + ( columnsx * p_z + 1 ) ) * 4 );
height_flt = ( floatheightvalue1_flt + floatheightvalue2_flt + floatheightvalue3_flt + floatheightvalue4_flt ) / 4.0;
}
}
dbSetVertexDataPosition( a, dbGetVertexDataPositionX( a ), height_flt, dbGetVertexDataPositionZ( a ) );
u_data_flt = x_flt / image_size;
v_data_flt = z_flt / image_size;
u_data_old_flt = dbGetVertexDataU( a );
v_data_old_flt = dbGetVertexDataV( a );
dbSetVertexDataUV( a, 0, u_data_flt, v_data_flt );
dbSetVertexDataUV( a, 1, u_data_old_flt, v_data_old_flt );
}
dbUnlockVertexData();
//recaculate dbp view fustrum bounds
dbCalculateObjectBounds( obj );
}
//***** 'get_ground_y' ********************************************************
//+**** ============== ********************************************************
float get_ground_y ( float cx_flt, float cy_flt, int memblock )
{
int image_size = 0;
int off_set = 0;
int cx = 0;
int cy = 0;
float posy_flt = 0;
int mem_y = 0;
int mem_x = 0;
float pos1_flt = 0;
float pos2_flt = 0;
float pos3_flt = 0;
float pos4_flt = 0;
image_size = dbGetImageWidth( 200 );
off_set = 3;
cx = int( cx_flt );
cy = int( cy_flt );
// this checks to see if the location is outside the memory bounds and if it is, returns a dummy position
// ERROR : 'if cx <= off_set or cy <= off_set or cx => image_size-off_set or cy => image_size-off_set'
posy_flt = 0;
}
else {
// works out where in memory to plot left position
mem_y = int( cy ) * ( image_size * 4 );
mem_x = ( int( cx + off_set ) * 4 );
mem_location = mem_x + mem_y;
// this reads the heightmap and gets the appropiate number
pos1_flt = dbMemblockByte( memblock, mem_location );
// works out where in memory to plot behind position x+1,y
mem_y = int( cy - off_set ) * ( image_size * 4 );
mem_x = ( int( cx ) * 4 );
mem_location = mem_x + mem_y;
// this reads the heightmap and gets the appropiate number
pos2_flt = dbMemblockByte( memblock, mem_location );
// works out where in memory to plot right position x,y+1
mem_y = int( cy ) * ( image_size * 4 );
mem_x = ( int( cx - off_set ) * 4 );
mem_location = mem_x + mem_y;
// this reads the heightmap and gets the appropiate number
pos3_flt = dbMemblockByte( memblock, mem_location );
// works out where in memory to plot foward position x+1,y+1
mem_y = int( cy + off_set ) * ( image_size * 4 );
mem_x = ( int( cx ) * 4 );
mem_location = mem_x + mem_y;
// this reads the heightmap and gets the appropiate number
pos4_flt = dbMemblockByte( memblock, mem_location );
//smooth the heights
posy_flt = ( pos1_flt + pos2_flt + pos3_flt + pos4_flt ) / 4.0;
}
return posy_flt;
}
//***** 'smooth_normals' ******************************************************
//+**** ================ ******************************************************
void smooth_normals ( int xx, int percent )
{
int limb = 0;
int a = 0;
dbSetObjectSmoothing( xx, percent );
limb = 0;
dbLockVertexDataForLimb( xx, limb, 2 );
for ( a = 0; a <= dbGetVertexDataVertexCount() - 1; a++ ) {
dbSetVertexDataNormals( a, dbGetVertexDataNormalsX( a ), dbGetVertexDataNormalsY( a ), dbGetVertexDataNormalsZ( a ) );
}
dbUnlockVertexData();
}
//***** 'make_memblock_grid' **************************************************
//+**** ==================== **************************************************
int make_memblock_grid ( int id, float x_width_flt, float z_width_flt, int x_segments, int z_segments )
{
float unitwidth_flt = 0;
float unitheight_flt = 0;
float xpos_flt = 0;
float ypos_flt = 0;
float zpos_flt = 0;
int j = 0;
int total_polys = 0;
int total_verts = 0;
int memsize = 0;
int last_mem_pos = 0;
int i = 0;
unitwidth_flt = x_width_flt / x_segments;
unitheight_flt = z_width_flt / z_segments;
xpos_flt = 0;
ypos_flt = 0;
zpos_flt = 0;
j = 1;
// calculate the size of the memblock we are going to need
total_polys = ( x_segments * z_segments ) * 2;
total_verts = total_polys * 3;
memsize = ( total_verts * 20 ) + 12;
// make a memblock of a size = memsize
dbMakeMemblock( 1, memsize );
// create the memblock header, which defines the FVF being used, in this case 338(mesh data,normals data, diffuse color, uv coords)
last_mem_pos = make_memblock_meshheader( 1, total_verts );
// call the make_memblock_triangle function and place the triangles
// first, it creates one triangle with the verts drawn from lower left, upper left, and lower right
// second, it creates the next triangle with the verts from upper left, upper right, and lower right
// then it just loops through drawing triangles until it reachs the x unit count, resets the I incrementer to startover
// and increments the zpos to start a new row of triangles
// change the RGB values above for different colors
for ( i = 1; i <= x_segments; i++ ) {
last_mem_pos = make_memblock_triangle( 1, last_mem_pos, xpos_flt, ypos_flt, zpos_flt, xpos_flt, ypos_flt, zpos_flt + unitheight_flt, xpos_flt + unitwidth_flt, ypos_flt, zpos_flt, 0, 1, 0, 0, 1, 1 );
last_mem_pos = make_memblock_triangle( 1, last_mem_pos, xpos_flt, ypos_flt, zpos_flt + unitheight_flt, xpos_flt + unitwidth_flt, 0, zpos_flt + unitheight_flt, xpos_flt + unitwidth_flt, ypos_flt, zpos_flt, 0, 0, 1, 0, 1, 1 );
xpos_flt += unitwidth_flt;
if ( j < z_segments ) {
if ( i == x_segments ) {
j += 1;
zpos_flt += unitheight_flt;
xpos_flt = 0;
i = 0;
}
}
}
dbMakeMeshFromMemblock( 1, 1 );
dbDeleteMemblock( 1 );
dbMakeObject( id, 1, 0 );
dbDeleteMesh( 1 );
return last_mem_pos;
}
//***** 'make_memblock_triangle' **********************************************
//+**** ======================== **********************************************
int make_memblock_triangle ( int id, int mem_start, float xpos1_flt, float ypos1_flt, float zpos1_flt, float xpos2_flt, float ypos2_flt, float zpos2_flt, float xpos3_flt, float ypos3_flt, float zpos3_flt, int u1, int v1, int u2, int v2, int u3, int v3 )
{
int a = 0;
a = mem_start;
// mesh data format, each block is one vertice, three blocks is a triangle
// we could probably get fancy here and do some loops, but I think this is more readable
// we are just writing the values needed for each vertice in a triangle, into the memblock
// location. Every memblock position for this format takes up 4 bytes, so after every write, we just
// increment the memblock position by 4
// vertice 1
dbWriteMemblockFloat( id, a, xpos1_flt );
a += 4; // x pos of triangle
dbWriteMemblockFloat( id, a, ypos1_flt );
a += 4; // y pos of triangle
dbWriteMemblockFloat( id, a, zpos1_flt );
a += 4; // z pos of triangle
dbWriteMemblockFloat( id, a, u1 );
a += 4; // u
dbWriteMemblockFloat( id, a, v1 );
a += 4; // v
// vertice 2
dbWriteMemblockFloat( id, a, xpos2_flt );
a += 4; // x pos of triangle
dbWriteMemblockFloat( id, a, ypos2_flt );
a += 4; // y pos of triangle
dbWriteMemblockFloat( id, a, zpos2_flt );
a += 4; // z pos of triangle
dbWriteMemblockFloat( id, a, u2 );
a += 4; // u
dbWriteMemblockFloat( id, a, v2 );
a += 4; // v
// vertice 3
dbWriteMemblockFloat( id, a, xpos3_flt );
a += 4; // x pos of triangle
dbWriteMemblockFloat( id, a, ypos3_flt );
a += 4; // y pos of triangle
dbWriteMemblockFloat( id, a, zpos3_flt );
a += 4; // z pos of triangle
dbWriteMemblockFloat( id, a, u3 );
a += 4; // u
dbWriteMemblockFloat( id, a, v3 );
a += 4; // v
// a just returns the last memblock position, which we can use to get the overall size in bytes of the mesh
return a;
}
//***** 'make_memblock_meshheader' ********************************************
//+**** ========================== ********************************************
int make_memblock_meshheader ( int id, int numverts )
{
// header for mesh format
// sets up header for standard FVF mesh 338
// we would change this to write a different FVF format if we wanted to
dbWriteMemblockDword( id, 0, 258 );
dbWriteMemblockDword( id, 4, 20 );
dbWriteMemblockDword( id, 8, numverts );
return 12;
}