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; } }
/** * 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 ); } } }