⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boidswin.cpp

📁 3D的Boids效果演示源程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:


	// 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 + -