📄 boidsland.cpp
字号:
/* Filename: BoidsLand.cpp
Author: Robert Platt
Creation date: 29/08/1999
Modified: 13/05/2000
Version: 0.54
Description: Implementation file for the boids landscape class.
*/
#include "BoidsWin.h"
// Constructor for the landscape class.
BoidsLand::BoidsLand( )
{
// Initialise the COM interface pointers.
landFrame = NULL;
solidStyle = DEFAULT_LANDSCAPE_SOLID_STYLE;
solidColour = LSC_GREEN;
wireframeOn = true; // Initialize the flags.
solidOn = false;
exists = false; // This will be set by the build function.
// Call the member function to produce the landscape altitudes.
calcHeights( );
}
// Build the full landscape using the previously set flags.
void BoidsLand::build( CFrameWnd *win, LPDIRECT3DRM d,
LPDIRECT3DRMFRAME s, D3DRMRENDERQUALITY solidStyle )
{
window = win;
d3drm = d; // Store two pointers to the D3D interfaces inside the object.
scene = s; // This helps to keep future calls to the object concise.
// Abort the build if nothing to do.
if ( solidOn == false && wireframeOn == false )
{
return;
}
// Calculate the uniform sizes of all the landscape patches.
xSpacing = X_LIMIT * 2 / LAND_X_SIZE;
ySpacing = LAND_HEIGHT;
zSpacing = Z_LIMIT * 2 / LAND_Z_SIZE;
// Create the main landscape root frame.
d3drm -> CreateFrame( scene, &landFrame );
landFrame -> SetPosition( scene, D3DVALUE( 0.0 ),
D3DVALUE( 0.0 ), D3DVALUE( 0.0 ) );
// Create the landscape mesh.
d3drm -> CreateMesh( &landMesh );
// Used for producing each patch of land.
D3DRMVERTEX patchVertices[ 6 ];
unsigned vertOrder[] = { 0, 1, 2, 3, 4, 5 };
// Generate the surface for the landMesh.
for ( int row = 0; row < LAND_Z_SIZE; row++ )
{
for ( int col = 0; col < LAND_X_SIZE; col++ )
{
// Create the solid representation if required.
if ( solidOn )
{
landMesh -> AddGroup( 6, 2, 3, vertOrder,
&patchGroups[ 0 ][ row ][ col ] );
}
// Create the wireframe overlay if required.
if ( wireframeOn )
{
landMesh -> AddGroup( 6, 2, 3, vertOrder,
&patchGroups[ 1 ][ row ][ col ] );
}
// Call the auxillary function to position the land patch.
positionPatch( patchVertices, row, col );
// Apply flat shading to the patch of land.
if ( solidOn )
{
flatShading( row, col, patchVertices );
}
// Complete the production of the patch of -
// - land for solid representation.
if ( solidOn )
{
landMesh -> SetVertices( patchGroups[ 0 ][ row ][ col ],
0, 6, patchVertices );
landMesh -> SetGroupQuality(
patchGroups[ 0 ][ row ][ col ], solidStyle );
// Set the landscape's colours.
// Colour the central tower brown.
if ( row == 4 && col == 4 )
{
// Brown.
landMesh -> SetGroupColor(
patchGroups[ 0 ][ row ][ col ], RGB_BROWN );
}
else // Colour the land.
{
if ( solidColour == LSC_CHECKERED )
{
// Colour the land checkered style.
if ( row % 2 == 0 )
{
if ( col % 2 == 0 )
{
// Black.
landMesh -> SetGroupColor(
patchGroups[ 0 ][ row ][ col ], RGB_BLACK );
}
else
{
// White.
landMesh -> SetGroupColor(
patchGroups[ 0 ][ row ][ col ], RGB_WHITE );
}
}
else
{
if ( col % 2 == 0 )
{
// White.
landMesh -> SetGroupColor(
patchGroups[ 0 ][ row ][ col ], RGB_WHITE );
}
else
{
// Black.
landMesh -> SetGroupColor(
patchGroups[ 0 ][ row ][ col ], RGB_BLACK );
}
}
}
if ( solidColour == LSC_GREEN )
{
// Colour the land green.
landMesh -> SetGroupColor(
patchGroups[ 0 ][ row ][ col ], RGB_LAND_GREEN );
}
}
}
if ( wireframeOn )
{
// Complete the production of the patch of land.
landMesh -> SetVertices( patchGroups[ 1 ][ row ][ col ],
0, 6, patchVertices );
landMesh -> SetGroupQuality( patchGroups[ 1 ][ row ][ col ],
D3DRMRENDER_WIREFRAME );
// Set the wireframe landscape colour.
if ( solidOn )
{
// Black.
landMesh -> SetGroupColor(
patchGroups[ 1 ][ row ][ col ], RGB_BLACK );
}
else
{
// If there is no solid land, colour -
// - the wireframe black for clarity.
// Black.
landMesh -> SetGroupColor(
patchGroups[ 1 ][ row ][ col ], RGB_BLACK );
}
}
// If the patch of land was a tower, add the sides of the tower.
if ( row == 4 && col == 4 )
{
buildTowerSides( row, col );
}
}
}
// Add the land to the land frame.
landFrame -> AddVisual( landMesh );
// Apply gouraud shading to the landscape if selected.
if ( solidStyle == D3DRMRENDER_GOURAUD && solidOn )
{
gouraudShading( );
}
exists = true; // Set the flag.
}
// Auxillary function to set the position of a patch of land.
void BoidsLand::positionPatch( D3DRMVERTEX vertices[ ], int r, int c )
{
// Set the vertices for the patch of land.
// First triangle.
//////////////////////////////////
// South west corner vertex <0>.
//////////////////////////////////
vertices[ 0 ].position.x = c * xSpacing - X_LIMIT;
// If the patch of land is a tower.
if ( r == 4 && c == 4 )
{
// Raise the height of the vertex to the top of the tower.
vertices[ 0 ].position.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
}
else
{
// Just keep the normal height.
vertices[ 0 ].position.y = landHeights[ r ][ c ]
* ySpacing - Y_LIMIT;
}
vertices[ 0 ].position.z = r * zSpacing - Z_LIMIT;
//////////////////////////////////
// North west corner vertex <1>.
//////////////////////////////////
vertices[ 1 ].position.x = c * xSpacing - X_LIMIT;
// If the patch of land is a tower.
if ( r == 4 && c == 4 )
{
// Raise the height of the vertex to the top of the tower.
vertices[ 1 ].position.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
}
else
{
// Just keep the normal height.
vertices[ 1 ].position.y = landHeights[ r + 1 ][ c ] *
ySpacing - Y_LIMIT;
}
vertices[ 1 ].position.z = ( r + 1 ) * zSpacing - Z_LIMIT;
//////////////////////////////////
// North east corner vertex <2>.
//////////////////////////////////
vertices[ 2 ].position.x = ( c + 1 ) * xSpacing - X_LIMIT;
// If the patch of land is a tower.
if ( r == 4 && c == 4 )
{
// Raise the height of the vertex to the top of the tower.
vertices[ 2 ].position.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
}
else
{
// Just keep the normal height.
vertices[ 2 ].position.y = landHeights[ r + 1 ][ c + 1 ] *
ySpacing - Y_LIMIT;
}
vertices[ 2 ].position.z = ( r + 1 ) * zSpacing - Z_LIMIT;
// Second triangle.
//////////////////////////////////
// South west corner vertex <3>.
//////////////////////////////////
vertices[ 3 ].position.x = c * xSpacing - X_LIMIT;
// If the patch of land is a tower.
if ( r == 4 && c == 4 )
{
// Raise the height of the vertex to the top of the tower.
vertices[ 3 ].position.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
}
else
{
// Just keep the normal height.
vertices[ 3 ].position.y = landHeights[ r ][ c ]
* ySpacing - Y_LIMIT;
}
vertices[ 3 ].position.z = r * zSpacing - Z_LIMIT;
//////////////////////////////////
// North east corner vertex <4>.
//////////////////////////////////
vertices[ 4 ].position.x = ( c + 1 ) * xSpacing - X_LIMIT;
// If the patch of land is a tower.
if ( r == 4 && c == 4 )
{
// Raise the height of the vertex to the top of the tower.
vertices[ 4 ].position.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
}
else
{
// Just keep the normal height.
vertices[ 4 ].position.y = landHeights[ r + 1 ][ c + 1 ] *
ySpacing - Y_LIMIT;
}
vertices[ 4 ].position.z = ( r + 1 ) * zSpacing - Z_LIMIT;
//////////////////////////////////
// South east corner vertex <5>.
//////////////////////////////////
vertices[ 5 ].position.x = ( c + 1 ) * xSpacing - X_LIMIT;
// If the patch of land is a tower.
if ( r == 4 && c == 4 )
{
// Raise the height of the vertex to the top of the tower.
vertices[ 5 ].position.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
}
else
{
// Just keep the normal height.
vertices[ 5 ].position.y = landHeights[ r ][ c + 1 ] *
ySpacing - Y_LIMIT;
}
vertices[ 5 ].position.z = r * zSpacing - Z_LIMIT;
}
// Build the faces for the sides of a tower.
void BoidsLand::buildTowerSides( int row, int col )
{
unsigned vertOrder[] = { 0, 1, 2, 3, 4, 5 };
D3DRMVERTEX towerVertices[ 6 ];
for ( int side = 0; side <= 3; side++ )
{
// Create the solid representation if required.
if ( solidOn )
{
landMesh -> AddGroup( 6, 2, 3, vertOrder,
&towerGroups[ 0 ][ side ] );
}
// Create the wireframe overlay if required.
if ( wireframeOn )
{
landMesh -> AddGroup( 6, 2, 3, vertOrder,
&towerGroups[ 1 ][ side ] );
}
// Set the vertices for the patch of land.
D3DVECTOR topLeftPoint,
topRightPoint,
bottomLeftPoint,
bottomRightPoint;
// These values are the same for all the sides.
topLeftPoint.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
topRightPoint.y = TOWER_HEIGHT * ySpacing - Y_LIMIT;
// The north facing side.
if ( side == 0 )
{
// Define the top left point.
topLeftPoint.x = col * xSpacing - X_LIMIT;
topLeftPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
// Define the top right point.
topRightPoint.x = ( col + 1 ) * 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 + 1 ][ col ]
* ySpacing - Y_LIMIT;
bottomLeftPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
// Define the bottom right point.
bottomRightPoint.x = ( col + 1 ) * xSpacing - X_LIMIT;
bottomRightPoint.y = landHeights[ row + 1 ][ col + 1 ]
* ySpacing - Y_LIMIT;
bottomRightPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
}
// The east facing side.
if ( side == 1 )
{
// Define the top left point.
topLeftPoint.x = ( col + 1 ) * xSpacing - X_LIMIT;
topLeftPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
// Define the top right point.
topRightPoint.x = ( col + 1 ) * 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 + 1 ][ col + 1 ]
* ySpacing - Y_LIMIT;
bottomLeftPoint.z = ( row + 1 ) * zSpacing - Z_LIMIT;
// Define the bottom right point.
bottomRightPoint.x = ( col + 1 ) * xSpacing - X_LIMIT;
bottomRightPoint.y = landHeights[ row ][ col + 1 ]
* ySpacing - Y_LIMIT;
bottomRightPoint.z = row * zSpacing - Z_LIMIT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -