void CAICorpseManager::DebugDraw() { if(g_pGameCVars->g_aiCorpses_DebugDraw == 0) return; IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); gEnv->pRenderer->Draw2dLabel( 50.0f, 50.0f, 1.5f, Col_White, false, "Corpse count %" PRISIZE_T " - Max %d", m_corpsesArray.size(), m_maxCorpses ); for(size_t i = 0; i < m_corpsesArray.size(); ++i) { CorpseInfo& corpse = m_corpsesArray[i]; CAICorpse* pCorpse = corpse.GetCorpse(); if(pCorpse != NULL) { AABB corpseBbox; pCorpse->GetEntity()->GetWorldBounds(corpseBbox); const Vec3 refPosition = corpseBbox.IsEmpty() ? pCorpse->GetEntity()->GetWorldPos() : corpseBbox.GetCenter(); gEnv->pRenderer->DrawLabel( refPosition, 1.5f, "%s\nPriority %d\n%s\n%s", pCorpse->GetEntity()->GetName(), pCorpse->GetPriority(), corpse.flags.AreAnyFlagsActive( CorpseInfo::eFlag_FarAway ) ? "Far away, remove when not visible" : "Not far away", corpse.flags.AreAllFlagsActive( CorpseInfo::eFlag_PhysicsDisabled) ? "Physics disabled" : "Physics enabled" ); pRenderAux->DrawCone( refPosition + Vec3(0.0f, 0.0f, 1.5f), Vec3(0.0f, 0.0f, -1.0f), 0.3f, 0.8f, Col_Red ); } } }
void CAIDebugRenderer::SetDepthWrite(bool bOn) { IRenderAuxGeom* pRenderAuxGeom = m_pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pRenderAuxGeom->GetRenderFlags(); flags.SetDepthWriteFlag(bOn ? e_DepthWriteOn : e_DepthWriteOff); pRenderAuxGeom->SetRenderFlags(flags); }
void CAIDebugRenderer::SetAlphaBlended(bool bOn) { IRenderAuxGeom* pRenderAuxGeom = m_pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pRenderAuxGeom->GetRenderFlags(); flags.SetAlphaBlendMode(bOn ? e_AlphaBlended : e_AlphaNone); pRenderAuxGeom->SetRenderFlags(flags); }
void CAIDebugRenderer::SetBackFaceCulling(bool bOn) { IRenderAuxGeom* pRenderAuxGeom = m_pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pRenderAuxGeom->GetRenderFlags(); flags.SetCullMode(bOn ? e_CullModeBack : e_CullModeNone); pRenderAuxGeom->SetRenderFlags(flags); }
void CAIDebugRenderer::SetDrawInFront(bool bOn) { IRenderAuxGeom* pRenderAuxGeom = m_pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pRenderAuxGeom->GetRenderFlags(); flags.SetDrawInFrontMode(bOn ? e_DrawInFrontOn : e_DrawInFrontOff); pRenderAuxGeom->SetRenderFlags(flags); }
void CGameVolume_Water::DebugDrawVolume() { IGameVolumes::VolumeInfo volumeInfo; if (GetVolumeInfoForEntity(GetEntityId(), volumeInfo) == false) return; if (volumeInfo.verticesCount < 3) return; const Matrix34 worldTM = GetEntity()->GetWorldTM(); const Vec3 depthOffset = worldTM.GetColumn2().GetNormalized() * - m_volumeDepth; IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); for (uint32 i = 0; i < volumeInfo.verticesCount - 1; ++i) { const Vec3 point1 = worldTM.TransformPoint(volumeInfo.pVertices[i]); const Vec3 point2 = worldTM.TransformPoint(volumeInfo.pVertices[i + 1]); pRenderAux->DrawLine( point1, Col_SlateBlue, point1 + depthOffset, Col_SlateBlue, 2.0f ); pRenderAux->DrawLine( point1 + depthOffset, Col_SlateBlue, point2 + depthOffset, Col_SlateBlue, 2.0f ); } const Vec3 firstPoint = worldTM.TransformPoint(volumeInfo.pVertices[0]); const Vec3 lastPoint = worldTM.TransformPoint(volumeInfo.pVertices[volumeInfo.verticesCount - 1]); pRenderAux->DrawLine( lastPoint, Col_SlateBlue, lastPoint + depthOffset, Col_SlateBlue, 2.0f ); pRenderAux->DrawLine( lastPoint + depthOffset, Col_SlateBlue, firstPoint + depthOffset, Col_SlateBlue, 2.0f ); }
void OnUpdate( SActivationInfo* pActInfo ) { const Vec3 positionOffsetLocal = GetPortVec3( pActInfo, PORT_IN_POSITION_OFFSET_LOCAL ); const float maxDistance = max( 0.f, GetPortFloat( pActInfo, PORT_IN_MAX_LENGTH ) ); const CCamera& camera = GetISystem()->GetViewCamera(); const Vec3 cameraDirection = camera.GetViewdir(); const Vec3 cameraPositionWorld = camera.GetPosition(); const Matrix33 cameraOrientation = Matrix33::CreateRotationVDir( cameraDirection ); const Vec3 positionOffsetWorld = cameraOrientation * positionOffsetLocal; const Vec3 rayOriginWorld = cameraPositionWorld + positionOffsetWorld; const Vec3 raySegment = cameraDirection * maxDistance; IPhysicalWorld* pWorld = gEnv->pPhysicalWorld; const int objectTypes = ent_all; const unsigned int raycastFlags = rwi_stop_at_pierceable | rwi_colltype_any; ray_hit hit; const int hitCount = pWorld->RayWorldIntersection( rayOriginWorld, raySegment, objectTypes, raycastFlags, &hit, 1 ); float hitDistance = maxDistance; if ( 0 < hitCount ) { hitDistance = hit.dist; } const float timeDelta = 0.1f; const float smoothTime = max( 0.f, GetPortFloat( pActInfo, PORT_IN_SMOOTH_TIME ) ); SmoothCD( m_smoothedHitDistance, m_hitDistanceChangeRate, timeDelta, hitDistance, smoothTime ); ActivateOutput( pActInfo, PORT_OUT_FOCUS_DISTANCE, m_smoothedHitDistance ); const float focusRangeFactor = max( 0.f, GetPortFloat( pActInfo, PORT_IN_FOCUS_RANGE_FACTOR ) ); const float focusRange = focusRangeFactor * m_smoothedHitDistance; ActivateOutput( pActInfo, PORT_OUT_FOCUS_RANGE, focusRange ); const bool drawDebugInfo = GetPortBool( pActInfo, PORT_IN_DEBUG_ENABLED ); if ( ! drawDebugInfo ) { return; } IRenderer* pRenderer = gEnv->pRenderer; IRenderAuxGeom* pRenderAuxGeom = pRenderer->GetIRenderAuxGeom(); ColorB rayColor = ( 0 < hitCount ) ? ColorB( 255, 255, 0 ) : ColorB( 255, 0, 0 ); pRenderAuxGeom->DrawSphere( hit.pt, 0.1f, rayColor ); pRenderAuxGeom->DrawLine( rayOriginWorld, rayColor, hit.pt, rayColor ); }
//------------------------------------------------------------------------ //chr safe to remove? bool CGunTurret::IsTargetCloaked(IActor *pActor) const { // cloak check if(m_turretparams.find_cloaked) return false; bool cloaked = false; // if destinationId assigned, target can always be found if(m_destinationId && pActor->GetEntityId() == m_destinationId) return false; if(cloaked && m_turretparams.light_fov != 0.f) { // if cloaked, target can only be found with searchlight // check if target inside light cone const Matrix34 &weaponTM = GetEntity()->GetSlotWorldTM(eIGS_ThirdPerson); Vec3 wpos(weaponTM.GetTranslation()); Vec3 wdir(weaponTM.GetColumn1()); Vec3 tpos(GetTargetPos(pActor->GetEntity())); float epsilon = 0.8f; Quat rot = Quat::CreateRotationAA(epsilon*0.5f*DEG2RAD(m_turretparams.light_fov), weaponTM.GetColumn2()); Vec3 a = wpos + m_turretparams.mg_range*(wdir*rot); Vec3 b = wpos + m_turretparams.mg_range*(wdir*rot.GetInverted()); bool inside = Overlap::PointInTriangle(tpos, wpos, a, b, weaponTM.GetColumn2()); if(inside) { rot = Quat::CreateRotationAA(0.5f*DEG2RAD(m_turretparams.light_fov), weaponTM.GetColumn0()); a = wpos + m_turretparams.mg_range*(wdir*rot); b = wpos + m_turretparams.mg_range*(wdir*rot.GetInverted()); inside = Overlap::PointInTriangle(tpos, wpos, a, b, weaponTM.GetColumn0()); } cloaked = !inside; if(g_pGameCVars->i_debug_turrets == eGTD_Search) { IRenderAuxGeom *pGeom = gEnv->pRenderer->GetIRenderAuxGeom(); pGeom->SetRenderFlags(e_Def3DPublicRenderflags); float color[] = {1,1,1,1}; Vec3 points[] = {wpos, a, b}; pGeom->DrawPolyline(points, 3, true, ColorB(0,255,0,255)); if(inside) gEnv->pRenderer->Draw2dLabel(200,200,1.4f,color,false,"target inside cone"); } } return cloaked; }
//------------------------------------------------------------------------ void CVehicleMovementStdBoat::DrawImpulse(const pe_action_impulse& action, const Vec3& offset, float scale, const ColorB& col) { if (!is_unused(action.impulse) && action.impulse.len2()>0) { IRenderAuxGeom* pGeom = gEnv->pRenderer->GetIRenderAuxGeom(); Vec3 start = action.point + offset; Vec3 end = start - (action.impulse*scale/m_pVehicle->GetMass()); Vec3 dir = (start-end).GetNormalizedSafe(); pGeom->DrawCone(start-1.f*dir, dir, 0.5f, 1.f, col); pGeom->DrawLine(start, col, end, col); pGeom->DrawSphere(end, 0.25f, col); } }
void DebugDrawLocation(const QuatT &location, ColorB colorPos, ColorB colorX, ColorB colorY, ColorB colorZ) { IRenderAuxGeom* pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); const float thickness = 7.0f; const Vec3 pushUp(0.0f, 0.03f, 0.0f); pAuxGeom->DrawLine(location.t + pushUp, colorX, location.t + pushUp + location.q.GetColumn0(), colorX, thickness); pAuxGeom->DrawLine(location.t + pushUp, colorY, location.t + pushUp + location.q.GetColumn1(), colorY, thickness); pAuxGeom->DrawLine(location.t + pushUp, colorZ, location.t + pushUp + location.q.GetColumn2(), colorZ, thickness); const float radius = 0.06f; pAuxGeom->DrawSphere(location.t + pushUp, radius, colorPos); }
void CPlayerVisTableDebugDraw::Update() { const float currentTime = gEnv->pTimer->GetCurrTime(); const float maxDebugLifeTime = 1.0f; IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); const ColorB visibleColor(0, 255, 0, 128); const ColorB hiddenColor(255, 0, 0, 128); const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; SAuxGeomRenderFlags oldRenderFlags = pRenderAux->GetRenderFlags(); SAuxGeomRenderFlags newRenderFlags = e_Def3DPublicRenderflags; newRenderFlags.SetAlphaBlendMode(e_AlphaBlended); newRenderFlags.SetDepthTestFlag(e_DepthTestOff); newRenderFlags.SetCullMode(e_CullModeNone); pRenderAux->SetRenderFlags(newRenderFlags); TDebugTargets::iterator targetIt = m_debugTargets.begin(); while (targetIt != m_debugTargets.end()) { SDebugInfo& targetInfo = *targetIt; const float lastUpdateAge = (currentTime - targetInfo.m_lastUpdatedTime); const bool remove = (lastUpdateAge > maxDebugLifeTime); if (!remove) { IEntity* pTargetEntity = gEnv->pEntitySystem->GetEntity(targetInfo.m_targetId); if (pTargetEntity) { const ColorB& color = targetInfo.m_visible ? visibleColor : hiddenColor; const Vec3 worldRefPosition = pTargetEntity->GetWorldTM().TransformPoint(targetInfo.m_localTargetPos); const Vec3 offset(0.0f, 0.0f, 0.4f); pRenderAux->DrawCone(worldRefPosition + offset, -Vec3Constants<float>::fVec3_OneZ, 0.125f, offset.z, color); gEnv->pRenderer->DrawLabelEx(worldRefPosition, 1.5f, white, true, false, "%.2f", lastUpdateAge); } ++targetIt; } else { TDebugTargets::iterator nextElement = m_debugTargets.erase(targetIt); targetIt = nextElement; } } pRenderAux->SetRenderFlags(oldRenderFlags); }
//------------------------------------------------------------------------ void CVehicleMovementTank::Update(const float deltaTime) { CVehicleMovementStdWheeled::Update(deltaTime); #if ENABLE_VEHICLE_DEBUG if (IsProfilingMovement()) { if (m_steeringImpulseMin > 0.f && m_wheelContactsLeft != 0 && m_wheelContactsRight != 0) { const Matrix34& worldTM = m_pVehicle->GetEntity()->GetWorldTM(); Vec3 localVel = worldTM.GetInvertedFast().TransformVector(m_statusDyn.v); Vec3 localW = worldTM.GetInvertedFast().TransformVector(m_statusDyn.w); float speed = m_statusDyn.v.len(); float speedRatio = min(1.f, speed/m_maxSpeed); const float maxW = 0.3f*gf_PI; float steer = abs(m_currSteer)>0.001f ? m_currSteer : 0.f; float desired = steer * maxW; float curr = -localW.z; float err = desired - curr; // err>0 means correction to right Limit(err, -maxW, maxW); if (abs(err) > 0.01f) { float amount = m_steeringImpulseMin + speedRatio*(m_steeringImpulseMax-m_steeringImpulseMin); float corr = -err * amount * m_statusDyn.mass * deltaTime; pe_action_impulse imp; imp.iApplyTime = 1; imp.angImpulse = worldTM.GetColumn2() * corr; float color[] = {1,1,1,1}; gEnv->pRenderer->Draw2dLabel(300,300,1.5f,color,false,"err: %.2f ", err); gEnv->pRenderer->Draw2dLabel(300,320,1.5f,color,false,"corr: %.3f", corr/m_statusDyn.mass); IRenderAuxGeom* pGeom = gEnv->pRenderer->GetIRenderAuxGeom(); float len = 4.f * imp.angImpulse.len() / deltaTime / m_statusDyn.mass; Vec3 dir = (float)-sgn(corr) * worldTM.GetColumn0(); //imp.angImpulse.GetNormalized(); pGeom->DrawCone(worldTM.GetTranslation()+Vec3(0,0,5)-(dir*len), dir, 0.5f, len, ColorB(128,0,0,255)); } } } DebugDrawMovement(deltaTime); #endif }
int CScriptBind_Game::DebugDrawCone( IFunctionHandler *pH, float x, float y, float z, float radius, float height, int r, int g, int b, int a ) { IRenderAuxGeom* pRenderAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); if (pRenderAuxGeom) { SAuxGeomRenderFlags oldFlags = pRenderAuxGeom->GetRenderFlags(); SAuxGeomRenderFlags newFlags = oldFlags; newFlags.SetCullMode(e_CullModeNone); newFlags.SetAlphaBlendMode(e_AlphaBlended); pRenderAuxGeom->SetRenderFlags(newFlags); pRenderAuxGeom->DrawCone(Vec3(x,y,z), Vec3(0.f, 0.f, 1.f), radius, height, ColorB(r,g,b,a)); pRenderAuxGeom->SetRenderFlags(oldFlags); } return pH->EndFunction(); }
int CScriptBind_Game::DebugDrawAABB( IFunctionHandler *pH, float x, float y, float z, float x2, float y2, float z2, int r, int g, int b, int a ) { IRenderAuxGeom* pRenderAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); if (pRenderAuxGeom) { SAuxGeomRenderFlags oldFlags = pRenderAuxGeom->GetRenderFlags(); SAuxGeomRenderFlags newFlags = oldFlags; newFlags.SetCullMode(e_CullModeNone); newFlags.SetAlphaBlendMode(e_AlphaBlended); pRenderAuxGeom->SetRenderFlags(newFlags); AABB bbox(Vec3(x, y, z), Vec3(x2, y2, z2)); pRenderAuxGeom->DrawAABB(bbox, true, ColorB(r, g, b, a), eBBD_Faceted); pRenderAuxGeom->SetRenderFlags(oldFlags); } return pH->EndFunction(); }
//------------------------------------------------------------------------ void CGameRulesHoldObjectiveBase::DebugDrawCylinder(SHoldEntityDetails *pDetails) { // Draw debug cylinder if(g_pGameCVars->g_holdObjectiveDebug == eHOB_Debug_Draw_Sphere) { IEntity *pHoldEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); if (pHoldEntity) { IRenderAuxGeom* pAuxRenderer = gEnv->pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags renderFlags = pAuxRenderer->GetRenderFlags(); renderFlags.SetAlphaBlendMode(e_AlphaBlended); pAuxRenderer->SetRenderFlags(renderFlags); pAuxRenderer->DrawCylinder( pHoldEntity->GetPos()+Vec3(0.f,0.f,pDetails->m_controlOffsetZ+(pDetails->m_controlHeight*0.5f)), Vec3(0.0f,0.0f,1.0f), pDetails->m_controlRadius, pDetails->m_controlHeight, ColorB(255,255,0,128)); } } }
void CHeavyMountedWeapon::Update( SEntityUpdateContext& ctx, int slot ) { BaseClass::Update(ctx, slot); if (m_rotatingSoundID!=INVALID_SOUNDID) { if (m_RotationSoundTimeOut>0) { m_RotationSoundTimeOut -= ctx.fFrameTime; RequireUpdate( eIUS_General ); } else { StopSound(m_rotatingSoundID); m_rotatingSoundID = INVALID_SOUNDID; } } // Helper for editor placing if (gEnv->IsEditing()) { // If host id is not 0, it means it is mounted to a vehicle, so don't render the helper in that case if (!GetHostId()) { IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); const Matrix34& weaponTM = GetEntity()->GetWorldTM(); const Vec3 point1 = weaponTM.GetTranslation(); const Vec3 point2 = point1 - (m_sharedparams->pMountParams->ground_distance * weaponTM.GetColumn2()); const Vec3 point3 = point2 - (m_sharedparams->pMountParams->body_distance * weaponTM.GetColumn1()); pRenderAux->DrawLine(point1, ColorB(0, 192, 0), point2, ColorB(0, 192, 0), 3.0f); pRenderAux->DrawLine(point2, ColorB(0, 192, 0), point3, ColorB(0, 192, 0), 3.0f); pRenderAux->DrawSphere(point3, 0.15f, ColorB(192, 0, 0)); RequireUpdate(eIUS_General); } } }
void SearchSpot::DebugDraw(float searchTimeOut) { ColorB spotColor; switch (m_status) { case NotSearchedYet: spotColor = ColorB(0, 0, 255); break; case BeingSearchedRightAboutNow: spotColor = ColorB(255, 255, 0); break; case Searched: spotColor = ColorB(0, 255, 0); break; case Unreachable: spotColor = ColorB(255, 0, 0); break; case SearchedTimingOut: if(searchTimeOut) { uint8 green = (uint8)(255 * clamp_tpl( (m_searchTimeoutLeft / (searchTimeOut / 2.0f)), 0.0f, 1.0f)); uint8 blue = (uint8)(255 * clamp_tpl(((searchTimeOut - m_searchTimeoutLeft) / (searchTimeOut / 2.0f)), 0.0f, 1.0f)); spotColor = ColorB(0, green, blue); } break; } IRenderAuxGeom* pDebugRenderer = gEnv->pRenderer->GetIRenderAuxGeom(); pDebugRenderer->DrawSphere(m_pos, 0.3f, spotColor); if (m_assigneeID) { Agent agent(m_assigneeID); if (agent) pDebugRenderer->DrawLine(agent.GetPos(), ColorB(255, 255, 0), m_pos, ColorB(255, 255, 0), 2.0f); } }
void SDebugCannonBallPenetration::Update(float frameTime) { IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags oldFlags = pRenderAux->GetRenderFlags(); SAuxGeomRenderFlags newFlags = e_Def3DPublicRenderflags; newFlags.SetAlphaBlendMode(e_AlphaBlended); newFlags.SetDepthTestFlag(e_DepthTestOff); newFlags.SetCullMode(e_CullModeNone); pRenderAux->SetRenderFlags(newFlags); const float baseDebugTimeOut = (g_pGameCVars->g_bulletPenetrationDebugTimeout > 0.0f) ? g_pGameCVars->g_bulletPenetrationDebugTimeout : DEFAULT_DEBUG_CannonBall_HIT_LIFETIME; for (int i = 0; i < MAX_DEBUG_CannonBall_HITS; ++i) { SDebugCannonBallHit& currentHit = m_hitsList[i]; if (currentHit.lifeTime <= 0.0f) { continue; } currentHit.lifeTime -= frameTime; //const float alpha = powf((currentHit.lifeTime / baseDebugTimeOut), 4.0f); // avoid powf whenever possible, for such simple cases, can do with 2 muls float alpha = (currentHit.lifeTime / baseDebugTimeOut); alpha *= alpha; alpha *= alpha; const ColorB red(255, 0, 0, (uint8)(192 * alpha)), green(0, 255, 0, (uint8)(192 * alpha)); const ColorB& hitColor = currentHit.stoppedCannonBall ? red : green; const Vec3 coneBase = currentHit.isBackFaceHit ? (currentHit.hitPosition + (currentHit.CannonBallDirection * 0.3f)) : (currentHit.hitPosition - (currentHit.CannonBallDirection * 0.2f)) ; const Vec3 lineEnd = (coneBase - (currentHit.CannonBallDirection * 0.3f)); pRenderAux->DrawCone(coneBase, currentHit.CannonBallDirection, 0.12f, 0.2f, hitColor); pRenderAux->DrawLine(coneBase, hitColor, lineEnd, hitColor, 3.0f); const Vec3 baseText = (currentHit.isBackFaceHit) ? coneBase + (0.2f * currentHit.CannonBallDirection) : lineEnd - (0.3f * currentHit.CannonBallDirection); const Vec3 textLineOffset(0.0f, 0.0f, 0.14f); const float textColor[4] = {1.0f, 1.0f, 1.0f, alpha}; gEnv->pRenderer->DrawLabelEx(baseText - (textLineOffset * 2.0f), 1.25f, textColor, true, false, "Damage: %.1f", currentHit.damage); gEnv->pRenderer->DrawLabelEx(baseText - (textLineOffset * 3.0f), 1.25f, textColor, true, false, "Pierceability: %d", currentHit.surfacePierceability); gEnv->pRenderer->DrawLabelEx(baseText - (textLineOffset * 4.0f), 1.25f, textColor, true, false, "%s", GetPenetrationLevelByPierceability(currentHit.surfacePierceability)); gEnv->pRenderer->DrawLabelEx(baseText - (textLineOffset * 5.0f), 1.25f, textColor, true, false, currentHit.tooThick ? "Too thick!" : "------"); } pRenderAux->SetRenderFlags(oldFlags); }
void CAutoAimManager::DebugDraw() { IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); const int numAutoaimTargets = m_autoaimTargets.size(); const Vec3 viewPos = gEnv->pSystem->GetViewCamera().GetPosition(); SAuxGeomRenderFlags oldFlags = pRenderAux->GetRenderFlags(); SAuxGeomRenderFlags newFlags = e_Def3DPublicRenderflags; newFlags.SetAlphaBlendMode(e_AlphaBlended); newFlags.SetDepthTestFlag(e_DepthTestOff); newFlags.SetCullMode(e_CullModeNone); pRenderAux->SetRenderFlags(newFlags); const ColorB enemyColor(255,0,0,128); const ColorB friendlyColor(0,255,0,128); const ColorB followColorInner(255,255,0,64); const ColorB followColorOuter(255,255,0,0); const ColorB snapColor(255,255,255,64); for(int i = 0; i < numAutoaimTargets; i++) { const SAutoaimTarget& aaTarget = m_autoaimTargets[i]; Vec3 dirToTarget = aaTarget.primaryAimPosition - viewPos; dirToTarget.NormalizeSafe(); const float snapRadius = aaTarget.HasFlagSet(eAATF_AIRadarTagged) ? aaTarget.snapRadiusTagged * g_pGameCVars->aim_assistSnapRadiusTaggedScale : aaTarget.snapRadius * g_pGameCVars->aim_assistSnapRadiusScale; pRenderAux->DrawSphere(aaTarget.primaryAimPosition, aaTarget.innerRadius, aaTarget.HasFlagSet(eAATF_AIHostile) ? enemyColor : friendlyColor); pRenderAux->DrawSphere(aaTarget.secondaryAimPosition, 0.2f, aaTarget.HasFlagSet(eAATF_AIHostile) ? enemyColor : friendlyColor); DrawDisc(aaTarget.primaryAimPosition, dirToTarget, aaTarget.innerRadius, aaTarget.outerRadius, followColorInner, followColorOuter); DrawDisc(aaTarget.primaryAimPosition, dirToTarget, aaTarget.outerRadius, snapRadius, followColorOuter, snapColor); } pRenderAux->SetRenderFlags(oldFlags); const float white[4] = {1.0f, 1.0f, 1.0f, 0.75f}; gEnv->pRenderer->Draw2dLabel(50.0f, 50.0f, 1.5f, white, false, "Number of targets: %d", numAutoaimTargets); }
void SearchGroup::Update() { IVisionMap& visionMap = *gEnv->pAISystem->GetVisionMap(); // Update vision { std::vector<SearchActor>::iterator actorIt = m_actors.begin(); std::vector<SearchActor>::iterator actorEnd = m_actors.end(); for ( ; actorIt != actorEnd; ++actorIt) { SearchActor& actor = (*actorIt); Agent agent(actor.entityID); if(!agent.IsValid()) continue; ObserverParams observerParams; observerParams.eyePosition = agent.GetPos(); observerParams.eyeDirection = agent.GetViewDir(); visionMap.ObserverChanged(actor.visionID, observerParams, eChangedPosition | eChangedOrientation); } } // Debug draw target pos if (g_pGameCVars->ai_DebugSearch) { IRenderAuxGeom* pDebugRenderer = gEnv->pRenderer->GetIRenderAuxGeom(); pDebugRenderer->DrawSphere(m_targetPos, 0.6f, ColorB(255, 255, 255, 128)); } const float frameTime = gEnv->pTimer->GetFrameTime(); std::vector<SearchSpot>::iterator spotIt = m_searchSpots.begin(); std::vector<SearchSpot>::iterator spotEnd = m_searchSpots.end(); for ( ; spotIt != spotEnd; ++spotIt) { SearchSpot& searchSpot = (*spotIt); if (g_pGameCVars->ai_DebugSearch) searchSpot.DebugDraw(m_searchSpotTimeout); if(searchSpot.IsTimingOut()) searchSpot.UpdateSearchedTimeout(frameTime); if (searchSpot.HasBeenSearched()) continue; // Naive Implementation! // Go through all the actors and see // if they see any of the search spots. // Later on, use a callback for this! SearchActorIter actorIt = m_actors.begin(); std::vector<SearchActor>::iterator actorEnd = m_actors.end(); for ( ; actorIt != actorEnd; ++actorIt) { SearchActor& actor = *actorIt; if (visionMap.IsVisible(actor.visionID, searchSpot)) { searchSpot.MarkAsSearchedBy(actor, m_searchSpotTimeout); break; } } } }
//------------------------------------------------------------------------ void CVehicleMovementStdBoat::Update(const float deltaTime) { CVehicleMovementBase::Update(deltaTime); SetAnimationSpeed(eVMA_Engine, abs(m_rpmScaleSgn)); if (m_inWater) { SetSoundParam(eSID_Run, "slip", 0.2f*abs(m_localSpeed.x)); } #if ENABLE_VEHICLE_DEBUG if (IsProfilingMovement() && g_pGameCVars->v_profileMovement != 2) { IEntity* pEntity = m_pVehicle->GetEntity(); const Matrix34& wTM = pEntity->GetWorldTM(); Matrix34 wTMInv = wTM.GetInvertedFast(); const SVehiclePhysicsStatus* physStatus = &m_physStatus[k_mainThread]; Vec3 localW = physStatus->q * physStatus->w; float speed = physStatus->v.len2() > 0.001f ? physStatus->v.len() : 0.f; float speedRatio = min(1.f, speed/(m_maxSpeed*m_factorMaxSpeed)); float absPedal = abs(m_movementAction.power); float absSteer = abs(m_movementAction.rotateYaw); static const float fSubmergedMin = 0.01f; static const float fWaterLevelMaxDiff = 0.15f; // max allowed height difference between propeller center and water level Vec3 worldPropPos = wTM * m_pushOffset; float waterLevelWorld = gEnv->p3DEngine->GetWaterLevel( &worldPropPos ); float fWaterLevelDiff = worldPropPos.z - waterLevelWorld; // wave stuff float waveFreq = 1.f; waveFreq += 3.f*speedRatio; float kx = m_waveIdleStrength.x*(m_waveRandomMult+0.3f) * (1.f-speedRatio + m_waveSpeedMult*speedRatio); float ky = m_waveIdleStrength.y * (1.f - 0.5f*absPedal - 0.5f*absSteer); Vec3 waveLoc = m_massOffset; waveLoc.y += speedRatio*min(0.f, m_pushOffset.y-m_massOffset.y); waveLoc = wTM * waveLoc; IRenderer* pRenderer = gEnv->pRenderer; static float color[4] = {1,1,1,1}; float colorRed[4] = {1,0,0,1}; float colorGreen[4] = {0,1,0,1}; float y=50.f, step1=15.f, step2=20.f, size1=1.3f, size2=1.5f; pRenderer->Draw2dLabel(5.0f, y, size2, color, false, "Boat movement"); pRenderer->Draw2dLabel(5.0f, y+=step2, size1, color, false, "Speed: %.1f (%.1f km/h)", speed, speed*3.6f); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "LocalW.z norm: %.2f", abs(localW.z)/m_turnRateMax); if (m_velLift > 0.f) { pRenderer->Draw2dLabel(5.0f, y+=step2, size1, m_lifted ? colorGreen : color, false, m_lifted ? "Lifted" : "not lifted"); //pRenderer->Draw2dLabel(5.0f, y+=step2, size1, color, false, "Impulse lift: %.0f", liftImp.impulse.len()); } pRenderer->Draw2dLabel(5.0f, y+=step1, size1, physStatus->submergedFraction > fSubmergedMin ? color : colorRed, false, "Submerged: %.2f", physStatus->submergedFraction); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, fWaterLevelDiff < fWaterLevelMaxDiff ? color : colorRed, false, "WaterLevel: %.2f (max: %.2f)", fWaterLevelDiff, fWaterLevelMaxDiff); pRenderer->Draw2dLabel(5.0f, y+=step2, size2, color, false, "Driver input"); pRenderer->Draw2dLabel(5.0f, y+=step2, size1, color, false, "power: %.2f", m_movementAction.power); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "steer: %.2f", m_movementAction.rotateYaw); pRenderer->Draw2dLabel(5.0f, y+=step2, size2, color, false, "Propelling"); //pRenderer->Draw2dLabel(5.0f, y+=step2, size1, color, false, "turnAccel (norm/real): %.2f / %.2f", turnAccelNorm, turnAccel); //pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "Impulse acc: %.0f", linearImp.impulse.len()); //pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "Impulse steer/damp: %.0f", angularImp.angImpulse.len()); //pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "Impulse corner: %.0f", dampImp.impulse.len()); pRenderer->Draw2dLabel(5.0f, y+=step2, size2, color, false, "Waves"); pRenderer->Draw2dLabel(5.0f, y+=step2, size1, color, false, "timer: %.1f", m_waveTimer); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "frequency: %.2f", waveFreq); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "random: %.2f", m_waveRandomMult); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "kX: %.2f", kx); pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "kY: %.2f", ky); if (Boosting()) pRenderer->Draw2dLabel(5.0f, y+=step1, size1, color, false, "Boost: %.2f", m_boostCounter); IRenderAuxGeom* pGeom = pRenderer->GetIRenderAuxGeom(); ColorB colorB(0,255,0,255); pRenderer->DrawLabel(worldPropPos, 1.3f, "WL: %.2f", waterLevelWorld); pGeom->DrawSphere(worldPropPos, 0.15f, colorB); pGeom->DrawSphere(waveLoc, 0.25f, colorB); pGeom->DrawLine(waveLoc, colorB, waveLoc+Vec3(0,0,2), colorB); // impulses //DrawImpulse(linearImp, Vec3(0,0,1), 3.f/deltaTime, ColorB(255,0,0,255)); //DrawImpulse(angularImp, Vec3(0,0,1), 2.f/deltaTime, ColorB(128,0,0,255)); //DrawImpulse(liftImp, Vec3(0,0,6), 2.f/deltaTime, ColorB(0,0,255,255)); } #endif }
//------------------------------------------------------------------------ void CDebugGun::Update( SEntityUpdateContext& ctx, int update) { if (!IsSelected()) return; static float drawColor[4] = {1,1,1,1}; static const int dx = 5; static const int dy = 15; static const float font = 1.2f; static const float fontLarge = 1.4f; IRenderer* pRenderer = gEnv->pRenderer; IRenderAuxGeom* pAuxGeom = pRenderer->GetIRenderAuxGeom(); pAuxGeom->SetRenderFlags(e_Def3DPublicRenderflags); pRenderer->Draw2dLabel(pRenderer->GetWidth()/5.f, pRenderer->GetHeight()-35, fontLarge, drawColor, false, "Firemode: %s (%.1f)", m_fireModes[m_fireMode].first.c_str(), m_fireModes[m_fireMode].second); ray_hit rayhit; int hits = 0; unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; if (m_fireModes[m_fireMode].first == "pierceability") { flags = (unsigned int)m_fireModes[m_fireMode].second & rwi_pierceability_mask; } // use cam, no need for firing pos/dir CCamera& cam = GetISystem()->GetViewCamera(); if (hits = gEnv->pPhysicalWorld->RayWorldIntersection(cam.GetPosition()+cam.GetViewdir(), cam.GetViewdir()*HIT_RANGE, ent_all, flags, &rayhit, 1)) { IMaterialManager* pMatMan = gEnv->p3DEngine->GetMaterialManager(); IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem(); int x = (int)(pRenderer->GetWidth() *0.5f) + dx; int y = (int)(pRenderer->GetHeight()*0.5f) + dx - dy; // draw normal ColorB colNormal(200,0,0,128); Vec3 end = rayhit.pt + 0.75f*rayhit.n; pAuxGeom->DrawLine(rayhit.pt, colNormal, end, colNormal); pAuxGeom->DrawCone(end, rayhit.n, 0.1f, 0.2f, colNormal); IEntity * pEntity = (IEntity*)rayhit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY); if(pEntity) { pRenderer->Draw2dLabel(x, y+=dy, fontLarge, drawColor, false, pEntity->GetName()); } // material const char* matName = pMatMan->GetSurfaceType(rayhit.surface_idx)->GetName(); if (matName[0]) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%s (%i)", matName, rayhit.surface_idx); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.1f m", rayhit.dist); if (pEntity) { IScriptTable* pScriptTable = pEntity->GetScriptTable(); // physics if (IPhysicalEntity* pPhysEnt = pEntity->GetPhysics()) { pe_status_dynamics status; if (pPhysEnt->GetStatus(&status)) { if (status.mass > 0.f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.1f kg", status.mass); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "pe_type: %i", pPhysEnt->GetType()); if (status.submergedFraction > 0.f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.2f submerged", status.submergedFraction); if (status.v.len2() > 0.0001f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.2f m/s", status.v.len()); } } if (pScriptTable) { HSCRIPTFUNCTION func = 0; if (pScriptTable->GetValue("GetFrozenAmount", func) && func) { float frozen = 0.f; Script::CallReturn(gEnv->pScriptSystem, func, pScriptTable, frozen); gEnv->pScriptSystem->ReleaseFunc(func); if (frozen > 0.f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "Frozen: %.2f", frozen); } } // class-specific stuff if (IActor* pActor = pActorSystem->GetActor(pEntity->GetId())) { pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%i health", pActor->GetHealth()); } else if (IVehicle* pVehicle = pVehicleSystem->GetVehicle(pEntity->GetId())) { const SVehicleStatus& status = pVehicle->GetStatus(); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.0f%% health", 100.f*status.health); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%i passengers", status.passengerCount); if (pVehicle->GetMovement() && pVehicle->GetMovement()->IsPowered()) { pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "Running"); } } else { if (pScriptTable) { HSCRIPTFUNCTION func = 0; if (pScriptTable->GetValue("GetHealth", func) && func) { float health = 0.f; if (Script::CallReturn(gEnv->pScriptSystem, func, pScriptTable, health)) { pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.0f health", health); } gEnv->pScriptSystem->ReleaseFunc(func); } } } } } }
//---------------------------------------------------------------------------- void CHomingMissile::UpdateCruiseMissile(float frameTime) { IRenderer* pRenderer = gEnv->pRenderer; IRenderAuxGeom* pGeom = pRenderer->GetIRenderAuxGeom(); float color[4] = {1,1,1,1}; const static float step = 15.f; float y = 20.f; bool bDebug = g_pGameCVars->i_debug_projectiles > 0; if (m_targetId) { IEntity* pTarget = gEnv->pEntitySystem->GetEntity(m_targetId); if (pTarget) { AABB box; pTarget->GetWorldBounds(box); SetDestination( box.GetCenter() ); //if (bDebug) //pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Target Entity: %s", pTarget->GetName()); } } else { // update destination pos from weapon static IItemSystem* pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem(); IItem* pItem = pItemSystem->GetItem(m_weaponId); if (pItem && pItem->GetIWeapon()) { const Vec3& dest = pItem->GetIWeapon()->GetDestination(); SetDestination( dest ); //if (bDebug) //pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Weapon Destination: (%.1f %.1f %.1f)", dest.x, dest.y, dest.z); } } pe_status_dynamics status; if (!GetEntity()->GetPhysics()->GetStatus(&status)) return; float currentSpeed = status.v.len(); Vec3 currentPos = GetEntity()->GetWorldPos(); Vec3 goalDir(ZERO); if (!m_destination.IsZero()) { if((currentPos-m_destination).len2()<(m_detonationRadius*m_detonationRadius)) { Explode(true, true, m_destination, -status.v.normalized(), status.v, m_targetId); return; } if (bDebug) pGeom->DrawCone(m_destination, Vec3(0,0,-1), 2.5f, 7.f, ColorB(255,0,0,255)); float heightDiff = (m_cruiseAltitude-m_alignAltitude) - currentPos.z; if (!m_isCruising && heightDiff * sgn(status.v.z) > 0.f) { // if heading towards align altitude (but not yet reached) accelerate to max speed if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] accelerating (%.1f / %.1f)", currentSpeed, m_maxSpeed); } else if (!m_isCruising && heightDiff * sgnnz(status.v.z) < 0.f && (status.v.z<0 || status.v.z>0.25f)) { // align to cruise if (currentSpeed != 0) { goalDir = status.v; goalDir.z = 0; goalDir.normalize(); } if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] aligning"); } else { if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] cruising..."); // cruise m_isCruising = true; if (!m_destination.IsZero()) { float groundDistSq = m_destination.GetSquaredDistance2D(currentPos); float distSq = m_destination.GetSquaredDistance(currentPos); float descendDistSq = sqr(m_descendDistance); if (m_isDescending || groundDistSq <= descendDistSq) { if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] descending!"); if (distSq != 0) goalDir = (m_destination - currentPos).normalized(); else goalDir.zero(); m_isDescending = true; } else { Vec3 airPos = m_destination; airPos.z = currentPos.z; goalDir = airPos - currentPos; if (goalDir.len2() != 0) goalDir.Normalize(); } } } } float desiredSpeed = currentSpeed; if (currentSpeed < m_maxSpeed-0.1f) { desiredSpeed = min(m_maxSpeed, desiredSpeed + m_accel*frameTime); } Vec3 currentDir = status.v.GetNormalizedSafe(FORWARD_DIRECTION); Vec3 dir = currentDir; if (!goalDir.IsZero()) { float cosine = max(min(currentDir.Dot(goalDir), 0.999f), -0.999f); float goalAngle = RAD2DEG(acos_tpl(cosine)); float maxAngle = m_turnSpeed * frameTime; if (bDebug) { pGeom->DrawCone( currentPos, goalDir, 0.4f, 12.f, ColorB(255,0,0,255) ); pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] goalAngle: %.2f", goalAngle); } if (goalAngle > maxAngle+0.05f) dir = (Vec3::CreateSlerp(currentDir, goalDir, maxAngle/goalAngle)).normalize(); else //if (goalAngle < 0.005f) dir = goalDir; } pe_action_set_velocity action; action.v = dir * desiredSpeed; GetEntity()->GetPhysics()->Action(&action); if (bDebug) { pGeom->DrawCone( currentPos, dir, 0.4f, 12.f, ColorB(128,128,0,255) ); pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] currentSpeed: %.1f (max: %.1f)", currentSpeed, m_maxSpeed); } }
//------------------------------------------------------------------------ Vec3 CGunTurret::GetSweepPos(IEntity *pTarget, const Vec3 &shootPos) { pTarget=ResolveTarget(pTarget); // sweep on ground int nhints = m_fireparams.hints.size(); float sweepTime = m_turretparams.sweep_time / (float)nhints; float timeFiring = max(0.f, GetBurstTime() - sweepTime*(m_fireHint-1)); float sweepRelTime = min(1.f, timeFiring/sweepTime); if(sweepRelTime == 1.f && m_fireHint == nhints) return shootPos; Vec3 wpos(GetWeaponPos()); Vec3 dir = shootPos - wpos; Vec3 dir2d(dir.x, dir.y, 0.f); float dist2d = dir2d.GetLength(); if(dist2d < 2.f*m_fireparams.hints[0].y) return shootPos; // don't sweep when target too close dir2d /= dist2d; Vec3 right = Vec3(0,0,-1) % dir2d; Vec3 zoffset(0,0,0); if(IPhysicalEntity *pPE = pTarget->GetPhysics()) { pe_status_pos ppos; if(pPE->GetStatus(&ppos)) zoffset=Vec3(0,0,-0.5f*(ppos.BBox[1].z-ppos.BBox[0].z)); } Vec3 lastHintPos(shootPos); const Vec2 &lastHint = m_fireparams.hints[m_fireHint-1]; lastHintPos += lastHint.y*-dir2d + lastHint.x*right + zoffset; Vec3 nextHintPos(shootPos); if(m_fireHint < nhints) { const Vec2 &nextHint = m_fireparams.hints[m_fireHint]; nextHintPos += nextHint.y*-dir2d + nextHint.x*right + zoffset; } Vec3 currPos = Vec3::CreateLerp(lastHintPos, nextHintPos, sweepRelTime); if(sweepRelTime == 1.f && m_fireHint < nhints) ++m_fireHint; if(g_pGameCVars->i_debug_turrets == eGTD_Sweep) { IRenderAuxGeom *pGeom = gEnv->pRenderer->GetIRenderAuxGeom(); pGeom->SetRenderFlags(e_Def3DPublicRenderflags); ColorB col(0,255,255,128); pGeom->DrawSphere(currPos, 0.3f, col); pGeom->DrawSphere(lastHintPos, 0.3f, col); pGeom->DrawSphere(nextHintPos, 0.3f, col); pGeom->DrawLine(lastHintPos, col, nextHintPos, col); gEnv->pRenderer->DrawLabel(currPos, 1.4f, "sweep, hint %i, ratio %.2f)", m_fireHint, sweepRelTime); } return currPos; }
void Draw() { IRenderAuxGeom* pRender = gEnv->pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pRender->GetRenderFlags(); SAuxGeomRenderFlags oldFlags = pRender->GetRenderFlags(); flags.SetDepthWriteFlag(e_DepthWriteOff); flags.SetDepthTestFlag(e_DepthTestOff); pRender->SetRenderFlags(flags); m_timer += gEnv->pTimer->GetFrameTime(); if (m_timer>30.f) m_timer = 0.f; float time = gEnv->pTimer->GetCurrTime(); float dt = (1.f/50.f); Vec3 offset = Vec3(0.f, 0.f, 0.025f + 0.003f*sinf(8.f*m_timer)); Vec3 offset2 = Vec3(0.f, 0.f, 0.035f + 0.003f*sinf(5.f*m_timer)); ColorB desiredColour = ColorB(255,0,0,255); // Red ColorB desiredVelColour = ColorB(255,(int)(128.f+127.f*sinf(8.f*m_timer)),0,255); // Yellow/Red ColorB actualPosColour = ColorB(0,255,0,255); // Green ColorB actualVelColour = ColorB(0,0,(int)(128.f+127.f*sinf(5.f*m_timer)),255); // blue/black ColorB snapPosColour = ColorB(255,255,255,255); // White ColorB lerpErrorColour = ColorB(255,0,0,255); // Red // Draw the desired positions for (unsigned int i=0; i<m_desired.size(); i++) { Desired &d = m_desired[i]; pRender->DrawSphere(d.pos + offset, 0.025f, desiredColour); pRender->DrawLine(d.pos + offset, desiredVelColour, d.pos + offset + d.vel*dt, desiredVelColour); } if(g_pGameCVars->pl_debugInterpolation == 1) // Show entity position + velocity { for (unsigned int i=0; i<m_actual.size(); i++) { Actual &a = m_actual[i]; pRender->DrawSphere(a.pos + offset2, 0.025f, a.snapped ? snapPosColour : actualPosColour); pRender->DrawLine(a.pos + offset2, actualVelColour, a.pos + offset2 + a.vel*dt, actualVelColour); } } if(g_pGameCVars->pl_debugInterpolation == 2) // Show entity position + lerpError { for (unsigned int i=0; i<m_actual.size(); i++) { Actual &a = m_actual[i]; pRender->DrawSphere(a.pos + offset2, 0.025f, a.snapped ? snapPosColour : actualPosColour); pRender->DrawLine(a.pos + offset2, lerpErrorColour, a.pos + offset2 + a.lerpError, lerpErrorColour); } } pRender->SetRenderFlags(oldFlags); }
void CClaymore::Update(SEntityUpdateContext &ctx, int updateSlot) { CProjectile::Update(ctx, updateSlot); bool debug = (g_pGameCVars->g_debugMines != 0); if(gEnv->bServer) { if(m_armed) { CGameRules* pGR = g_pGame->GetGameRules(); if(pGR) { for(std::list<EntityId>::iterator it = m_targetList.begin(); it != m_targetList.end(); ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*it); if(!pEntity) continue; // if this is a team game, claymores aren't set off by their own team... if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) continue; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) continue; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus) && physStatus.v.GetLengthSquared() > 0.01f) { // now check angle between this claymore and approaching object // to see if it is within the angular range m_triggerAngle. // If it is, then check distance is less than m_triggerRange, // and also check line-of-sight between the two entities. IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); AABB entityBBox; pEntity->GetWorldBounds(entityBBox); if(debug) { pRAG->DrawAABB( entityBBox, true, ColorF(1,0,0,0.4f), eBBD_Faceted ); } Vec3 enemyDir = entityBBox.GetCenter() - GetEntity()->GetPos(); Vec3 checkDir = enemyDir; checkDir.z = 0; float distanceSq = enemyDir.GetLengthSquared(); // for players a simple distance check is fine, but for vehicles use a better intersection check // so any corner of the vehicle going inside the zone sets off the claymore. static float playerRadius = 2.5f; bool inside = false; if(entityBBox.GetRadius() < playerRadius) { inside = (distanceSq < (m_triggerRadius * m_triggerRadius)); } else { static ray_hit hit; if(gEnv->pPhysicalWorld->CollideEntityWithBeam(pEntity->GetPhysics(), GetEntity()->GetWorldPos(), enemyDir, m_triggerRadius, &hit)) { inside = true; enemyDir = hit.pt - GetEntity()->GetWorldPos(); } } if(inside) { enemyDir.NormalizeSafe(); checkDir.NormalizeSafe(); float dotProd = checkDir.Dot(m_triggerDirection); if(debug) { pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(-m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } if(dotProd > cry_cosf(m_triggerAngle/2.0f)) { static const int objTypes = ent_all&(~ent_terrain); static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(GetEntity()->GetPos(), (enemyDir * m_triggerRadius * 1.5f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics()); bool bang = false; if (!col) bang = true; else if (entityBBox.IsContainPoint(hit.pt)) bang = true; else if (hit.pt.GetSquaredDistance(GetEntity()->GetWorldPos()) >= distanceSq) bang = true; if (bang) { // pass in the explosion normal, which is -m_triggerDirection Explode(true, false, Vec3(0,0,0), -m_triggerDirection); if(debug) { ColorF clr; clr.a = 0.3f; clr.g = 0.1f; clr.r = 1.0f; clr.b = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } } } } } } } } } else { m_timeToArm -= gEnv->pTimer->GetFrameTime(); if(m_timeToArm <= 0.0f) { m_armed = true; IEntityTriggerProxy *pTriggerProxy = (IEntityTriggerProxy*)(GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER)); if (!pTriggerProxy) { GetEntity()->CreateProxy(ENTITY_PROXY_TRIGGER); pTriggerProxy = (IEntityTriggerProxy*)GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER); } if(pTriggerProxy) { // create a trigger volume a couple of metres bigger than we need, to ensure we catch vehicles. // Checks above will still make sure the entity is within the radius before detonating though. float radius = m_triggerRadius + 2.0f; AABB boundingBox = AABB(Vec3(-radius,-radius,-radius), Vec3(radius,radius,radius)); pTriggerProxy->SetTriggerBounds(boundingBox); } } } } if(debug && m_armed) { IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); pRAG->DrawCylinder(GetEntity()->GetPos(), Vec3(0, 0, 1), m_triggerRadius, m_triggerRadius * 2.0f, clr); Vec3 size(m_triggerRadius + 2.0f, m_triggerRadius + 2.0f, m_triggerRadius + 2.0f); AABB box(GetEntity()->GetPos() - size, GetEntity()->GetPos() + size); pRAG->DrawAABB(box, false, ColorF(0.1f, 0.1f, 0.1f, 0.1f), eBBD_Faceted); pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + m_triggerDirection, clr, 5.0f); } }
void CNetPlayerInput::UpdateInterpolation() { Vec3 desiredPosition = m_curInput.position; Vec3 entPos = m_pPlayer->GetEntity()->GetPos(); Vec3 displacement = desiredPosition - entPos; displacement.z = 0.0f; float dist = displacement.len(); CTimeValue curTime=gEnv->pTimer->GetFrameStartTime(); Vec3 desiredVelocity = m_curInput.deltaMovement * g_pGameCVars->pl_netSerialiseMaxSpeed; m_netDesiredSpeed = desiredVelocity.GetLength2D(); if (m_newInterpolation) { InitialiseInterpolation(dist, displacement, desiredVelocity, curTime); } float dt = curTime.GetDifferenceInSeconds(m_netLastUpdate) + k_lerpTargetTime; dt = min(dt, k_maxPredictTime); m_predictedPosition = desiredPosition + (desiredVelocity * dt); Vec3 predOffset = m_predictedPosition - entPos; float predDist = predOffset.GetLength2D(); float lerpSpeed = (predDist/k_lerpTargetTime); lerpSpeed=clamp(lerpSpeed, k_minInterpolateSpeed, k_maxInterpolateSpeed); m_netLerpSpeed = lerpSpeed; UpdateErrorSnap(entPos, desiredPosition, dist, displacement, curTime); if (!m_passedNetPos && (m_initialDir.Dot(displacement) < 0.0f)) { m_passedNetPos = true; } Vec3 maxPrediction = desiredPosition + (desiredVelocity * k_maxPredictTime); if (m_passedNetPos && !m_passedPredictionPos && (m_initialDir.Dot(maxPrediction - entPos) < 0.0f)) { m_passedPredictionPos = true; } #if !defined(_RELEASE) if (g_pGameCVars->pl_debugInterpolation) { CryWatch("Cur: (%f, %f, %f) Des: (%f, %f, %f) Pred: (%f, %f, %f) ", entPos.x, entPos.y, entPos.z, desiredPosition.x, desiredPosition.y, desiredPosition.z, m_predictedPosition.x, m_predictedPosition.y, m_predictedPosition.z); CryWatch("BlockTime: (%f) PredictTime (%f) LastNetTime (%f) CurTime (%f)", m_blockedTime, dt, m_netLastUpdate.GetSeconds(), curTime.GetSeconds()); CryWatch("Lerp Speed: (%f) Passed pred pos (%d) Passed net pos (%d)", m_netLerpSpeed, m_passedPredictionPos, m_passedNetPos); CryWatch("InputSpeed: (%f, %f, %f) ", desiredVelocity.x, desiredVelocity.y, desiredVelocity.z); IRenderAuxGeom* pRender = gEnv->pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pRender->GetRenderFlags(); SAuxGeomRenderFlags oldFlags = pRender->GetRenderFlags(); flags.SetDepthWriteFlag(e_DepthWriteOff); flags.SetDepthTestFlag(e_DepthTestOff); pRender->SetRenderFlags(flags); pRender->DrawSphere(desiredPosition + Vec3(0.0f, 0.0f, 0.035f), 0.07f, ColorB(255,0,0,255)); pRender->DrawSphere(m_predictedPosition + Vec3(0.0f, 0.0f, 0.025f), 0.05f, ColorB(255,255,255,255)); pRender->SetRenderFlags(oldFlags); ColorF ballCol = m_passedPredictionPos ? ColorF(1.0f,1.0f,0.0f,0.75f) : (m_passedNetPos ? ColorF(1.0f,1.0f,1.0f,0.75f) : ColorF(0.0f,1.0f,0.0f,0.75f)); g_pGame->GetIGameFramework()->GetIPersistantDebug()->Begin("INTERPOLATION TRAIL", false); g_pGame->GetIGameFramework()->GetIPersistantDebug()->AddSphere(desiredPosition + Vec3(0.0f, 0.0f, 0.1f), 0.04f, ColorF(1.0f,0.0f,0.0f,0.75f), 30.f); g_pGame->GetIGameFramework()->GetIPersistantDebug()->AddSphere(m_predictedPosition + Vec3(0.0f, 0.0f, 0.1f), 0.03f, ColorF(0.0f,0.0f,1.0f,0.8f), 30.f); ballCol.a = 1.0f; g_pGame->GetIGameFramework()->GetIPersistantDebug()->AddSphere(entPos + Vec3(0.0f, 0.0f, 0.1f), 0.02f, ballCol, 30.f); g_pGame->GetIGameFramework()->GetIPersistantDebug()->AddLine(entPos + Vec3(0.0f, 0.0f, 0.1f), m_predictedPosition + Vec3(0.0f, 0.0f, 0.1f), ballCol, 30.f); } #endif //!_RELEASE }
void CVehiclePartSuspensionPart::Update(const float frameTime) { inherited::Update(frameTime); const Matrix34& parentTm = m_pParentPart->GetLocalTM(false); const Matrix34& targetTm = m_targetPart->GetLocalTM(false); Vec3 pos = parentTm * m_pos0; Vec3 targetPos = (m_ikFlags&k_flagIgnoreTargetRotation) ? (targetTm.GetColumn3() + m_targetOffset) : (targetTm * m_targetOffset); Vec3 dir = targetPos - pos; float length = dir.GetLength(); if (length > 1e-2f) { Matrix33 rot = Matrix33::CreateRotationV0V1(m_direction0, dir*(1.f/length)); Matrix33 partRot = rot*Matrix33(m_initialRot); if (m_mode==k_modeRotate || m_mode==k_modeSnapToEF) { if (m_mode==k_modeSnapToEF) { pos = targetPos - rot * m_direction0; } Matrix34 tm(partRot, pos); SetLocalTM(tm); } else if (m_mode==k_modeStretch) { const float scale = length * m_invLength0; const Vec3 z = m_direction0; const Vec3 sz = m_direction0*(scale-1.f); Matrix33 scaleM; scaleM.m00 = 1.f+sz.x*z.x; scaleM.m01 = sz.y*z.x ; scaleM.m02 = sz.z*z.x; scaleM.m10 = sz.x*z.y ; scaleM.m11 = 1.f+sz.y*z.y; scaleM.m12 = sz.z*z.y; scaleM.m20 = sz.x*z.z ; scaleM.m21 = sz.y*z.z ; scaleM.m22 = 1.f+sz.z*z.z; Matrix34 tm(partRot * scaleM, pos); SetLocalTM(tm); } } #if !defined(_RELEASE) if (VehicleCVars().v_debugSuspensionIK) { IRenderAuxGeom* pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); SAuxGeomRenderFlags flags = pAuxGeom->GetRenderFlags(); SAuxGeomRenderFlags oldFlags = pAuxGeom->GetRenderFlags(); flags.SetDepthWriteFlag(e_DepthWriteOff); flags.SetDepthTestFlag(e_DepthTestOff); pAuxGeom->SetRenderFlags(flags); ColorB colRed(255,0,0,255); ColorB colBlue(0,0,255,255); ColorB colWhite(255,255,255,255); ColorB colGreen(0,255,0,255); pos = m_pVehicle->GetEntity()->GetWorldTM() * pos; targetPos = m_pVehicle->GetEntity()->GetWorldTM() * targetPos; pAuxGeom->DrawSphere(pos, 0.02f, colGreen); pAuxGeom->DrawSphere(targetPos, 0.02f, colBlue); pAuxGeom->DrawLine(pos, colWhite, targetPos, colWhite); } #endif }
void CPersistantDebug::Update( float frameTime ) { if (m_objects.empty()) return; IRenderAuxGeom * pAux = gEnv->pRenderer->GetIRenderAuxGeom(); static const int flags3D = e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn; static const int flags2D = e_Mode2D | e_AlphaBlended; std::vector<ListObj::iterator> toClear; std::vector<MapListObj::iterator> toClearMap; for (MapListObj::iterator iterMap = m_objects.begin(); iterMap != m_objects.end(); ++iterMap) { toClear.resize(0); for (ListObj::iterator iterList = iterMap->second.begin(); iterList != iterMap->second.end(); ++iterList) { iterList->timeRemaining -= frameTime; if (iterList->timeRemaining <= 0.0f && !(iterList->obj == eOT_EntityTag && iterList->columns.size() > 1)) toClear.push_back(iterList); else { ColorF clr = iterList->clr; clr.a *= iterList->timeRemaining / iterList->totalTime; switch (iterList->obj) { case eOT_Sphere: pAux->SetRenderFlags( flags3D ); pAux->DrawSphere( iterList->pos, iterList->radius, clr ); break; case eOT_Quat: pAux->SetRenderFlags( flags3D ); { float r = iterList->radius; Vec3 x = r * iterList->q.GetColumn0(); Vec3 y = r * iterList->q.GetColumn1(); Vec3 z = r * iterList->q.GetColumn2(); Vec3 p = iterList->pos; OBB obb = OBB::CreateOBB( Matrix33::CreateIdentity(), Vec3(0.05f,0.05f,0.05f), ZERO ); pAux->DrawOBB( obb, p, false, clr, eBBD_Extremes_Color_Encoded ); pAux->DrawLine( p, ColorF(1,0,0,clr.a), p+x, ColorF(1,0,0,clr.a) ); pAux->DrawLine( p, ColorF(0,1,0,clr.a), p+y, ColorF(0,1,0,clr.a) ); pAux->DrawLine( p, ColorF(0,0,1,clr.a), p+z, ColorF(0,0,1,clr.a) ); } break; case eOT_Arrow: pAux->SetRenderFlags( flags3D ); pAux->DrawLine( iterList->pos - iterList->dir * iterList->radius, clr, iterList->pos + iterList->dir * iterList->radius, clr ); pAux->DrawCone( iterList->pos + iterList->dir * iterList->radius, iterList->dir, 0.1f * iterList->radius, 0.3f * iterList->radius, clr ); break; case eOT_Line: pAux->SetRenderFlags( flags3D ); pAux->DrawLine( iterList->pos, clr, iterList->pos + iterList->dir, clr ); break; case eOT_Cone: pAux->SetRenderFlags( flags3D ); pAux->DrawCone( iterList->pos, iterList->dir, iterList->radius, iterList->radius2, clr ); break; case eOT_Cylinder: pAux->SetRenderFlags( flags3D ); pAux->DrawCylinder( iterList->pos, iterList->dir, iterList->radius, iterList->radius2, clr ); break; case eOT_AABB: pAux->SetRenderFlags( flags3D ); pAux->DrawAABB( AABB(iterList->pos,iterList->dir), Matrix34(IDENTITY), false, clr, eBBD_Faceted ); break; case eOT_Line2D: pAux->SetRenderFlags( flags2D ); pAux->DrawLine( iterList->pos, clr, iterList->dir, clr ); break; case eOT_Text: { float clrAry[4] = {clr.r, clr.g, clr.b, clr.a}; gEnv->pRenderer->Draw2dLabel( iterList->pos.x, iterList->pos.y, iterList->radius, clrAry, false, "%s", iterList->text.c_str() ); } break; case eOT_Disc: { pAux->SetRenderFlags( flags3D ); vtx_idx indTriQuad[ 6 ] = { 0, 2, 1, 0, 3, 2 }; vtx_idx indTriTri[ 3 ] = { 0, 1, 2 }; int steps = (int)(10 * iterList->radius2); steps = std::max(steps, 10); float angStep = gf_PI2 / steps; for (int i=0; i<steps; i++) { float a0 = angStep*i; float a1 = angStep*(i+1); float c0 = cosf( a0 ); float c1 = cosf( a1 ); float s0 = sinf( a0 ); float s1 = sinf( a1 ); Vec3 pts[4]; int n, n2; vtx_idx * indTri; if (iterList->radius) { n = 4; n2 = 6; pts[0] = iterList->pos + iterList->radius * Vec3( c0, s0, 0 ); pts[1] = iterList->pos + iterList->radius * Vec3( c1, s1, 0 ); pts[2] = iterList->pos + iterList->radius2 * Vec3( c1, s1, 0 ); pts[3] = iterList->pos + iterList->radius2 * Vec3( c0, s0, 0 ); indTri = indTriQuad; } else { n = 3; n2 = 3; pts[0] = iterList->pos; pts[1] = pts[0] + iterList->radius2 * Vec3( c0, s0, 0 ); pts[2] = pts[0] + iterList->radius2 * Vec3( c1, s1, 0 ); indTri = indTriTri; } pAux->DrawTriangles( pts, n, indTri, n2, clr ); } } break; case eOT_EntityTag: { UpdateTags(frameTime, *iterList); } break; } } } while (!toClear.empty()) { iterMap->second.erase(toClear.back()); toClear.pop_back(); } if (iterMap->second.empty()) toClearMap.push_back(iterMap); } while (!toClearMap.empty()) { m_objects.erase(toClearMap.back()); toClearMap.pop_back(); } }
//------------------------------------------------------------------------ void CVehicleMovementStdBoat::UpdateSurfaceEffects(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); if (0 == g_pGameCVars->v_pa_surface) { ResetParticles(); return; } IEntity* pEntity = m_pVehicle->GetEntity(); const Matrix34& worldTM = pEntity->GetWorldTM(); float distSq = worldTM.GetTranslation().GetSquaredDistance(gEnv->pRenderer->GetCamera().GetPosition()); if (distSq > sqr(300.f) || (distSq > sqr(50.f) && !m_pVehicle->GetGameObject()->IsProbablyVisible())) return; Matrix34 worldTMInv = worldTM.GetInverted(); const SVehicleStatus& status = m_pVehicle->GetStatus(); float velDot = status.vel * worldTM.GetColumn1(); float powerNorm = min(abs(m_movementAction.power), 1.f); SEnvironmentParticles* envParams = m_pPaParams->GetEnvironmentParticles(); SEnvParticleStatus::TEnvEmitters::iterator end = m_paStats.envStats.emitters.end(); for (SEnvParticleStatus::TEnvEmitters::iterator emitterIt = m_paStats.envStats.emitters.begin(); emitterIt!=end; ++emitterIt) { if (emitterIt->layer < 0) { assert(0); continue; } const SEnvironmentLayer& layer = envParams->GetLayer(emitterIt->layer); SEntitySlotInfo info; info.pParticleEmitter = 0; pEntity->GetSlotInfo(emitterIt->slot, info); float countScale = 1.f; float sizeScale = 1.f; float speedScale = 1.f; float speed = 0.f; // check if helper position is beneath water level Vec3 emitterWorldPos = worldTM * emitterIt->quatT.t; float waterLevel = gEnv->p3DEngine->GetWaterLevel(&emitterWorldPos); int matId = 0; if (emitterWorldPos.z <= waterLevel+0.1f && m_physStatus[k_mainThread].submergedFraction<0.999f) { matId = gEnv->pPhysicalWorld->GetWaterMat(); speed = status.speed; bool spray = !strcmp(layer.GetName(), "spray"); if (spray) { // slip based speed -= abs(velDot); } GetParticleScale(layer, speed, powerNorm, countScale, sizeScale, speedScale); } else { countScale = 0.f; } if (matId && matId != emitterIt->matId) { // change effect IParticleEffect* pEff = 0; const char* effect = GetEffectByIndex( matId, layer.GetName() ); if (effect && (pEff = gEnv->pParticleManager->FindEffect(effect))) { #if ENABLE_VEHICLE_DEBUG if (DebugParticles()) CryLog("%s changes water sfx to %s (slot %i)", pEntity->GetName(), effect, emitterIt->slot); #endif if (info.pParticleEmitter) { info.pParticleEmitter->Activate(false); pEntity->FreeSlot(emitterIt->slot); } emitterIt->slot = pEntity->LoadParticleEmitter(emitterIt->slot, pEff); if (emitterIt->slot != -1) pEntity->SetSlotLocalTM(emitterIt->slot, Matrix34(emitterIt->quatT)); info.pParticleEmitter = 0; pEntity->GetSlotInfo(emitterIt->slot, info); } else countScale = 0.f; } if (matId) emitterIt->matId = matId; if (info.pParticleEmitter) { SpawnParams sp; sp.fSizeScale = sizeScale; sp.fCountScale = countScale; sp.fSpeedScale = speedScale; info.pParticleEmitter->SetSpawnParams(sp); if (layer.alignToWater && countScale > 0.f) { Vec3 worldPos(emitterWorldPos.x, emitterWorldPos.y, waterLevel+0.05f); Matrix34 localTM(emitterIt->quatT); localTM.SetTranslation(worldTMInv * worldPos); pEntity->SetSlotLocalTM(emitterIt->slot, localTM); } } #if ENABLE_VEHICLE_DEBUG if (DebugParticles() && m_pVehicle->IsPlayerDriving()) { float color[] = {1,1,1,1}; ColorB red(255,0,0,255); IRenderAuxGeom* pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); const char* effect = info.pParticleEmitter ? info.pParticleEmitter->GetName() : ""; const Matrix34& slotTM = m_pEntity->GetSlotWorldTM(emitterIt->slot); Vec3 ppos = slotTM.GetTranslation(); pAuxGeom->DrawSphere(ppos, 0.2f, red); pAuxGeom->DrawCone(ppos, slotTM.GetColumn1(), 0.1f, 0.5f, red); gEnv->pRenderer->Draw2dLabel(50.f, (float)(400+10*emitterIt->slot), 1.2f, color, false, "<%s> water fx: slot %i [%s], speed %.1f, sizeScale %.2f, countScale %.2f (pos %.0f,%0.f,%0.f)", pEntity->GetName(), emitterIt->slot, effect, speed, sizeScale, countScale, ppos.x, ppos.y, ppos.z); } #endif } // generate water splashes Vec3 wakePos; if(m_pSplashPos) { wakePos = m_pSplashPos->GetWorldSpaceTranslation(); } else { wakePos = worldTM.GetTranslation(); } float wakeWaterLevel = gEnv->p3DEngine->GetWaterLevel(&wakePos); const Vec3& localW = m_localSpeed; if (localW.x >= 0.f) m_diving = false; if (!m_diving && localW.x < -0.03f && status.speed > 10.f && wakePos.z < m_lastWakePos.z && wakeWaterLevel+0.1f >= wakePos.z) { float speedRatio = min(1.f, status.speed/(m_maxSpeed*m_factorMaxSpeed)); m_diving = true; if (m_pWaveEffect) { if (IParticleEmitter* pEmitter = pEntity->GetParticleEmitter(m_wakeSlot)) { pEmitter->Activate(false); pEntity->FreeSlot(m_wakeSlot); m_wakeSlot = -1; } SpawnParams spawnParams; spawnParams.fSizeScale = spawnParams.fCountScale = 0.5f + 0.25f*speedRatio; spawnParams.fSizeScale += 0.4f*m_waveRandomMult; spawnParams.fCountScale += cry_random(0.0f, 0.4f); m_wakeSlot = pEntity->LoadParticleEmitter(m_wakeSlot, m_pWaveEffect, &spawnParams); } // handle splash sound ExecuteTrigger(eSID_Splash); SetSoundParam(eSID_Splash, "intensity", 0.2f*speedRatio + 0.5f*m_waveRandomMult); if (m_rpmPitchDir == 0) { m_rpmPitchDir = -1; m_waveSoundPitch = 0.f; m_waveSoundAmount = 0.02f + m_waveRandomMult*0.08f; } } if (m_wakeSlot != -1) { // update emitter local pos to short above waterlevel Matrix34 tm; if(m_pSplashPos) m_pSplashPos->GetVehicleTM(tm); else tm.SetIdentity(); Vec3 pos = tm.GetTranslation(); pos.z = worldTMInv.TransformPoint(Vec3(wakePos.x,wakePos.y,wakeWaterLevel)).z + 0.2f; tm.SetTranslation(pos); pEntity->SetSlotLocalTM(m_wakeSlot, tm); #if ENABLE_VEHICLE_DEBUG if (IsProfilingMovement()) { Vec3 wPos = worldTM * tm.GetTranslation(); ColorB col(128, 128, 0, 200); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(wPos, 0.4f, col); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(wPos, col, wPos+Vec3(0,0,1.5f), col); } #endif } m_lastWakePos = wakePos; }