void CGameVolume_Water::SetupVolumeSegment(const WaterProperties& waterProperties, const uint32 segmentIndex, const Vec3* pVertices, const uint32 vertexCount) { SWaterSegment& segment = m_segments[segmentIndex]; IWaterVolumeRenderNode*& pWaterRenderNode = segment.m_pWaterRenderNode; CreateWaterRenderNode(pWaterRenderNode); CRY_ASSERT ( pWaterRenderNode != NULL ); const Matrix34& entityWorldTM = GetEntity()->GetWorldTM(); pWaterRenderNode->SetMinSpec( waterProperties.minSpec ); pWaterRenderNode->SetMaterialLayers( (uint8)waterProperties.materialLayerMask ); pWaterRenderNode->SetViewDistRatio( waterProperties.viewDistanceRatio ); Plane fogPlane; fogPlane.SetPlane( Vec3Constants<float>::fVec3_OneZ, pVertices[0] ); pWaterRenderNode->SetFogDensity( waterProperties.fogDensity ); pWaterRenderNode->SetFogColor( waterProperties.fogColor * max( waterProperties.fogColorMultiplier , 0.0f ) ); pWaterRenderNode->SetFogColorAffectedBySun( waterProperties.fogColorAffectedBySun ); pWaterRenderNode->SetFogShadowing( waterProperties.fogShadowing ); pWaterRenderNode->SetCapFogAtVolumeDepth( waterProperties.capFogAtVolumeDepth ); pWaterRenderNode->SetCaustics( waterProperties.caustics ); pWaterRenderNode->SetCausticIntensity( waterProperties.causticIntensity ); pWaterRenderNode->SetCausticTiling( waterProperties.causticTiling ); pWaterRenderNode->SetCausticHeight( waterProperties.causticHeight ); const Vec3* segmentVertices = pVertices; uint32 segmentVertexCount = vertexCount; Vec3 vertices[4]; if(waterProperties.isRiver) { FillOutRiverSegment(segmentIndex, pVertices, vertexCount, &vertices[0]); segmentVertices = &vertices[0]; segmentVertexCount = 4; } pWaterRenderNode->CreateArea( 0, &segmentVertices[0], segmentVertexCount, Vec2( waterProperties.uScale, waterProperties.vScale ), fogPlane, false ); pWaterRenderNode->SetMaterial( GetEntity()->GetMaterial() ); pWaterRenderNode->SetVolumeDepth( waterProperties.depth ); pWaterRenderNode->SetStreamSpeed( waterProperties.streamSpeed ); CreatePhysicsArea( segmentIndex, entityWorldTM, segmentVertices, segmentVertexCount, waterProperties.isRiver, waterProperties.streamSpeed ); // NOTE: // Set the matrix after everything has been setup in local space UpdateRenderNode( pWaterRenderNode, entityWorldTM ); }
void CLaserBeam::OnRayCastDataReceived( const QueuedRayID& rayID, const RayCastResult& result ) { CRY_ASSERT(m_pLaserParams); CRY_ASSERT(rayID == m_queuedRayId); m_queuedRayId = 0; const float range = m_pLaserParams->laser_range[eIGS_ThirdPerson]; float laserLength = range; Vec3 hitPos(0,0,0); bool hitSolid = false; if (result.hitCount > 0) { laserLength = result.hits[0].dist; hitPos = result.hits[0].pt; hitSolid = true; } else { hitPos = m_lastLaserUpdatePosition + (m_lastLaserUpdateDirection * range); laserLength = range + 0.1f; } const CCamera& camera = gEnv->pRenderer->GetCamera(); // Hit near plane if (m_lastLaserUpdateDirection.Dot(camera.GetViewdir()) < 0.0f) { Plane nearPlane; nearPlane.SetPlane(camera.GetViewdir(), camera.GetPosition()); nearPlane.d -= camera.GetNearPlane()+0.15f; Ray ray(m_lastLaserUpdatePosition, m_lastLaserUpdateDirection); Vec3 out; if (Intersect::Ray_Plane(ray, nearPlane, out)) { float dist = Distance::Point_Point(m_lastLaserUpdatePosition, out); if (dist < laserLength) { laserLength = dist; hitPos = out; hitSolid = true; } } } m_hasHitData = true; m_lastHit = hitPos; m_hitSolid = hitSolid; }
void CExactPositioningTrigger::Update( float frameTime, Vec3 userPos, Quat userOrient, bool allowTriggering ) { if (m_state == eS_Invalid) return; CRY_ASSERT(m_pos.IsValid()); CRY_ASSERT(m_userPos.IsValid()); CRY_ASSERT(m_orient.IsValid()); CRY_ASSERT(m_userOrient.IsValid()); CRY_ASSERT(m_posSize.IsValid()); CRY_ASSERT(NumberValid(m_cosOrientTolerance)); CRY_ASSERT(NumberValid(frameTime)); CRY_ASSERT(userPos.IsValid()); CRY_ASSERT(userOrient.IsValid()); m_userPos = userPos; m_userOrient = userOrient; if (m_state == eS_Initializing) m_state = eS_Before; Plane threshold; threshold.SetPlane( m_orient.GetColumn1(), m_pos ); if (threshold.DistFromPlane(userPos) >= 0.0f) { if (m_sideTime < 0.0f) m_sideTime = 0.0f; else m_sideTime += frameTime; } else { if (m_sideTime > 0.0f) m_sideTime = 0.0f; else m_sideTime -= frameTime; } Vec3 curDir = userOrient.GetColumn1(); Vec3 wantDir = m_orient.GetColumn1(); if (m_state == eS_Before) { OBB triggerBox; triggerBox.SetOBB( Matrix33(m_orient), m_posSize+Vec3(0.5f,0.5f,0), ZERO ); if (Overlap::Point_OBB(m_userPos, m_pos, triggerBox)) m_state = eS_Optimizing; } if ((m_state == eS_Optimizing) && allowTriggering) { #ifdef INCLUDE_EXACTPOS_DEBUGGING bool debug = (CAnimationGraphCVars::Get().m_debugExactPos != 0); CPersistantDebug* pPD = CCryAction::GetCryAction()->GetPersistantDebug(); #endif Vec3 bump(0.0f, 0.0f, 0.1f); Vec3 posDistanceError = m_userPos - m_pos; if ( posDistanceError.z > -1.0f && posDistanceError.z < 1.0f ) posDistanceError.z = 0; Vec3 orientFwd = m_orient.GetColumn1(); orientFwd.z = 0.0f; orientFwd.Normalize(); Vec3 rotAnimMovementWanted = orientFwd * m_animMovementLength; Vec3 userFwd = m_userOrient.GetColumn1(); userFwd.z = 0.0f; userFwd.Normalize(); Vec3 rotAnimMovementUser = userFwd * m_animMovementLength; float cosRotError = orientFwd.Dot( userFwd ); float rotError = CLAMP(m_cosOrientTolerance - cosRotError, 0.0f, 1.0f); //Vec3 rotDistanceError = rotAnimMovementUser - rotAnimMovementWanted; float fwdDistance = fabsf(orientFwd.Dot( posDistanceError )); float sideDistance = max( 0.0f, sqrtf( MAX(0,posDistanceError.GetLengthSquared2D() - sqr(fwdDistance)) ) - m_width ); float deltaFwd = m_oldFwdDir < fwdDistance ? fwdDistance - m_oldFwdDir : 0.0f; m_oldFwdDir = fwdDistance; fwdDistance += deltaFwd * 0.5f; deltaFwd = max(0.1f, deltaFwd); f32 distanceError = sqrtf(sqr(fwdDistance) + sqr(sideDistance)); // posDistanceError.len() * m_distanceErrorFactor; f32 temp = 1.0f-sqr(1.0f-rotError*rotError); temp = max(temp,0.0f); //never do a sqrtf with a negative value f32 orientError = sqrtf(temp) * m_animMovementLength; // rotDistanceError.len(); f32 totalDistanceError = distanceError + orientError; if (((m_distanceError * 1.05f) < distanceError) && ((m_orientError * 1.05f) < orientError) && (totalDistanceError < deltaFwd) || (totalDistanceError < deltaFwd*0.5f)) { // found local minimum in distance error, force triggering. m_state = eS_Triggered; m_oldFwdDir = 0.0f; #ifdef INCLUDE_EXACTPOS_DEBUGGING if (debug) { pPD->Begin("AnimationTrigger LocalMinima Triggered", false); pPD->AddPlanarDisc(m_pos + bump, 0.0f, m_distanceError, ColorF(0,1,0,0.5), 10.0f); } #endif } else { m_distanceError = m_distanceError > distanceError ? distanceError : m_distanceError * 0.999f; // should timeout in ~2 secs. on 50 FPS m_orientError = m_orientError > orientError ? orientError : m_orientError - 0.0001f; #ifdef INCLUDE_EXACTPOS_DEBUGGING if (debug) { pPD->Begin("AnimationTrigger LocalMinima Optimizing", true); pPD->AddPlanarDisc(m_pos + bump, 0.0f, m_distanceError, ColorF(1,1,0,0.5), 10.0f); } #endif } #ifdef INCLUDE_EXACTPOS_DEBUGGING if (debug) { pPD->AddLine(m_userPos + bump, m_pos + bump, ColorF(1,0,0,1), 10.0f); pPD->AddLine(m_userPos + rotAnimMovementUser + bump, m_pos + rotAnimMovementWanted + bump, ColorF(1,0,0,1), 10.0f); pPD->AddLine(m_pos + bump, m_pos + rotAnimMovementWanted + bump, ColorF(1,0.5,0,1), 10.0f); pPD->AddLine(m_userPos + bump, m_pos + rotAnimMovementUser + bump, ColorF(1,0.5,0,1), 10.0f); } #endif } CRY_ASSERT(m_pos.IsValid()); CRY_ASSERT(m_userPos.IsValid()); CRY_ASSERT(m_orient.IsValid()); CRY_ASSERT(m_userOrient.IsValid()); CRY_ASSERT(m_posSize.IsValid()); CRY_ASSERT(NumberValid(m_cosOrientTolerance)); }
//------------------------------------------------------------------ void CLam::UpdateTPLaser(float frameTime, CItem* parent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); const int frameId = gEnv->pRenderer->GetFrameID(); if (s_lastUpdateFrameId != frameId) { // Check how many LAMs to update this frame. float dt = frameTime; // + s_laserUpdateTimeError; const int n = s_lasers.size(); int nActive = 0; for (int i = 0; i < n; ++i) { if (!s_lasers[i]->IsLaserActivated() && !s_lasers[i]->IsLightActivated()) continue; nActive++; } float updatedPerSecond = (nActive / LASER_UPDATE_TIME) + s_laserUpdateTimeError; int updateCount = (int)floorf(updatedPerSecond * dt); if(dt==0.0f) s_laserUpdateTimeError = 0.0f; else s_laserUpdateTimeError = updatedPerSecond - updateCount/dt; s_curLaser %= n; for (int i = 0, j = 0; i < n && j < updateCount ; ++i) { s_curLaser = (s_curLaser + 1) % n; if (!s_lasers[s_curLaser]->IsLaserActivated() && !s_lasers[s_curLaser]->IsLightActivated()) continue; s_lasers[s_curLaser]->SetAllowUpdate(); ++j; } s_lastUpdateFrameId = frameId; } IEntity* pRootEnt = GetEntity(); if (!pRootEnt) return; IEntity *pLaserEntity = m_pEntitySystem->GetEntity(m_pLaserEntityId); // if(!pLaserEntity) // return; const CCamera& camera = gEnv->pRenderer->GetCamera(); Vec3 lamPos = pRootEnt->GetWorldPos(); //pLaserEntity->GetParent()->GetWorldPos(); Vec3 dir = pRootEnt->GetWorldRotation().GetColumn1(); //pLaserEntity->GetParent()->GetWorldRotation().GetColumn1(); bool charNotVisible = false; float dsg1Scale = 1.0f; //If character not visible, laser is not correctly updated if(parent) { if(CActor* pOwner = parent->GetOwnerActor()) { ICharacterInstance* pCharacter = pOwner->GetEntity()->GetCharacter(0); if(pCharacter && !pCharacter->IsCharacterVisible()) charNotVisible = true; } if(parent->GetEntity()->GetClass()==CItem::sDSG1Class) dsg1Scale = 3.0f; } // if (!pLaserEntity->GetParent()) // return; Vec3 hitPos(0,0,0); float laserLength = 0.0f; // HACK??: Use player movement controller locations, or else the laser // pops all over the place when character out of the screen. CActor *pActor = parent->GetOwnerActor(); if (pActor && (!pActor->IsPlayer() || charNotVisible)) { if (IMovementController* pMC = pActor->GetMovementController()) { SMovementState state; pMC->GetMovementState(state); if(!charNotVisible) lamPos = state.weaponPosition; else { float oldZPos = lamPos.z; lamPos = state.weaponPosition; if(m_lastZPos>0.0f) lamPos.z = m_lastZPos; //Stabilize somehow z position (even if not accurate) else lamPos.z = oldZPos; } const float angleMin = DEG2RAD(3.0f); const float angleMax = DEG2RAD(7.0f); const float thr = cosf(angleMax); float dot = dir.Dot(state.aimDirection); if (dot > thr) { float a = acos_tpl(dot); float u = 1.0f - clamp((a - angleMin) / (angleMax - angleMin), 0.0f, 1.0f); dir = dir + u * (state.aimDirection - dir); dir.Normalize(); } } } if(!charNotVisible) m_lastZPos = lamPos.z; lamPos += (dir*0.10f); if (m_allowUpdate) { m_allowUpdate = false; IPhysicalEntity* pSkipEntity = NULL; if(parent->GetOwner()) pSkipEntity = parent->GetOwner()->GetPhysics(); const float range = m_lamparams.laser_range[eIGS_ThirdPerson]*dsg1Scale; // Use the same flags as the AI system uses for visbility. const int objects = ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid|ent_independent; //ent_living; const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit); ray_hit hit; if (gEnv->pPhysicalWorld->RayWorldIntersection(lamPos, dir*range, objects, flags, &hit, 1, &pSkipEntity, pSkipEntity ? 1 : 0)) { laserLength = hit.dist; m_lastLaserHitPt = hit.pt; m_lastLaserHitSolid = true; } else { m_lastLaserHitSolid = false; m_lastLaserHitPt = lamPos + dir * range; laserLength = range + 0.1f; } // Hit near plane if (dir.Dot(camera.GetViewdir()) < 0.0f) { Plane nearPlane; nearPlane.SetPlane(camera.GetViewdir(), camera.GetPosition()); nearPlane.d -= camera.GetNearPlane()+0.15f; Ray ray(lamPos, dir); Vec3 out; m_lastLaserHitViewPlane = false; if (Intersect::Ray_Plane(ray, nearPlane, out)) { float dist = Distance::Point_Point(lamPos, out); if (dist < laserLength) { laserLength = dist; m_lastLaserHitPt = out; m_lastLaserHitSolid = true; m_lastLaserHitViewPlane = true; } } } hitPos = m_lastLaserHitPt; } else { laserLength = Distance::Point_Point(m_lastLaserHitPt, lamPos); hitPos = lamPos + dir * laserLength; } if (m_smoothLaserLength < 0.0f) m_smoothLaserLength = laserLength; else { if (laserLength < m_smoothLaserLength) m_smoothLaserLength = laserLength; else m_smoothLaserLength += (laserLength - m_smoothLaserLength) * min(1.0f, 10.0f * frameTime); } float laserAIRange = 0.0f; if (m_laserActivated && pLaserEntity) { // Orient the laser towards the point point. Matrix34 parentTMInv; parentTMInv = pRootEnt->GetWorldTM().GetInverted(); Vec3 localDir = parentTMInv.TransformPoint(hitPos); float finalLaserLen = localDir.NormalizeSafe(); Matrix33 rot; rot.SetIdentity(); rot.SetRotationVDir(localDir); pLaserEntity->SetLocalTM(rot); laserAIRange = finalLaserLen; const float assetLength = 2.0f; finalLaserLen = CLAMP(finalLaserLen,0.01f,m_lamparams.laser_max_len*dsg1Scale); float scale = finalLaserLen / assetLength; // Scale the laser based on the distance. if (m_laserEffectSlot >= 0) { Matrix33 scl; scl.SetIdentity(); scl.SetScale(Vec3(1,scale,1)); pLaserEntity->SetSlotLocalTM(m_laserEffectSlot, scl); } if (m_dotEffectSlot >= 0) { if (m_lastLaserHitSolid) { Matrix34 mt = Matrix34::CreateTranslationMat(Vec3(0,finalLaserLen,0)); if(m_lastLaserHitViewPlane) mt.Scale(Vec3(0.2f,0.2f,0.2f)); pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, mt); } else { Matrix34 scaleMatrix; scaleMatrix.SetIdentity(); scaleMatrix.SetScale(Vec3(0.001f,0.001f,0.001f)); pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, scaleMatrix); } } } float lightAIRange = 0.0f; if (m_lightActivated) { float range = clamp(m_smoothLaserLength, 0.5f, m_lamparams.light_range[eIGS_ThirdPerson]); lightAIRange = range * 1.5f; if (m_lightID[eIGS_ThirdPerson] && m_smoothLaserLength > 0.0f) { CItem* pLightEffect = this; if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) pLightEffect = (CItem *)pOwnerItem; pLightEffect->SetLightRadius(range, m_lightID[eIGS_ThirdPerson]); } } if (laserAIRange > 0.0001f || lightAIRange > 0.0001f) UpdateAILightAndLaser(lamPos, dir, lightAIRange, m_lamparams.light_fov[eIGS_ThirdPerson], laserAIRange); }
//---------------------------------------------------- void CRocketLauncher::UpdateTPLaser(float frameTime) { m_lastUpdate -= frameTime; bool allowUpdate = true; if(m_lastUpdate<=0.0f) m_lastUpdate = m_Timeout; else allowUpdate = false; const CCamera& camera = gEnv->pRenderer->GetCamera(); //If character not visible, laser is not correctly updated if(CActor* pOwner = GetOwnerActor()) { ICharacterInstance* pCharacter = pOwner->GetEntity()->GetCharacter(0); if(pCharacter && !pCharacter->IsCharacterVisible()) return; } Vec3 offset(-0.06f,0.28f,0.115f); //To match scope position in TP LAW model Vec3 pos = GetEntity()->GetWorldTM().TransformPoint(offset); Vec3 dir = GetEntity()->GetWorldRotation().GetColumn1(); Vec3 hitPos(0,0,0); float laserLength = 0.0f; if(allowUpdate) { IPhysicalEntity* pSkipEntity = NULL; if(GetOwner()) pSkipEntity = GetOwner()->GetPhysics(); const float range = m_LaserRangeTP; // Use the same flags as the AI system uses for visibility. const int objects = ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid|ent_independent; //ent_living; const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit); ray_hit hit; if (gEnv->pPhysicalWorld->RayWorldIntersection(pos, dir*range, objects, flags, &hit, 1, &pSkipEntity, pSkipEntity ? 1 : 0)) { laserLength = hit.dist; m_lastLaserHitPt = hit.pt; m_lastLaserHitSolid = true; } else { m_lastLaserHitSolid = false; m_lastLaserHitPt = pos + dir * range; laserLength = range + 0.1f; } // Hit near plane if (dir.Dot(camera.GetViewdir()) < 0.0f) { Plane nearPlane; nearPlane.SetPlane(camera.GetViewdir(), camera.GetPosition()); nearPlane.d -= camera.GetNearPlane()+0.15f; Ray ray(pos, dir); Vec3 out; m_lastLaserHitViewPlane = false; if (Intersect::Ray_Plane(ray, nearPlane, out)) { float dist = Distance::Point_Point(pos, out); if (dist < laserLength) { laserLength = dist; m_lastLaserHitPt = out; m_lastLaserHitSolid = true; m_lastLaserHitViewPlane = true; } } } hitPos = m_lastLaserHitPt; } else { laserLength = Distance::Point_Point(m_lastLaserHitPt, pos); hitPos = pos + dir * laserLength; } if (m_smoothLaserLength < 0.0f) m_smoothLaserLength = laserLength; else { if (laserLength < m_smoothLaserLength) m_smoothLaserLength = laserLength; else m_smoothLaserLength += (laserLength - m_smoothLaserLength) * min(1.0f, 10.0f * frameTime); } const float assetLength = 2.0f; m_smoothLaserLength = CLAMP(m_smoothLaserLength,0.01f,m_LaserRangeTP); float scale = m_smoothLaserLength / assetLength; // Scale the laser based on the distance. Matrix34 scl; scl.SetIdentity(); scl.SetScale(Vec3(1,scale,1)); scl.SetTranslation(offset); GetEntity()->SetSlotLocalTM( eIGS_Aux1, scl); if (m_dotEffectSlot >= 0) { if (m_lastLaserHitSolid) { Matrix34 dotMatrix = Matrix34::CreateTranslationMat(Vec3(0,m_smoothLaserLength,0)); dotMatrix.AddTranslation(offset); if(m_lastLaserHitViewPlane) dotMatrix.Scale(Vec3(0.2f,0.2f,0.2f)); GetEntity()->SetSlotLocalTM(m_dotEffectSlot,dotMatrix); } else { Matrix34 scaleMatrix; scaleMatrix.SetIdentity(); scaleMatrix.SetScale(Vec3(0.001f,0.001f,0.001f)); GetEntity()->SetSlotLocalTM(m_dotEffectSlot, scaleMatrix); } } }