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 + -
显示快捷键?