Example #1
0
static void gTryPositionViewer( const SVector3& newPos, const SVector3& finalPos )
{
	// if we're in megamap mode - allow it!
	if( !gAppSettings.followMode ) {
		gViewer.getOrigin() = newPos;
		return;
	}

	// else, if the final needed position is very far away - allow it
	SVector3 toFinal = gViewer.getOrigin() - finalPos;
	const float FAR_AWAY = 20.0f;
	if( toFinal.lengthSq() > FAR_AWAY * FAR_AWAY ) {
		gViewer.getOrigin() = newPos;
		return;
	}

	// else, check the new position for collisions
	const CLevelMesh& level = CGameInfo::getInstance().getLevelMesh();
	SVector3 targetPos = newPos;
	level.fitSphere( targetPos, VIEWER_R );
	gViewer.getOrigin() = targetPos;
}
void CActorEntity::update( float timeAlpha )
{
	bool alive = mGameEntity->isAlive();
	if( alive ) {
		// fade out the outline
		float dt = CSystemTimer::getInstance().getDeltaTimeS();
		mOutlineTTL -= dt;
		if( mOutlineTTL < 0.0f )
			mOutlineTTL = 0.0f;

		SMatrix4x4& m = mWorldMat;
		SVector3 pos = samplePos( timeAlpha );
		SVector3 dir = samplePos( timeAlpha + 0.1f ) - pos;
		if( dir.lengthSq() < 1.0e-3f )
			dir = m.getAxisZ();
		else
			dir.normalize();

		if( mGameEntity->getType() == ENTITY_BLOCKER ) {
			double tt = CSystemTimer::getInstance().getTimeS();
			D3DXMatrixRotationY( &m, tt * 0.2f );
			m.getOrigin() = pos;
			m.getOrigin().y += sinf( tt * 0.6f ) * 0.2f;
		} else {
			m.getOrigin() = pos;
			m.getAxisZ() = dir;
			m.getAxisZ().y *= 0.2f;
			m.getAxisZ().normalize();
			m.getAxisY().set( 0, 1, 0 );
			m.getAxisX() = m.getAxisY().cross( m.getAxisZ() );
			m.getAxisX().normalize();
			m.getAxisY() = m.getAxisZ().cross( m.getAxisX() );
		}
	} else {
		mOutlineTTL = 0.0f;
	}
}
Example #3
0
/**
 *  Main loop code.
 */
void CDemo::perform()
{
	char buf[100];

	time_value tmv = CSystemTimer::getInstance().getTime();
	double t = tmv.tosec();
	float dt = CSystemTimer::getInstance().getDeltaTimeS();
	gTimeParam = float(t);

	CDynamicVBManager::getInstance().discard();

	CD3DDevice& dx = CD3DDevice::getInstance();
	gScreenFixUVs.set( 0.5f/dx.getBackBufferWidth(), 0.5f/dx.getBackBufferHeight(), 0.0f, 0.0f );

	CGameInfo& gi = CGameInfo::getInstance();
	const CGameDesc& desc = gi.getGameDesc();
	CGameState& state = gi.getState();
	const CGameMap& gmap = desc.getMap();

	//
	// should we still perform some initialization steps?

	if( !gInitGuiDone ) {
		// perform multi-step initialization...
		const char* initStepName = NULL;
		if( !gInitMainStarted ) {

			BEGIN_T();
			
			initStepName = gi.initBegin();
			gInitMainStarted = true;
		} else if( !gInitMainDone ) {
			initStepName = gi.initStep();
			if( !initStepName ) {
				initStepName = "Initializing GUI...";
				gInitMainDone = true;
			}
		} else {
			gInitiallyPlaceViewer();
			gSetupGUI();
			gInitGuiDone = true;

			END_T( "initialization" );
			
			return;
		}
		// check for init errors...
		if( !gErrorMsg.empty() ) {
			CONS << "Fatal error: " << gErrorMsg << endl;
			gFinished = true;
			return;
		}
		if( initStepName ) {
			CONS << "Init step: " << initStepName << endl;
		}
		// render progress
		assert( initStepName );
		dx.clearTargets( true, true, true, 0xFF000000, 1.0f, 0L );
		dx.sceneBegin();
		G_RENDERCTX->applyGlobalEffect();
		gUIDlg->renderBegin();
		gUIDrawLogo();
		gUIDrawProgress( initStepName );
		gUIDlg->renderEnd();
		dx.sceneEnd();
		return;
	}

	//
	// fatal error

	if( gCheckFatalError() )
		return;

	//
	// check if settings dialog just was closed

	if( gSettingsDlgWasActive && gUISettingsDlg->getState() != CDemoSettingsDialog::STATE_ACTIVE ) {
		gSettingsDlgWasActive = false;
		gUIDlg->getCheckBox( GID_CHK_OPTIONS )->setChecked( false );
		if( gUISettingsDlg->getState() == CDemoSettingsDialog::STATE_OK ) {
			// apply settings, return
			if( gAppSettings.gfxDetail != gUISettingsDlg->getAppSettings().gfxDetail ) {
				gi.getLevelMesh().updateDetailLevel( gUISettingsDlg->getAppSettings().gfxDetail );
			}
			gAppSettings = gUISettingsDlg->getAppSettings();
			CD3DSettings d3dset;
			gUISettingsDlg->getFinalSettings( d3dset );
			// don't apply d3d settings if they didn't change
			if( d3dset != gAppContext->getD3DSettings() )
				gAppContext->applyD3DSettings( d3dset );
			return;
		}
	} else if( gSettingsDlgWasActive ) {
		// if the dialog is active, but the d3d settings just changed (eg. alt-tab),
		// hide it and re-show it
		if( gSettingsAtDlgStart != gAppContext->getD3DSettings() ) {
			gUISettingsDlg->hideDialog();
			gSettingsAtDlgStart = gAppContext->getD3DSettings();
			gUISettingsDlg->showDialog( gSettingsAtDlgStart );
		}
	}

	//
	// check if help dialog just was closed

	if( gHelpDlgWasActive && !gUIHelpDlg->isActive() ) {
		gHelpDlgWasActive = false;
		gUIDlg->getCheckBox( GID_CHK_HELP )->setChecked( false );
	}


	bool gameSetupActive = (gUIGameSetupDlg->getState() == CGameSetupDialog::STATE_ACTIVE);
	bool insideView = gAppSettings.followMode && !gameSetupActive;

	//
	// perform input

	G_INPUTCTX->perform();

	//
	// update game if it's started

	if( gameSetupActive ) {
		gUILabelTime->setVisible( false );
	} else {
		// if server state is starting, update it
		if( state.getServerState().state == GST_STARTING ) {
			gUILabelTime->setVisible( false );
			state.updateServerState( false, false );
		} else {
			gUILabelTime->setVisible( true );
			// update game state
			if( tmv - gLastGameUpdateTime >= time_value::fromsec(desc.getTurnDT()*0.5f) ) {
				// TBD: commands to dll
				net::updateGame( 0, 0, 0, state );
				gLastGameUpdateTime = tmv;
			}
		}
	}


	//
	// control time

	// TBD
	/*
	float gameTime = gi.getTime();
	float oldGameTime = gameTime;
	if( gUIBtnTimeRew->isPressed() )
		gameTime -= TURNS_PER_SEC * TIME_SPD_FAST * dt;
	if( gUIBtnTimeFfwd->isPressed() )
		gameTime += TURNS_PER_SEC * TIME_SPD_FAST * dt;
	if( gameTime != oldGameTime )
		gSetPlayMode( false );
	if( gPlayMode )
		gameTime += TURNS_PER_SEC * TIME_SPD_NORMAL * dt;
	if( gameTime < 0 )
		gameTime = 0;
	if( gameTime > replay.getGameTurnCount()-1 ) {
		gameTime = replay.getGameTurnCount()-1;
		gSetPlayMode( false );
	}
	gUIDlg->enableNonUserEvents( false );
	gUISliderTime->setValue( gameTime );
	gUIDlg->enableNonUserEvents( true );
	gi.setTime( gameTime );
	*/

	//
	// camera

	int selEntityID = gi.getEntities().getSelectedEntityID();
	const CActorEntity* selEntity = gi.getEntities().getActorEntityByID( selEntityID );
	bool hasSelected = (selEntity != NULL);
	if( hasSelected ) {
		SVector3 selPos = selEntity->mWorldMat.getOrigin();
		if( !gAppSettings.followMode ) {
			selPos.y = VIEWER_Y;
			SVector3 newPos = smoothCD( gViewer.getOrigin(), selPos, gViewerVel, 0.25f, dt );
			gTryPositionViewer( newPos, selPos );
		} else {
			//SVector3 selPrevPos = selEntity.samplePos( gi.getTime() - 10.0f );
			// TBD
			SVector3 selPrevPos = selPos;
			selPrevPos.y = (selPrevPos.y + VIEWER_Y)*0.5f;
			selPos.y = selPrevPos.y;
			SVector3 dirZ = selPos - selPrevPos;
			dirZ.y = 0.0f;
			const float MIN_DIST = 2.0f;
			if( dirZ.lengthSq() < MIN_DIST*MIN_DIST ) {
				dirZ = gViewer.getAxisZ();
				selPrevPos = selPrevPos - dirZ * MIN_DIST;
			}
			const float PREF_DIST = 5.0f;
			if( dirZ.lengthSq() < PREF_DIST*PREF_DIST ) {
				dirZ.normalize();
				selPrevPos = selPos - dirZ * PREF_DIST;
			} else {
				dirZ.normalize();
			}
			const float SMOOTHT = 0.5f;
			SVector3 newPos = smoothCD( gViewer.getOrigin(), selPrevPos, gViewerVel, SMOOTHT, dt );
			gTryPositionViewer( newPos, selPrevPos );
			dirZ = smoothCD( gViewer.getAxisZ(), dirZ, gViewerZVel, SMOOTHT, dt );
			if( dirZ.lengthSq() < 0.5f ) {
				dirZ = gViewer.getAxisZ();
			} else {
				gViewer.getAxisZ() = dirZ.getNormalized();
			}
			gViewer.getAxisY().set(0,1,0);
			gViewer.getAxisX() = gViewer.getAxisY().cross( gViewer.getAxisZ() );
		}
	} else {
		gViewerVel.set(0,0,0);
		gViewerZVel.set(0,0,0);
	}

	//
	// check if current viewer's position is valid

	{
		SVector3 testViewerPos = gViewer.getOrigin();
		int cx = testViewerPos.x;
		int cy = -testViewerPos.z;
		if( cx >= 0 && cy >= 0 && cx < gmap.getCellsX() && cy < gmap.getCellsY() && gmap.isBlood( gmap.getCell(cx,cy).type ) ) {
			gi.getLevelMesh().fitSphere( testViewerPos, VIEWER_R*2.0f );
			const float SMALL_FIT = 0.2f;
			if( SVector3(testViewerPos - gViewer.getOrigin()).lengthSq() < SMALL_FIT * SMALL_FIT ) {
				gLastViewerValidPos = testViewerPos;
			}
		}
	}

	SMatrix4x4& mm = gCamera.mWorldMat;
	mm = gViewer;
	float camnear, camfar, camfov, fognear, fogfar;
	if( !insideView ) {
		float tilt = gAppSettings.megaTilt;
		float zoom = gAppSettings.megaZoom;
		if( gameSetupActive ) {
			gUIGameSetupDlg->updateViewer( gViewer, tilt, zoom );
		}

		SMatrix4x4 mr;
		D3DXMatrixRotationX( &mr, D3DXToRadian( tilt ) );
		mm = mr * mm;
		mm.getOrigin() -= mm.getAxisZ() * zoom;

		camnear = (zoom - 15.0f) * 0.25f;
		camfar = (zoom + 10.0f) * 2.5f;
		camfov = D3DX_PI/3;
		fognear = (zoom + 10.0f) * 2.0f;
		fogfar = (zoom + 10.0f) * 2.3f;
		gFogColorParam.set( 0, 0, 0, 1 );
	} else {
		camnear = 0.3f;
		camfar = 60.0f;
		camfov = D3DX_PI/4;
		fognear = 20.0f;
		fogfar = camfar-1;
		gFogColorParam.set( 0.25f, 0, 0, 1 );
	}

	if( camnear < 0.1f )
		camnear = 0.1f;
	gCamera.setProjectionParams( camfov, dx.getBackBufferAspect(), camnear, camfar );
	gCamera.setOntoRenderContext();


	//
	// update entities and stats UI

	gMouseRay = gCamera.getWorldRay( gMouseX, gMouseY );
	const SVector3& eyePos = gCamera.mWorldMat.getOrigin();
	SLine3 mouseRay;
	mouseRay.pos = eyePos;
	mouseRay.vec = gMouseRay;

	float timeAlpha = (tmv - gi.getState().getTurnReceivedTime()).tosec() / desc.getTurnDT();
	if( timeAlpha >= 1.0f )
		timeAlpha = 1.0f;
	gi.getEntities().update( mouseRay, timeAlpha );
	
	// stats UI
	int nplayers = desc.getPlayerCount();
	for( int p = 0; p < nplayers; ++p ) {
		const CGameState::SPlayer& pl = state.getPlayer(p);
		SUIPlayerStats& plui = gUIPlayerStats[p];
		if( plui.score ) {
			itoa( pl.score, buf, 10 );
			plui.score->setText( buf );
		}
		if( plui.botCount ) {
			itoa( pl.botCount, buf, 10 );
			plui.botCount->setText( buf );
		}
	}

	// entity stats UI
	gUpdateSelEntityStats();
	gUpdateMissionStats();
	
	// time UI
	sprintf( buf, "%i", state.getTurn() );
	gUILabelTime->setText( buf );
	sprintf( buf, "fps: %.1f", dx.getStats().getFPS() );
	gUILabelFPS->setText( buf );

	gFogParam.set( fognear, fogfar, 1.0f/(fogfar-fognear), 0 );


	dx.clearTargets( true, true, true, insideView ? 0xFF400000 : 0xFF000000, 1.0f, insideView ? 1L : 0L );
	dx.sceneBegin();
	G_RENDERCTX->applyGlobalEffect();
	gi.getLevelMesh().render( RM_NORMAL, insideView ? (CLevelMesh::FULL) : (CLevelMesh::NOTOP) );
	gi.getPointsMesh().render( RM_NORMAL );
	gi.getEntities().render( RM_NORMAL, !insideView, insideView, timeAlpha );
	G_RENDERCTX->perform();

	// render GUI
	if( !gameSetupActive ) {
		gUIDlg->onRender( dt );
	}

	// render minimap
	if( gAppSettings.showMinimap && !gameSetupActive )
		gRenderMinimap();

	// render GUI #2
	if( gUISettingsDlg->getState() == CDemoSettingsDialog::STATE_ACTIVE ) {
		gUISettingsDlg->getDialog().onRender( dt );
	}
	if( gUIHelpDlg->isActive() ) {
		gUIHelpDlg->getDialog().onRender( dt );
	}
	if( gUIGameSetupDlg->getState() == CGameSetupDialog::STATE_ACTIVE ) {
		gUIGameSetupDlg->getDialog().onRender( dt );
	}

	dx.sceneEnd();
}
void CWall3D::fracturePiecesInSphere( float t, const SVector3& pos, float radius, TIntVector& pcs,
		float restoreAfter, float restoreDuration, bool noRestore )
{
	if( !mPiecesInited )
		initPieces();

	pcs.resize( 0 );
	
	// to local space
	SVector3 locPos;
	D3DXVec3TransformCoord( &locPos, &pos, &mInvMatrix );

	if( locPos.z < -radius || locPos.z > radius )
		return;

	// remember restore times
	if( mResTimeGrid && !noRestore ) {
		float rad = radius*2.0f;
		float lx1 = (locPos.x - rad) / mWall2D.getSize().x * RESGRID_X;
		float lx2 = (locPos.x + rad) / mWall2D.getSize().x * RESGRID_X;
		float ly1 = (locPos.y - rad) / mWall2D.getSize().y * RESGRID_Y;
		float ly2 = (locPos.y + rad) / mWall2D.getSize().y * RESGRID_Y;
		int ix1 = (int)clamp( lx1, 0, RESGRID_X-1 );
		int ix2 = (int)clamp( lx2, 0, RESGRID_X-1 );
		int iy1 = (int)clamp( ly1, 0, RESGRID_Y-1 );
		int iy2 = (int)clamp( ly2, 0, RESGRID_Y-1 );
		float dx = mWall2D.getSize().x / RESGRID_X;
		float dy = mWall2D.getSize().y / RESGRID_Y;
		for( int iy = iy1; iy <= iy2; ++iy ) {
			float* resval = mResTimeGrid + RESGRID_X*iy + ix1;
			float fy = iy * dy;
			for( int ix = ix1; ix <= ix2; ++ix, ++resval ) {
				float fx = ix * dx;

				// don't touch restore grid outside the circle
				float diffX = fx-locPos.x;
				float diffY = fy-locPos.y;
				float diffR2 = diffX*diffX + diffY*diffY;
				if( diffR2 > rad*rad )
					continue;

				// restore time for this grid point - start at
				// t+restoreAfter at circle boundaries, later at circle
				// center
				float resTime = t + restoreAfter + (1.0f-diffR2/(rad*rad)) * restoreDuration;

				if( *resval < 0.0f )
					*resval = resTime;
				else
					*resval = max( (*resval), resTime );
			}
		}
	}

	// fetch the pieces

	float pieceRestoreTime;
	if( noRestore ) {
		pieceRestoreTime = t + 1.0e9f;
	} else {
		pieceRestoreTime = t + restoreAfter + restoreDuration;
	}

	// TODO: optimize, right now linear search!
	int n = mWall2D.getPieceCount();
	for( int i = 0; i < n; ++i ) {
		const CWallPiece2D& p = mWall2D.getPiece( i );
		SVector2 c = p.getAABB().getCenter();
		SVector3 tocenter = locPos - SVector3(c.x,c.y,0);
		if( tocenter.lengthSq() < radius*radius ) {
			mPieceRestoreTimes[i] = pieceRestoreTime;
			if( mFracturedPieces[i] )
				continue;
			pcs.push_back( i );
			fractureOutPiece( i );
		}
	}
}