boidsland.cpp
来自「3D的Boids效果演示源程序」· C++ 代码 · 共 1,248 行 · 第 1/3 页
CPP
1,248 行
// The south facing side.
if ( side == 2 )
{
// Define the top left point.
topLeftPoint.x = ( col + 1 ) * xSpacing - X_LIMIT;
topLeftPoint.z = row * zSpacing - Z_LIMIT;
// Define the top right point.
topRightPoint.x = col * xSpacing - X_LIMIT;
topRightPoint.z = row * zSpacing - Z_LIMIT;
// Define the bottom left point.
bottomLeftPoint.x = ( col + 1 ) * xSpacing - X_LIMIT;
bottomLeftPoint.y = landHeights[ row ][ col + 1 ]
* ySpacing - Y_LIMIT;
bottomLeftPoint.z = row * zSpacing - Z_LIMIT;
// Define the bottom right point.
bottomRightPoint.x = col * xSpacing - X_LIMIT;
bottomRightPoint.y = landHeights[ row ][ col ]
* ySpacing - Y_LIMIT;
bottomRightPoint.z = row * zSpacing - Z_LIMIT;
}
// The west facing side.
if ( side == 3 )
{
// Define the top left point.
topLeftPoint.x = col * xSpacing - X_LIMIT;
topLeftPoint.z = row * zSpacing - Z_LIMIT;
// Define the top right point.
topRightPoint.x = col * xSpacing - X_LIMIT;
topRightPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
// Define the bottom left point.
bottomLeftPoint.x = col * xSpacing - X_LIMIT;
bottomLeftPoint.y = landHeights[ row ][ col ]
* ySpacing - Y_LIMIT;
bottomLeftPoint.z = row * zSpacing - Z_LIMIT;
// Define the bottom right point.
bottomRightPoint.x = col * xSpacing - X_LIMIT;
bottomRightPoint.y = landHeights[ row + 1 ][ col ]
* ySpacing - Y_LIMIT;
bottomRightPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
}
// First triangle.
// South west corner vertex <0>.
towerVertices[ 0 ].position = topLeftPoint;
// North west corner vertex <1>.
towerVertices[ 1 ].position = bottomLeftPoint;
// North east corner vertex <2>.
towerVertices[ 2 ].position = bottomRightPoint;
// Second triangle.
// South west corner vertex <3>.
towerVertices[ 3 ].position = topLeftPoint;
// North east corner vertex <4>.
towerVertices[ 4 ].position = bottomRightPoint;
// South east corner vertex <5>.
towerVertices[ 5 ].position = topRightPoint;
// Apply flat shading to the side of the tower.
if ( solidOn )
{
towerFlatShading( side, towerVertices );
}
// Complete the production of the patch -
// - of land for solid representation.
if ( solidOn )
{
landMesh -> SetVertices( towerGroups[ 0 ][ side ], 0, 6,
towerVertices );
landMesh -> SetGroupQuality( towerGroups[ 0 ][ side ],
solidStyle );
// Colour the tower face brown.
landMesh -> SetGroupColor( towerGroups[ 0 ][ side ], RGB_BROWN );
}
if ( wireframeOn )
{
// Complete the production of the patch of land.
landMesh -> SetVertices( towerGroups[ 1 ][ side ], 0, 6,
towerVertices );
landMesh -> SetGroupQuality( towerGroups[ 1 ][ side ],
D3DRMRENDER_WIREFRAME );
// Set the wireframe landscape colour.
if ( solidOn )
{
// Black.
landMesh -> SetGroupColor( towerGroups[ 1 ][ side ],
RGB_BLACK );
}
else
{
// If there is no solid land, colour -
// - the wireframe black for clarity.
landMesh -> SetGroupColor( towerGroups[ 1 ][ side ],
RGB_BLACK );
}
}
}
}
// Generate some altitudes to shape the landscape.
void BoidsLand::calcHeights( )
{
srand( time( 0 ) ); // Initialise random number generation.
for ( int row = 0; row < LAND_Z_SIZE + 1; row++ )
{
for ( int col = 0; col < LAND_X_SIZE + 1; col++ )
{
landHeights[ row ][ col ] = rand( ) % LAND_Y_SIZE;
}
}
}
// Calculate the normals for all the face of the patches of land.
void BoidsLand::flatShading( int row, int col, D3DRMVERTEX patchVertices[ ] )
{
// Calculate the normals for the triangular faces.
// First make references to the values to simpify the code.
D3DVALUE &x1 = patchVertices[ 0 ].position.x;
D3DVALUE &x2 = patchVertices[ 1 ].position.x;
D3DVALUE &x3 = patchVertices[ 2 ].position.x;
D3DVALUE &y1 = patchVertices[ 0 ].position.y;
D3DVALUE &y2 = patchVertices[ 1 ].position.y;
D3DVALUE &y3 = patchVertices[ 2 ].position.y;
D3DVALUE &z1 = patchVertices[ 0 ].position.z;
D3DVALUE &z2 = patchVertices[ 1 ].position.z;
D3DVALUE &z3 = patchVertices[ 2 ].position.z;
D3DVALUE &x4 = patchVertices[ 3 ].position.x;
D3DVALUE &x5 = patchVertices[ 4 ].position.x;
D3DVALUE &x6 = patchVertices[ 5 ].position.x;
D3DVALUE &y4 = patchVertices[ 3 ].position.y;
D3DVALUE &y5 = patchVertices[ 4 ].position.y;
D3DVALUE &y6 = patchVertices[ 5 ].position.y;
D3DVALUE &z4 = patchVertices[ 3 ].position.z;
D3DVALUE &z5 = patchVertices[ 4 ].position.z;
D3DVALUE &z6 = patchVertices[ 5 ].position.z;
// Produce two vectors from the first triangle.
D3DVECTOR v1, v2, v3;
v1.x = x3 - x2;
v1.y = y3 - y2;
v1.z = z3 - z2;
v2.x = x1 - x3;
v2.y = y1 - y3;
v2.z = z1 - z3;
// Find the cross product of the two vectors.
D3DRMVectorCrossProduct( &v3, &v1, &v2 );
// Normalise the resultant vector.
D3DRMVectorNormalize( &v3 );
// Set the normals of the first triangular face.
patchFaceNormals[ row ][ col ][ 0 ] = v3;
// Produce two vectors from the second triangle.
v1.x = x6 - x5;
v1.y = y6 - y5;
v1.z = z6 - z5;
v2.x = x4 - x6;
v2.y = y4 - y6;
v2.z = z4 - z6;
// Find the cross product of the two vectors.
D3DRMVectorCrossProduct( &v3, &v1, &v2 );
// Normalise the resultant vector.
D3DRMVectorNormalize( &v3 );
// Set the normals of the second triangular face.
patchFaceNormals[ row ][ col ][ 1 ] = v3;
// Set the normals for the trianglar faces for flat shading.
// First triangle.
patchVertices[ 0 ].normal = patchFaceNormals[ row ][ col ][ 0 ];
patchVertices[ 1 ].normal = patchFaceNormals[ row ][ col ][ 0 ];
patchVertices[ 2 ].normal = patchFaceNormals[ row ][ col ][ 0 ];
// Second triangle.
patchVertices[ 3 ].normal = patchFaceNormals[ row ][ col ][ 1 ];
patchVertices[ 4 ].normal = patchFaceNormals[ row ][ col ][ 1 ];
patchVertices[ 5 ].normal = patchFaceNormals[ row ][ col ][ 1 ];
}
// Calculate the normals for all the face of the patches of land.
void BoidsLand::towerFlatShading( int side, D3DRMVERTEX towerVertices[ ] )
{
// Calculate the normals for the triangular faces.
// First make references to the values to simpify the code.
D3DVALUE &x1 = towerVertices[ 0 ].position.x;
D3DVALUE &x2 = towerVertices[ 1 ].position.x;
D3DVALUE &x3 = towerVertices[ 2 ].position.x;
D3DVALUE &y1 = towerVertices[ 0 ].position.y;
D3DVALUE &y2 = towerVertices[ 1 ].position.y;
D3DVALUE &y3 = towerVertices[ 2 ].position.y;
D3DVALUE &z1 = towerVertices[ 0 ].position.z;
D3DVALUE &z2 = towerVertices[ 1 ].position.z;
D3DVALUE &z3 = towerVertices[ 2 ].position.z;
D3DVALUE &x4 = towerVertices[ 3 ].position.x;
D3DVALUE &x5 = towerVertices[ 4 ].position.x;
D3DVALUE &x6 = towerVertices[ 5 ].position.x;
D3DVALUE &y4 = towerVertices[ 3 ].position.y;
D3DVALUE &y5 = towerVertices[ 4 ].position.y;
D3DVALUE &y6 = towerVertices[ 5 ].position.y;
D3DVALUE &z4 = towerVertices[ 3 ].position.z;
D3DVALUE &z5 = towerVertices[ 4 ].position.z;
D3DVALUE &z6 = towerVertices[ 5 ].position.z;
// Produce two vectors from the first triangle.
D3DVECTOR v1, v2, v3;
v1.x = x3 - x2;
v1.y = y3 - y2;
v1.z = z3 - z2;
v2.x = x1 - x3;
v2.y = y1 - y3;
v2.z = z1 - z3;
// Find the cross product of the two vectors.
D3DRMVectorCrossProduct( &v3, &v1, &v2 );
// Normalise the resultant vector.
D3DRMVectorNormalize( &v3 );
// Set the normals of the first triangular face.
towerFaceNormals[ side ][ 0 ] = v3;
// Produce two vectors from the second triangle.
v1.x = x6 - x5;
v1.y = y6 - y5;
v1.z = z6 - z5;
v2.x = x4 - x6;
v2.y = y4 - y6;
v2.z = z4 - z6;
// Find the cross product of the two vectors.
D3DRMVectorCrossProduct( &v3, &v1, &v2 );
// Normalise the resultant vector.
D3DRMVectorNormalize( &v3 );
// Set the normals of the second triangular face.
towerFaceNormals[ side ][ 1 ] = v3;
// Set the normals for the trianglar faces for flat shading.
// First triangle.
towerVertices[ 0 ].normal = towerFaceNormals[ side ][ 0 ];
towerVertices[ 1 ].normal = towerFaceNormals[ side ][ 0 ];
towerVertices[ 2 ].normal = towerFaceNormals[ side ][ 0 ];
// Second triangle.
towerVertices[ 3 ].normal = towerFaceNormals[ side ][ 1 ];
towerVertices[ 4 ].normal = towerFaceNormals[ side ][ 1 ];
towerVertices[ 5 ].normal = towerFaceNormals[ side ][ 1 ];
}
// Calculate the normals for all the vertices of the patches of land.
void BoidsLand::gouraudShading( )
{
// Local buffer for storing the current patches details.
D3DRMVERTEX patchVertices[ 6 ];
D3DVECTOR averageNormal;
int faces;
// Iterate through the patches of land on the landscape.
for ( int row = 0; row < LAND_Z_SIZE; row++ )
{
for ( int col = 0; col < LAND_X_SIZE; col++ )
{
// Get the current state of the current vertex.
landMesh -> GetVertices( patchGroups[ 0 ][ row ][ col ],
0, 6, patchVertices );
// Recalculate the normals from vertices 0 & 3.
// Find the average of the face normals surrounding the vertex.
averageNormal.x = 0;
averageNormal.y = 0;
averageNormal.z = 0;
faces = 0;
// Working round in a clockwise direction -
// - starting from the current face.
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col ][ 1 ] );
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col ][ 0 ] );
faces += 2;
if ( row > 0 )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row - 1 ][ col ][ 0 ] );
faces++;
}
if ( row > 0 && col > 0 )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row - 1 ][ col - 1 ][ 1 ] );
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row - 1 ][ col - 1 ][ 0 ] );
faces += 2;
}
if ( col > 0 )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col - 1 ][ 1 ] );
faces++;
}
averageNormal.x /= faces;
averageNormal.y /= faces;
averageNormal.z /= faces;
// Normalise the resultant vector.
D3DRMVectorNormalize( &averageNormal );
// Update the normal of vertex 0.
patchVertices[ 0 ].normal = averageNormal;
// Update the normal of vertex 3.
patchVertices[ 3 ].normal = averageNormal;
// Recalculate the normal from vertex 1.
// Find the average of the face normals surrounding the vertex.
averageNormal.x = 0;
averageNormal.y = 0;
averageNormal.z = 0;
faces = 0;
// Working round in a clockwise direction -
// - starting from the current face.
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col ][ 0 ] );
faces++;
if ( col > 0 )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col - 1 ][ 1 ] );
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col - 1 ][ 0 ] );
faces += 2;
}
if ( col > 0 && ( ( row + 1 ) < LAND_Z_SIZE ) )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row + 1 ][ col - 1 ][ 1 ] );
faces++;
}
if ( ( row + 1 ) < LAND_Z_SIZE )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row + 1 ][ col ][ 0 ] );
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row + 1 ][ col ][ 1 ] );
faces += 2;
}
averageNormal.x /= faces;
averageNormal.y /= faces;
averageNormal.z /= faces;
// Normalise the resultant vector.
D3DRMVectorNormalize( &averageNormal );
// Update the normal of vertex 1.
patchVertices[ 1 ].normal = averageNormal;
// Recalculate the normals from vertices 2 & 4.
// Find the average of the face normals surrounding the vertex.
averageNormal.x = 0;
averageNormal.y = 0;
averageNormal.z = 0;
faces = 0;
// Working round in a clockwise direction -
// - starting from the current face.
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col ][ 1 ] );
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row ][ col ][ 0 ] );
faces += 2;
if ( ( row + 1 ) < LAND_Z_SIZE )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row + 1 ][ col ][ 1 ] );
faces++;
}
if ( ( row + 1 ) < LAND_Z_SIZE && ( col + 1 ) < LAND_X_SIZE )
{
D3DRMVectorAdd( &averageNormal, &averageNormal,
&patchFaceNormals[ row + 1 ][ col + 1 ][ 0 ] );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?