void LightCPURenderThread::ConnectToEye(const float u0, const BSDF &bsdf, const Point &lensPoint, const Spectrum &flux, vector<SampleResult> &sampleResults) { LightCPURenderEngine *engine = (LightCPURenderEngine *)renderEngine; Scene *scene = engine->renderConfig->scene; Vector eyeDir(bsdf.hitPoint - lensPoint); const float eyeDistance = eyeDir.Length(); eyeDir /= eyeDistance; BSDFEvent event; Spectrum bsdfEval = bsdf.Evaluate(-eyeDir, &event); if (!bsdfEval.Black()) { const float epsilon = Max(MachineEpsilon::E(lensPoint), MachineEpsilon::E(eyeDistance)); Ray eyeRay(lensPoint, eyeDir, epsilon, eyeDistance - epsilon); float scrX, scrY; if (scene->camera->GetSamplePosition(lensPoint, eyeDir, eyeDistance, &scrX, &scrY)) { RayHit eyeRayHit; BSDF bsdfConn; Spectrum connectionThroughput; if (!scene->Intersect(device, true, u0, &eyeRay, &eyeRayHit, &bsdfConn, &connectionThroughput)) { // Nothing was hit, the light path vertex is visible const float cosToCamera = Dot(bsdf.shadeN, -eyeDir); const float cosAtCamera = Dot(scene->camera->GetDir(), eyeDir); const float cameraPdfW = 1.f / (cosAtCamera * cosAtCamera * cosAtCamera * scene->camera->GetPixelArea()); const float cameraPdfA = PdfWtoA(cameraPdfW, eyeDistance, cosToCamera); const float fluxToRadianceFactor = cameraPdfA; const Spectrum radiance = connectionThroughput * flux * fluxToRadianceFactor * bsdfEval; AddSampleResult(sampleResults, PER_SCREEN_NORMALIZED, scrX, scrY, radiance, 1.f); } } } }
//----------------------------------------------------------------------------- void CHomingMissile::UpdateControlledMissile(float frameTime) { bool isServer = gEnv->bServer; bool isClient = gEnv->bClient; CActor *pClientActor=0; if (gEnv->bClient) pClientActor=static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor()); bool isOwner = ((!m_ownerId && isServer) || (isClient && pClientActor && (pClientActor->GetEntityId() == m_ownerId) && pClientActor->IsPlayer())); 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 (isOwner || isServer) { //If there's a target, follow the target if(isServer) { if (m_targetId) { if (m_lockedTimer>0.0f) m_lockedTimer=m_lockedTimer-frameTime; else { // If we are here, there's a target IEntity* pTarget = gEnv->pEntitySystem->GetEntity(m_targetId); if (pTarget) { AABB box; pTarget->GetWorldBounds(box); Vec3 finalDes = box.GetCenter(); SetDestination(finalDes); //SetDestination( box.GetCenter() ); if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Target Entity: %s", pTarget->GetName()); } m_lockedTimer+=0.05f; } } else if(m_autoControlled) return; } if (m_controlled && !m_autoControlled && isOwner && !m_targetId) { //Check if the weapon is still selected CWeapon *pWeapon = GetWeapon(); if(!pWeapon || !pWeapon->IsSelected()) return; if (m_controlledTimer>0.0f) m_controlledTimer=m_controlledTimer-frameTime; else if (pClientActor && pClientActor->IsPlayer()) //Follow the crosshair { if (IMovementController *pMC=pClientActor->GetMovementController()) { Vec3 eyePos(ZERO); Vec3 eyeDir(ZERO); IVehicle* pVehicle = pClientActor->GetLinkedVehicle(); if(!pVehicle) { SMovementState state; pMC->GetMovementState(state); eyePos = state.eyePosition; eyeDir = state.eyeDirection; } else { SViewParams viewParams; pVehicle->UpdateView(viewParams, pClientActor->GetEntityId()); eyePos = viewParams.position; eyeDir = viewParams.rotation * Vec3(0,1,0); //eyeDir = (viewParams.targetPos - viewParams.position).GetNormalizedSafe(); } int pierceability=7; if (IPhysicalEntity *pPE=GetEntity()->GetPhysics()) { if (pPE->GetType()==PE_PARTICLE) { pe_params_particle pp; if (pPE->GetParams(&pp)) pierceability=pp.iPierceability; } } static const int objTypes = ent_all; static const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (pierceability & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit); IPhysicalWorld* pWorld = gEnv->pPhysicalWorld; static IPhysicalEntity* pSkipEnts[10]; int numSkip = CSingle::GetSkipEntities(pWeapon, pSkipEnts, 10); ray_hit hit; int hits = 0; float range=m_maxTargetDistance; hits = pWorld->RayWorldIntersection(eyePos + 1.5f*eyeDir, eyeDir*range, objTypes, flags, &hit, 1, pSkipEnts, numSkip); while (hits) { if (gEnv->p3DEngine->RefineRayHit(&hit, eyeDir*range)) break; eyePos = hit.pt+eyeDir*0.003f; range -= hit.dist+0.003f; hits = pWorld->RayWorldIntersection(eyePos, eyeDir*range, objTypes, flags, &hit, 1, pSkipEnts, numSkip); } DestinationParams params; if(hits) params.pt=hit.pt; else params.pt=(eyePos+m_maxTargetDistance*eyeDir); //Some point in the sky... GetGameObject()->InvokeRMI(SvRequestDestination(), params, eRMI_ToServer); if (bDebug) { pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "PlayerView eye direction: %.3f %.3f %.3f", eyeDir.x, eyeDir.y, eyeDir.z); pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "PlayerView Target: %.3f %.3f %.3f", hit.pt.x, hit.pt.y, hit.pt.z); pRenderer->GetIRenderAuxGeom()->DrawCone(m_destination, Vec3(0,0,-1), 2.5f, 7.f, ColorB(255,0,0,255)); } } m_controlledTimer+=0.0f; } } } //This code is shared by both modes above (auto and controlled) if(!m_destination.IsZero()) { pe_status_dynamics status; if (!GetEntity()->GetPhysics()->GetStatus(&status)) { CryLogAlways("couldn't get physics status!"); return; } pe_status_pos pos; if (!GetEntity()->GetPhysics()->GetStatus(&pos)) { CryLogAlways("couldn't get physics pos!"); return; } float currentSpeed = status.v.len(); if (currentSpeed>0.001f) { Vec3 currentVel = status.v; Vec3 currentPos = pos.pos; Vec3 goalDir(ZERO); assert(!_isnan(currentSpeed)); assert(!_isnan(currentVel.x) && !_isnan(currentVel.y) && !_isnan(currentVel.z)); //Just a security check if((currentPos-m_destination).len2()<(m_detonationRadius*m_detonationRadius)) { Explode(true, true, m_destination, -currentVel.normalized(), currentVel, m_targetId); return; } goalDir = m_destination - currentPos; goalDir.Normalize(); //Turn more slowly... currentVel.Normalize(); if(bDebug) { pRenderer->Draw2dLabel(50,55,2.0f,color,false, " Destination: %.3f, %.3f, %.3f",m_destination.x,m_destination.y,m_destination.z); pRenderer->Draw2dLabel(50,80,2.0f,color,false, " Current Dir: %.3f, %.3f, %.3f",currentVel.x,currentVel.y,currentVel.z); pRenderer->Draw2dLabel(50,105,2.0f,color,false," Goal Dir: %.3f, %.3f, %.3f",goalDir.x,goalDir.y,goalDir.z); } float cosine = currentVel.Dot(goalDir); cosine = CLAMP(cosine,-1.0f,1.0f); float totalAngle = RAD2DEG(cry_acosf(cosine)); assert(totalAngle>=0); if (cosine<0.99) { float maxAngle = m_turnSpeed*frameTime; if (maxAngle>totalAngle) maxAngle=totalAngle; float t=(maxAngle/totalAngle)*m_lazyness; assert(t>=0.0 && t<=1.0); goalDir = Vec3::CreateSlerp(currentVel, goalDir, t); goalDir.Normalize(); } if(bDebug) pRenderer->Draw2dLabel(50,180,2.0f,color,false,"Corrected Dir: %.3f, %.3f, %.3f",goalDir.x,goalDir.y,goalDir.z); pe_action_set_velocity action; action.v = goalDir * currentSpeed; GetEntity()->GetPhysics()->Action(&action); } } }