📄 boidswin.cpp
字号:
// If any extra flyers are required add one to the scene.
if ( numFlyers < requiredFlyers && !overloaded )
{
// Wait for the correct frame delay before adding.
if ( frameCount % ADD_BOID_FRAME_DELAY == 0 )
{
createFlyers( 1 ); // Add a flyer.
updateAddFlyers( );
}
}
// If the application is overloaded, remove some flyers.
if ( overloaded && numFlyers > 1 )
{
requiredFlyers = numFlyers * 0.75;
overloaded = false;
updateRemoveFlyers( );
}
// If less flyers are required remove the right amount.
if ( numFlyers > requiredFlyers )
{
int amount = numFlyers - requiredFlyers;
removeFlyers( amount ); // Remove the surplus amount.
updateRemoveFlyers( );
}
}
// Set up the necessary requirements to start the simulation.
void BoidsWin::createScene( )
{
// Create the root frame for the scene.
d3drm -> CreateFrame( NULL, &scene );
srand( time( 0 ) ); // Initialise random number generation.
int randomX, randomY, randomZ;
int speed, hHeading, vHeading;
// Create the flyers at random positions and velocities.
BoidsFlyer *newObjPtr;
for ( int number = 0; number < numFlyers; number++ )
{
newObjPtr = new BoidsFlyer( );
flyers.push_back( newObjPtr );
flyers[ number ] -> build( this, d3drm, scene );
randomX = ( ( 1 + rand( ) % (int)( X_LIMIT * 2 ) ) - X_LIMIT );
randomY = ( ( 1 + rand( ) % 10 ) - 5 );
randomZ = ( ( 1 + rand( ) % (int)( Z_LIMIT * 2 ) ) - Z_LIMIT );
speed = ( ( 1 + rand( ) % (int)( maximumSpeed -
minimumSpeed ) ) + minimumSpeed );
hHeading = ( ( 1 + rand( ) % 360 ) - 180 );
vHeading = ( ( 1 + rand( ) % 10 ) - 5 );
flyers[ number ] -> setPosition( randomX, randomY, randomZ );
flyers[ number ] -> setReqVelocity( speed, hHeading, vHeading );
}
// All the flyers meshes are set to the right type to start with.
flyerMeshesChanged = numFlyers;
// Set all the object's sizes to the position of the size slider.
for ( int index = 0; index < numFlyers; index++ )
{
double posSize = ( sliderSize.GetPos() * SIZE_SCALE_FACTOR );
flyers[ index ] -> setSize( posSize );
}
// Create the directional lighting.
LPDIRECT3DRMLIGHT light;
d3drm -> CreateLightRGB( D3DRMLIGHT_DIRECTIONAL,
D3DVALUE( 1.0 ), D3DVALUE( 1.0 ), D3DVALUE( 1.0 ), &light );
// Create a frame for the lighting.
LPDIRECT3DRMFRAME lightFrame;
d3drm -> CreateFrame( scene, &lightFrame );
lightFrame -> AddLight( light );
lightFrame -> SetOrientation( scene,
D3DVALUE( 0 ), D3DVALUE( -1 ), D3DVALUE( 1 ),
D3DVALUE( 0 ), D3DVALUE( 1 ), D3DVALUE( 1 ) );
light -> Release( );
light = NULL;
lightFrame -> Release( );
lightFrame = NULL;
// Create some white ambient lighting and add it to the scene.
d3drm -> CreateLightRGB( D3DRMLIGHT_AMBIENT,
D3DVALUE( 0.4 ), D3DVALUE( 0.4 ), D3DVALUE( 0.4 ), &light );
scene -> AddLight( light );
light -> Release( );
light = NULL;
// Create a viewport frame for the viewport called camera.
d3drm -> CreateFrame( scene, &camera );
// Set the camera's position with reference to the sliderCam control.
cameraPosition = sliderCam.GetPos();
cameraPosition2 = sliderCam2.GetPos();
positionCamera( );
// Create the viewport and attach it to the frame called camera.
d3drm -> CreateViewport( device, camera, 0, 0, device -> GetWidth( ),
device -> GetHeight( ), &viewPort );
// Set the range of vision, default is 100.
viewPort -> SetBack( D3DVALUE( VIEWPORT_BACK_DISTANCE ) );
// Set the background colour to a light blue (sky colour).
scene -> SetSceneBackground( RGB_BACKGROUND );
// Create the landscape.
landscape.build( this, d3drm, scene, DEFAULT_LANDSCAPE_SOLID_STYLE );
}
// Window's event hander to repaint the window.
afx_msg void BoidsWin::OnPaint( )
{
// Create the device if not yet present.
if ( device == NULL )
{
createWinDevice( );
}
// Use the D3DRMWinDevice interface to repaint the window.
LPDIRECT3DRMWINDEVICE windev;
PAINTSTRUCT ps;
BeginPaint( &ps );
device -> QueryInterface( IID_IDirect3DRMWinDevice, (void**)&windev );
windev -> HandlePaint( ps.hdc );
windev -> Release( );
EndPaint( &ps );
}
// Resize the main application's window.
void BoidsWin::reSizeD3D( )
{
// Abort if the rendering thread is still active.
if ( threadFinished == false )
{
return;
}
// Reposition the window's controls.
// Work from the bottom of the window upwards.
CRect position;
GetClientRect( &position );
position.left = position.right - CONTROL_PANEL_SIZE;
// border5 to place some spacing in the controls.
position.top = 400;
border5.MoveWindow( position );
// btnStop CButton control as a push button to stop the simulation.
position.top = 370;
position.bottom = 400;
btnStop.MoveWindow( position );
// staticTime for the simulation time.
position.top = 350;
position.bottom = 370;
staticTime.MoveWindow( position );
// staticFrames for the frames per second.
position.top = 330;
position.bottom = 350;
staticFrames.MoveWindow( position );
// border4 to place some spacing in the controls.
position.top = 310;
position.bottom = 330;
border4.MoveWindow( position );
// btnCentre CButton control as a push button to reset the camera angle.
position.top = 280;
position.bottom = 310;
btnCentre.MoveWindow( position );
// sliderCam2 for the camera position.
position.top = 250;
position.bottom = 280;
sliderCam2.MoveWindow( position );
// staticCam2 for the camera position.
position.top = 230;
position.bottom = 250;
staticCam2.MoveWindow( position );
// border3 to place some spacing in the controls.
position.top = 210;
position.bottom = 230;
border3.MoveWindow( position );
// sliderCam for the camera position.
position.top = 180;
position.bottom = 210;
sliderCam.MoveWindow( position );
// staticCam for the camera position.
position.top = 160;
position.bottom = 180;
staticCam.MoveWindow( position );
// border2 to place some spacing in the controls.
position.top = 140;
position.bottom = 160;
border2.MoveWindow( position );
// sliderSize for the size of the flyers.
position.top = 110;
position.bottom = 140;
sliderSize.MoveWindow( position );
// staticSize for the size of the flyers.
position.top = 90;
position.bottom = 110;
staticSize.MoveWindow( position );
// border1 to place some spacing in the controls.
position.top = 70;
position.bottom = 90;
border1.MoveWindow( position );
// sliderNum for the number of flyers.
position.top = 40;
position.bottom = 70;
sliderNum.MoveWindow( position );
// staticNum for the number of flyers.
position.top = 20;
position.bottom = 40;
staticNum.MoveWindow( position );
// topBorder static control.
position.top = 0;
position.bottom = 20;
topBorder.MoveWindow( position );
// Abort if no device present.
if ( !device )
{
return;
}
// Get new the dimensions of the window.
CRect size;
GetClientRect( &size );
int width = size.right;
if ( showControlPanel )
{
width -= CONTROL_PANEL_SIZE;
}
int height = size.bottom;
// Destroy and recreate a new device if -
// - provided with any client window area.
if ( ( width > 0 ) && height )
{
// Retrieve the device characteristics before destroying it.
D3DRMRENDERQUALITY old_quality = device -> GetQuality();
viewPort -> Release( ); // Destroy the previous viewport.
viewPort = NULL;
device -> Release( ); // Destroy the previous device.
device = NULL;
// Recreate a new device & viewPort for the new window size.
d3drm -> CreateDeviceFromClipper( clipper,
NULL, width, height, &device );
device -> SetQuality( old_quality );
width = device -> GetWidth( );
height = device -> GetHeight( );
d3drm -> CreateViewport( device, camera, 0, 0,
width, height, &viewPort );
// Set the range of vision, default is 100.
viewPort ->SetBack( D3DVALUE( VIEWPORT_BACK_DISTANCE ) );
}
// Update the window's data member when -
// - the resize operation has completed.
prevWindowSize = newWindowSize;
}
// Function to increase the number of boids active.
void BoidsWin::createFlyers( int amount )
{
// Create all the new flyers.
BoidsFlyer *newObjPtr;
int randomX, randomY, randomZ;
int speed, hHeading, vHeading;
for ( int index = 0; index < amount; index++ )
{
newObjPtr = new BoidsFlyer( ); // Create a new flyer.
flyers.push_back( newObjPtr );
flyers[ numFlyers ] -> build( this, d3drm, scene );
randomX = ( ( 1 + rand( ) % 900 ) - 450 );
randomY = ( ( 1 + rand( ) % 100 ) - 50 );
randomZ = ( ( 1 + rand( ) % 900 ) - 450 );
speed = ( ( 1 + rand( ) % (int)( maximumSpeed - minimumSpeed ) )
+ minimumSpeed );
hHeading = ( ( 1 + rand( ) % 360 ) - 180 );
vHeading = ( ( 1 + rand( ) % 10 ) - 5 );
flyers[ numFlyers ] -> setPosition( randomX, randomY, randomZ );
flyers[ numFlyers ] -> setReqVelocity( speed, hHeading, vHeading );
numFlyers++;
}
}
// Function to reduce the number of active flyers.
void BoidsWin::removeFlyers( int amount )
{
// Remove the correct number of flyers.
BoidsFlyer *oldObjPtr;
for ( int index = 0; index < amount; index++ )
{
oldObjPtr = flyers[ numFlyers - 1 ];
flyers.pop_back( );
delete oldObjPtr;
numFlyers--;
}
}
// Set the appropriate position and orientation for the camera.
void BoidsWin::positionCamera( )
{
if ( cameraView == CAM_ABOVE )
{
camera -> SetPosition( scene, D3DVALUE( 0 ),
D3DVALUE( ( 2.3 * X_LIMIT ) - ( cameraPosition
* X_LIMIT / 450.0 ) ), D3DVALUE( 0 ) );
// Convert the angle of the camera rotation to a suitable vector.
D3DVALUE xVector = D3DVALUE( sin( ( 180 -
cameraPosition2 ) / 180.0 * PI ) );
D3DVALUE zVector = D3DVALUE( cos( ( 180 -
cameraPosition2 ) / 180.0 * PI ) );
camera -> SetOrientation( scene, D3DVALUE( 0 ), D3DVALUE( -1 ),
D3DVALUE( 0 ), D3DVALUE( -xVector ),
D3DVALUE( 0 ), D3DVALUE( zVector ) );
}
if ( cameraView == CAM_BOID )
{
// Convert the angle of the camera rotation to a suitable position.
// Subtract scale to reverse the scale.
int positioning = 1001 - cameraPosition;
// Add the size of the boid to the camera -
// - distance, to prevent an internal view.
D3DVALUE sizeSetting = ( sliderSize.GetPos() * SIZE_SCALE_FACTOR );
positioning += sizeSetting * BOID_VIEW_CAMERA_DISTANCE_FACTOR;
D3DVALUE xPos = positioning * D3DVALUE( sin( (
cameraPosition2 - 180 ) / 180.0 * PI ) );
D3DVALUE zPos = positioning * D3DVALUE( cos( (
cameraPosition2 - 180 ) / 180.0 * PI ) );
// Add the viewport to a boid.
// This code is activated when the camera first moves to the boid.
if ( cameraOnBoid == false )
{
camera -> SetPosition( scene, 0, 0, 0 );
flyers[ 0 ] -> getFramePtr( ) -> AddChild( camera );
cameraOnBoid = true;
}
camera -> SetPosition( flyers[ 0 ] ->
getFramePtr( ), -xPos, 0, -zPos );
camera -> SetOrientation( flyers[ 0 ] ->
getFramePtr( ), xPos, 0, zPos, 0, 1, 0 );
}
// Process the north camera view.
if ( cameraView == CAM_NORTH )
{
// Convert the angle of the camera rotation to a suitable position.
D3DVALUE xPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( sin( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
D3DVALUE zPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( cos( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
// Set the camera position and orientation.
camera -> SetPosition( scene, -xPos, CAMERA_HEIGHT, -zPos );
camera -> SetOrientation( scene, xPos, 0, zPos, 0, 1, 0 );
}
// Process the east camera view.
if ( cameraView == CAM_EAST )
{
// Convert the angle of the camera rotation to a suitable position.
D3DVALUE xPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( cos( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
D3DVALUE zPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( sin( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
// Set the camera position and orientation.
camera -> SetPosition( scene, -xPos, CAMERA_HEIGHT, zPos );
camera -> SetOrientation( scene, xPos, 0, -zPos, 0, 1, 0 );
}
// Process the south camera view.
if ( cameraView == CAM_SOUTH )
{
// Convert the angle of the camera rotation to a suitable position.
D3DVALUE xPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( sin( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
D3DVALUE zPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( cos( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
// Set the camera position and orientation.
camera -> SetPosition( scene, xPos, CAMERA_HEIGHT, zPos );
camera -> SetOrientation( scene, -xPos, 0, -zPos, 0, 1, 0 );
}
// Process the west camera view.
if ( cameraView == CAM_WEST )
{
// Convert the angle of the camera rotation to a suitable position.
D3DVALUE xPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( cos( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
D3DVALUE zPos = X_LIMIT * 4 / 1000 * ( 1001 - cameraPosition ) *
D3DVALUE( sin( ( cameraPosition2 - 180 ) / 180.0 * PI ) );
// Set the camera position and orientation.
camera -> SetPosition( scene, xPos, CAMERA_HEIGHT, -zPos );
camera -> SetOrientation( scene, -xPos, 0, zPos, 0, 1, 0 );
}
}
// Member function to update the rest of the simulation, -
// - after adding a quantity of new flyers.
void BoidsWin::updateAddFlyers( )
{
// Set the text of the static control to show the current number.
CString numberObjText( "Number of Flyers: " );
char buffer[ 50 ]; // Temporary buffer for string conversion.
numberObjText += _itoa( numFlyers, buffer, 10 );
staticNum.SetWindowText( numberObjText );
// Set all the object's sizes to the position of the size slider.
for ( int index = 0; index < numFlyers; index++ )
{
double posSize = ( sliderSize.GetPos() * SIZE_SCALE_FACTOR );
flyers[ index ] -> setSize( posSize );
}
}
// Member function to update the rest of the simulation, -
// - after removing a quantity of flyers.
void BoidsWin::updateRemoveFlyers( )
{
// Set the text of the static control to show the current number.
CString numberObjText( "Number of Flyers: " );
char buffer[ 50 ]; // Temporary buffer for string conversion.
numberObjText += _itoa( numFlyers, buffer, 10 );
staticNum.SetWindowText( numberObjText );
// Check if the view from a boid has been invalidated.
if ( numFlyers == 0 && cameraView == CAM_BOID )
{
// Remove the camera from a boid, if it is on one.
if ( cameraOnBoid == true )
{
scene -> AddChild( camera );
cameraOnBoid = false;
}
cameraView = CAM_ABOVE;
positionCamera( );
}
// Move the slider to the correct position.
sliderNum.SetPos( numFlyers );
}
// Window's event handler to process the control panel's sliders.
afx_msg void BoidsWin::OnHScroll( UINT SBCode, UINT Pos, CScrollBar *SB )
{
// Only update the correct slider.
// Cast the pointer to the scroll bar -
// - to a pointer to a void for the comparison.
if ( static_cast< void * >( SB ) == &sliderNum )
{
// Process the slider for the number of flyers.
// Adjust the number of flyers.
requiredFlyers = sliderNum.GetPos();
}
// Process the slider for the object's size.
if ( static_cast< void * >( SB ) == &sliderSize )
{
for ( int index = 0; index < numFlyers; index++ )
{
D3DVALUE posSize = ( sliderSize.GetPos() * SIZE_SCALE_FACTOR );
flyers[ index ] -> setSize( posSize );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -