//------------------------------------------------------------------------ void CTracer::Reset(const Vec3 &pos, const Vec3 &dest) { m_pos.zero(); m_dest.zero(); m_startingPos=pos; m_age=0.0f; m_lifeTime=1.5f; m_tracerFlags &= ~kTracerFlag_scaleToDistance; m_startFadeOutTime = 0.0f; m_slideFrac = 0.f; if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity(m_entityId)) { pEntity->FreeSlot(TRACER_GEOM_SLOT); pEntity->FreeSlot(TRACER_FX_SLOT); Vec3 dir = dest - pos; dir.Normalize(); Matrix34 tm; tm.SetIdentity(); if(!dir.IsZero()) { tm = Matrix33::CreateRotationVDir(dir); } tm.AddTranslation(pos); pEntity->SetWorldTM(tm); } }
bool CIntersectionAssistanceUnit::TestForIntersectionAtLocation(const eTestMethod testMethod, const Matrix34& wMat, EntityId testEntityId, EntityId ignoreEnt, QuatT& outAdjustedResult, const bool bCentreOnFocalEnt /* = false */, bool bRenderOnFail /* = true */, const int index /* = -1*/) { // Build an OOBB that surrounds this entity, test for intersection between that and world IEntity* pEntity = gEnv->pEntitySystem->GetEntity(testEntityId); if(pEntity) { IPhysicalEntity* pPhysical = pEntity->GetPhysics(); if(pPhysical) { OBB entOBB; AABB entAABB; pEntity->GetLocalBounds(entAABB); entOBB.SetOBBfromAABB(Quat(IDENTITY), entAABB); // Do Primitive world intersection primitives::box physBox; physBox.bOriented = 1; // LSpace physBox.center = entOBB.c; physBox.Basis = entOBB.m33; physBox.size.x = entOBB.h.x; physBox.size.y = entOBB.h.y; physBox.size.z = entOBB.h.z; // WSpace physBox.center = wMat.TransformPoint(physBox.center); physBox.Basis *= Matrix33(wMat).GetInverted(); // Optional tweak - We can get away with a little bit of scaling down (if edges are slightly embedded the physics pushes them out easily) physBox.size = physBox.size.scale(kPhysBoxScaleFactor); // adjust Vec3 vAdjustments(0.0f,0.0f,0.0f); if(bCentreOnFocalEnt && m_focalEntityId) { Vec3 vDesiredPos = CalculateTargetAdjustPoint(pEntity, wMat, physBox.center); vAdjustments = (vDesiredPos - physBox.center); physBox.center += vAdjustments; } IEntity* pIgnoreEnt = gEnv->pEntitySystem->GetEntity(ignoreEnt); IPhysicalEntity* pIgnorePhys = pIgnoreEnt ? pIgnoreEnt->GetPhysics() : NULL; // Test if(testMethod == eTM_Immediate #ifndef _RELEASE || g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled >= 1 #endif // #ifndef _RELEASE ) { geom_contact *contacts; intersection_params params; float numHits = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(primitives::box::type, &physBox, Vec3(ZERO), ent_static|ent_terrain, &contacts, 0, 3, ¶ms, 0, 0, &pIgnorePhys, pIgnorePhys ? 1 : 0); // Debug #ifndef _RELEASE if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled) { const bool bIntersect = numHits <= 0.0f ? false : true; if(bRenderOnFail || !bIntersect) { const ColorB colorPositive = ColorB(16, 96, 16); const ColorB colorNegative = ColorB(128, 0, 0); const ColorB colorSelected = ColorB(0,255,0); if(numHits > 0.0f) { gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(contacts->pt, 0.1f, colorPositive); } OBB finalOBB; finalOBB.SetOBB(Matrix33(IDENTITY), physBox.size, Vec3(0.0f,0.0f,0.0f)); Matrix34 drawMat = wMat; drawMat.AddTranslation(physBox.center - wMat.GetTranslation()); if(index != -1 && index == m_currentBestIndex) { gEnv->pRenderer->GetIRenderAuxGeom()->DrawOBB(finalOBB, drawMat, false, colorSelected, eBBD_Faceted); } else { gEnv->pRenderer->GetIRenderAuxGeom()->DrawOBB(finalOBB, drawMat, false, bIntersect ? colorNegative : colorPositive, eBBD_Faceted); } } } #endif //#ifndef RELEASE // If we performed an adjust, make sure we pass out the QuatT representing the FINAL ENTITY POSITION that passed/failed (not the phys box etc) outAdjustedResult.t = wMat.GetTranslation() + vAdjustments; outAdjustedResult.q = Quat(wMat); #ifndef _RELEASE // allow optional debug drawing of last known good positions by retaining non adjusted position if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled == 1) { outAdjustedResult.t = wMat.GetTranslation(); } #endif // #ifndef _RELEASE return (numHits > 0.0f); } else { // QUEUE primitive intersection check outAdjustedResult.t = wMat.GetTranslation() + vAdjustments; outAdjustedResult.q = Quat(wMat); CRY_ASSERT(index >= 0); m_intersectionTester.DoCheck(index,physBox,outAdjustedResult,pIgnorePhys); return false; } } } return false; }
void CEntityObject::Render( CEntity* pEntity,SRendParams &rParams,int nRndFlags,CRenderProxy* pRenderProxy, const SRenderingPassInfo &passInfo ) { if (!bWorldTMValid) { UpdateWorldTM(pEntity); } // Override with custom slot material. IMaterial* pPrevMtl = rParams.pMaterial; if (pMaterial) rParams.pMaterial = pMaterial; int32 nOldObjectFlags = rParams.dwFObjFlags; rParams.dwFObjFlags |= dwFObjFlags; if (flags & ENTITY_SLOT_RENDER_AFTER_POSTPROCESSING) { rParams.dwFObjFlags |= FOB_RENDER_AFTER_POSTPROCESSING; } #ifdef SEG_WORLD rParams.nCustomFlags |= (1 << (COB_SW_SHIFT + pEntity->GetSwObjDebugFlag())); #endif // SEG_WORLD ////////////////////////////////////////////////////////////////////////// rParams.pInstance = this; const bool bIsInCameraSpace = (flags & ENTITY_SLOT_RENDER_NEAREST) != 0; // Draw static object. if (pStatObj) { rParams.pMatrix = &m_worldTM; rParams.dwFObjFlags |= FOB_TRANS_MASK; rParams.pFoliage = pFoliage; rParams.nSubObjHideMask = nSubObjHideMask; // make sure object motion blur can be applied to this object if (bObjectMoved) { rParams.dwFObjFlags |= FOB_DYNAMIC_OBJECT; bObjectMoved = false; } Matrix34 entityTM; if (bIsInCameraSpace) { rParams.pMatrix = &entityTM; entityTM = m_worldTM; // Camera space if (m_pCameraSpacePos) { // Use camera space relative position entityTM.SetTranslation(*m_pCameraSpacePos); } else { // We don't have camera space relative position, so calculate it out from world space // (This will not have the precision advantages of camera space rendering) entityTM.AddTranslation(-gEnv->pSystem->GetViewCamera().GetPosition()); } } if (rParams.pMatrix->IsValid()) pStatObj->Render( rParams, passInfo ); else EntityWarning("CEntityObject::Render: Invalid world matrix: %s", pEntity->GetEntityTextDescription()); } else if (pCharacter) { QuatTS Offset; Matrix34 PhysLocation(pEntity->GetWorldTM()); if (m_pXForm) Offset = QuatTS(m_pXForm->localTM); else { //CRY_FIXME(03,12,2009,"Animation & Rendering of entities needs to be re-written to avoid derivation of local offset due to float inaccuracy - Richard Semmens"); if (!Matrix34::IsEquivalent(PhysLocation,m_worldTM)) { Matrix34 invPhysLocation = PhysLocation.GetInverted(); Matrix34 matOffset = invPhysLocation * m_worldTM; Offset = QuatTS(matOffset); } else { Offset.SetIdentity(); } } if (bIsInCameraSpace) { // Camera space if (m_pCameraSpacePos) { // Use camera space relative position const Matrix33 camRot = Matrix33(gEnv->pSystem->GetViewCamera().GetViewMatrix()); PhysLocation.SetTranslation(*m_pCameraSpacePos * camRot); } else { // We don't have camera space relative position, so calculate it out from world space // (This will not have the precision advantages of camera space rendering) PhysLocation.AddTranslation(-gEnv->pSystem->GetViewCamera().GetPosition()); } Offset.SetIdentity(); } rParams.pMatrix = &PhysLocation; //rParams.pInstance = pCharacter; // Disable hand-placed (static) decals on characters rParams.dwFObjFlags |= FOB_DYNAMIC_OBJECT; pCharacter->Render(rParams, Offset, passInfo); const uint32 renderProxyFlags = pRenderProxy->GetFlags(); if (!passInfo.IsShadowPass() || (renderProxyFlags & CRenderProxy::FLAG_ANIMATE_OFFSCREEN_SHADOW)) { // If We render character, make sure it is also gets animation activated. if (!pEntity->m_bInActiveList) pEntity->ActivateForNumUpdates(8); } } else if (pChildRenderNode) { rParams.pMatrix = &m_worldTM; //rParams.pInstance = pChildRenderNode; pChildRenderNode->m_dwRndFlags = nRndFlags; pChildRenderNode->Render( rParams, passInfo ); } rParams.pMaterial = pPrevMtl; rParams.dwFObjFlags = nOldObjectFlags; if (!passInfo.IsShadowPass()) // Should also ignore rendering into the recursion. { if (pFoliage) { pFoliage->SetFlags(pFoliage->GetFlags() & ~IFoliage::FLAG_FROZEN | -(int)(rParams.nMaterialLayers & MTL_LAYER_FROZEN) & IFoliage::FLAG_FROZEN); static ICVar* g_pWindActivationDist = gEnv->pConsole->GetCVar("e_FoliageWindActivationDist"); float maxdist = g_pWindActivationDist ? g_pWindActivationDist->GetFVal() : 0.0f; Vec3 pos = m_worldTM.GetTranslation(); if (pStatObj && (gEnv->pSystem->GetViewCamera().GetPosition() - pos).len2() < sqr(maxdist) && gEnv->p3DEngine->GetWind(AABB(pos),false).len2() > 101.0f) pStatObj->PhysicalizeFoliage(pEntity->GetPhysics(),m_worldTM,pFoliage,0,4); } } }
//-------------------------------------------------------------------------------------------------- // Name: CalculateGlassBounds // Desc: Calculates glass bounds from physics geometry //-------------------------------------------------------------------------------------------------- void CBreakableGlassSystem::CalculateGlassBounds(const phys_geometry* const pPhysGeom, Vec3& size, Matrix34& matrix) { // Find thinnest axis of physics geometry primitives::box bbox; pPhysGeom->pGeom->GetBBox(&bbox); Matrix33 basis = bbox.Basis.T(); Vec3 halfSize = bbox.size; Vec3 center = bbox.center; const uint thinAxis = idxmin3(&halfSize.x); // Need to rotate so Z is our thin axis if (thinAxis < 2) { float tempSize; Matrix33 tempMat; tempMat.SetIdentity(); // Calculate the rotation based on current facing dir const Vec3 axes[2] = { Vec3Constants<float>::fVec3_OneX, Vec3Constants<float>::fVec3_OneY }; const Vec3& thinRow = bbox.Basis.GetRow(thinAxis); const Vec3 localAxis = bbox.Basis.TransformVector(axes[thinAxis]); float rot = (thinRow.Dot(localAxis) >= 0.0f) ? -gf_PI*0.5f : gf_PI*0.5f; if (thinAxis == 0) { tempSize = halfSize.x; halfSize.x = halfSize.z; tempMat.SetRotationY(rot); } else { tempSize = halfSize.y; halfSize.y = halfSize.z; tempMat.SetRotationX(rot); } // Apply rotation to matrix and vectors basis = basis * tempMat; halfSize.z = tempSize; } // Assert minimum thickness const float halfMinThickness = 0.004f; halfSize.z = max(halfSize.z, halfMinThickness); size = halfSize * 2.0f; // Calculate locally offset bounds matrix.SetIdentity(); matrix.SetTranslation(-halfSize); matrix = basis * matrix; matrix.AddTranslation(center); }//-------------------------------------------------------------------------------------------------
//---------------------------------------------------- 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); } } }