BOOL obj_ItemSpawnPoint::Update() { static int delayCheckSpawnPointsInAir = 100; if(delayCheckSpawnPointsInAir) --delayCheckSpawnPointsInAir; if(g_bEditMode && m_bEditorCheckSpawnPointAtStart && delayCheckSpawnPointsInAir ==0) { m_bEditorCheckSpawnPointAtStart = false; for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ++it) { PxVec3 from(it->pos.x, it->pos.y+1.0f, it->pos.z); PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlags(PxSceneQueryFilterFlag::eSTATIC)); if(g_pPhysicsWorld->raycastSingle(from, PxVec3(0,-1,0), 10000, PxSceneQueryFlags(PxSceneQueryFlag::eIMPACT), hit, filter)) { r3dPoint3D hitPos(hit.impact.x, hit.impact.y, hit.impact.z); if(R3D_ABS(it->pos.y - hitPos.y) > 2.0f) { r3dArtBug("Item CP Spawn at %.2f, %.2f, %.2f has spawn position(s) in the air. Please select it and use Check Locations button\n", GetPosition().x, GetPosition().y, GetPosition().z); break; } } } r3dShowArtBugs(); } return parent::Update(); }
void WeaponSystem::Process(float _deltaTime, SystemRequierements& _provided) { //loading times and energy given are proportional float energyRatio = m_energyIn / m_energyDemand; //load weapons with the given energy for (auto& weapon : m_weapons) weapon.cooldown -= ei::min(weapon.cooldown, _deltaTime / weapon.cooldownBase * energyRatio); //fire when commanded if (!m_firing) return; for (auto& weapon : m_weapons) { if (weapon.cooldown <= 0.f) { weapon.cooldown = weapon.cooldownBase; Ray ray(weapon.position, m_ship.GetRotationMatrix() * Vec3(0.f, 0.f, 1.f)/*zaxis(m_ship.GetRotation())*/); ray.origin = m_ship.GetRotationMatrix() * ray.origin; //when the player ship is not in the way // if (!m_ship.GetVoxelTree().RayCast(ray, 1, hit, distance)) { Vec3 basePos(m_ship.GetPosition() - m_particles.GetPosition()); basePos += ray.origin; Math::WorldRay wRay; wRay.origin = m_ship.GetPosition(); wRay.origin.x += Math::Fix(ray.origin.x); wRay.origin.y += Math::Fix(ray.origin.y); wRay.origin.z += Math::Fix(ray.origin.z); wRay.direction = ray.direction; float d = g_fireManager->FireRay(FireRayInfo(wRay, weapon.damage)); for (int i = 0; i < 10; ++i) m_particles.AddParticle(basePos, //position ray.direction * c_projVel * i / 10.f,// velocity d / c_projVel, //life time Utils::Color8U(0.4f, 0.1f, 0.8f).RGBA(), 1.f); //temporary, hit feedback should be done by the model? if (d != 100.f) { static Generators::Random rng(351298); Vec3 hitPos(basePos + ray.direction * d); for (int i = 0; i < 50; ++i) m_particles.AddParticle(hitPos, //position Vec3(rng.Uniform(0.1f, 3.0f), rng.Uniform(0.1f,3.0f), rng.Uniform(0.1f, 3.0f)),// velocity rng.Uniform(0.2f, 1.f), //life time Utils::Color8U(0.15f, 0.2f, 0.2f).RGBA(), 0.5f); } } } } }
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; }
IntersectionData ofxIntersection::RayTriangleIntersection(IsTriangle& triangle, IsRay& ray){ // Copied from ofxRayTriangleIntersection IntersectionData idata; ofVec3f rayStart=ray.getP0(); ofVec3f rayDir=ray.getVec(); ofVec3f triNorm = triangle.getNormal(); float vn = rayDir.dot(triNorm); ofVec3f aa = rayStart - triangle.getP0(); float xpn = aa.dot(triNorm); float distance = -xpn / vn; if (distance < 0) return idata; // behind ray origin. fail ofPoint hitPos(rayDir.x * distance + rayStart.x, rayDir.y * distance + rayStart.y, rayDir.z * distance + rayStart.z); ofVec3f hit00 = hitPos - triangle.getP0(); ofVec3f hit01 = triangle.getP1() - triangle.getP0(); ofVec3f cross0 = hit00.cross(hit01); if (cross0.dot(triNorm) > EPS) return idata; // not in triangle. fail ofVec3f hit10 = hitPos - triangle.getP1(); ofVec3f hit11 = triangle.getP2() - triangle.getP1(); ofVec3f cross1 = hit10.cross(hit11); if (cross1.dot(triNorm) > EPS) return idata; // not in triangle. fail ofVec3f hit20 = hitPos - triangle.getP2(); ofVec3f hit21 = triangle.getP0() - triangle.getP2(); ofVec3f cross2 = hit20.cross(hit21); if (cross2.dot(triNorm) > EPS) return idata;; // not in triangle. fail idata.isIntersection=true; idata.pos=hitPos; idata.dist=distance; }
//------------------------------------------------------------------ void CLam::UpdateFPLaser(float frameTime, CItem* parent) { Vec3 lamPos, dir; if (m_laserActivated) AdjustLaserFPDirection(parent,dir,lamPos); else { // Lam Light lamPos = parent->GetSlotHelperPos(eIGS_FirstPerson,m_laserHelperFP.c_str(),true); Quat lamRot = Quat(parent->GetSlotHelperRotation(eIGS_FirstPerson,m_laserHelperFP.c_str(),true)); dir = lamRot.GetColumn1(); } // float len = m_lamparams.laser_range[eIGS_FirstPerson]; dir.Normalize(); const float nearClipPlaneLimit = 10.0f; Vec3 hitPos(0,0,0); float laserLength = 0.0f; float dotScale = 1.0f; { IPhysicalEntity* pSkipEntity = NULL; if(parent->GetOwner()) pSkipEntity = parent->GetOwner()->GetPhysics(); const int objects = ent_all; 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*m_lamparams.laser_range[eIGS_FirstPerson], objects, flags, &hit, 1, &pSkipEntity, pSkipEntity?1:0)) { //Clamp distance below near clip plane limits, if not dot will be overdrawn during rasterization if(hit.dist>nearClipPlaneLimit) { laserLength = nearClipPlaneLimit; m_lastLaserHitPt = lamPos + (nearClipPlaneLimit*dir); } else { laserLength = hit.dist; m_lastLaserHitPt = hit.pt; } m_lastLaserHitSolid = true; if(parent->GetOwnerActor() && parent->GetOwnerActor()->GetActorParams()) dotScale *= max(0.3f,parent->GetOwnerActor()->GetActorParams()->viewFoVScale); } else { m_lastLaserHitSolid = false; m_lastLaserHitPt = lamPos - (dir*3.0f); laserLength = 3.0f; } hitPos = m_lastLaserHitPt; if(g_pGameCVars->i_debug_projectiles!=0) gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(hitPos, 0.2f, ColorB(255,0,0)); } if (m_laserActivated && m_dotEffectSlot >= 0) { Matrix34 worldMatrix = GetEntity()->GetWorldTM(); if(laserLength<=0.7f) hitPos = lamPos+(0.7f*dir); CWeapon* pWep = static_cast<CWeapon*>(parent->GetIWeapon()); if(pWep && pWep->IsWeaponLowered()) { hitPos = lamPos+(2.0f*dir); laserLength = 2.0f; } if(laserLength<=2.0f) dotScale *= min(1.0f,(0.35f + ((laserLength-0.7f)*0.5f))); IEntity* pDotEntity = m_pEntitySystem->GetEntity(m_pLaserEntityId); if(pDotEntity) { Matrix34 finalMatrix = Matrix34::CreateTranslationMat(hitPos-(0.2f*dir)); pDotEntity->SetWorldTM(finalMatrix); Matrix34 localScale = Matrix34::CreateIdentity(); localScale.SetScale(Vec3(dotScale,dotScale,dotScale)); pDotEntity->SetSlotLocalTM(m_dotEffectSlot,localScale); } } if (m_laserActivated || m_lightActivated) { float laserAIRange = m_laserActivated ? laserLength : 0.0f; float lightAIRange = m_lightActivated ? min(laserLength, m_lamparams.light_range[eIGS_FirstPerson] * 1.5f) : 0.0f; UpdateAILightAndLaser(lamPos, dir, lightAIRange, m_lamparams.light_fov[eIGS_FirstPerson], laserAIRange); } }
//------------------------------------------------------------------ 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); }
float obj_ItemSpawnPoint::DrawPropertyEditor(float scrx, float scry, float scrw, float scrh, const AClass* startClass, const GameObjects& selected) { float starty = scry; starty += parent::DrawPropertyEditor(scrx, scry, scrw,scrh, startClass, selected ); if( IsParentOrEqual( &ClassData, startClass ) ) { starty += imgui_Static ( scrx, starty, "Item Spawn Point Parameters" ); starty += imgui_Value_Slider(scrx, starty, "Tick Period (sec)", &m_TickPeriod, 1.0f, 50000.0f, "%.2f"); starty += imgui_Value_Slider(scrx, starty, "Cooldown (sec)", &m_Cooldown, 1.0f, 50000.0f, "%.2f"); starty += imgui_Value_Slider(scrx, starty, "De-spawn (sec)", &m_DestroyItemTimer, 0.0f, 50000.0f, "%.2f"); int isOneItemSpawn = m_OneItemSpawn?1:0; starty += imgui_Checkbox(scrx, starty, "One Item Spawn", &isOneItemSpawn, 1); m_OneItemSpawn = isOneItemSpawn?true:false; if(!m_OneItemSpawn) { static stringlist_t lootBoxNames; static int* lootBoxIDs = NULL; static int numLootBoxes = 0; if(numLootBoxes == 0) { struct tempS { char* name; uint32_t id; }; std::vector<tempS> lootBoxes; { tempS holder; holder.name = "EMPTY"; holder.id = 0; lootBoxes.push_back(holder); } g_pWeaponArmory->startItemSearch(); while(g_pWeaponArmory->searchNextItem()) { uint32_t itemID = g_pWeaponArmory->getCurrentSearchItemID(); const BaseItemConfig* cfg = g_pWeaponArmory->getConfig(itemID); if( cfg->category == storecat_LootBox ) { tempS holder; holder.name = cfg->m_StoreName; holder.id = cfg->m_itemID; lootBoxes.push_back(holder); } } numLootBoxes = (int)lootBoxes.size(); lootBoxIDs = new int[numLootBoxes]; for(int i=0; i<numLootBoxes; ++i) { lootBoxNames.push_back(lootBoxes[i].name); lootBoxIDs[i] = lootBoxes[i].id; } } int sel = 0; static float offset = 0; for(int i=0; i<numLootBoxes; ++i) if(m_LootBoxID == lootBoxIDs[i]) sel = i; starty += imgui_Static ( scrx, starty, "Loot box:" ); if(imgui_DrawList(scrx, starty, 360, 122, lootBoxNames, &offset, &sel)) { m_LootBoxID = lootBoxIDs[sel]; PropagateChange( m_LootBoxID, &obj_ItemSpawnPoint::m_LootBoxID, this, selected ) ; } starty += 122; } else { starty += imgui_Value_SliderI(scrx, starty, "ItemID", (int*)&m_LootBoxID, 0, 1000000, "%d", false); PropagateChange( m_LootBoxID, &obj_ItemSpawnPoint::m_LootBoxID, this, selected ) ; } // don't allow multi edit of this if( selected.Count() <= 1 ) { { if(imgui_Button(scrx, starty, 200, 25, "Check locations")) { for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ++it) { PxVec3 from(it->pos.x, it->pos.y+1.0f, it->pos.z); PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlags(PxSceneQueryFilterFlag::eSTATIC)); if(g_pPhysicsWorld->raycastSingle(from, PxVec3(0,-1,0), 10000, PxSceneQueryFlags(PxSceneQueryFlag::eIMPACT), hit, filter)) { r3dPoint3D hitPos(hit.impact.x, hit.impact.y, hit.impact.z); if(R3D_ABS(it->pos.y - hitPos.y) > 2.0f) { gCam = it->pos + r3dPoint3D(0,1,0); break; } } } } starty += 30; } if(imgui_Button(scrx+110, starty, 100, 25, "Add Location")) { ItemSpawn itemSpawn; itemSpawn.pos = GetPosition() + r3dPoint3D(2, 0, 2); m_SpawnPointsV.push_back(itemSpawn); m_SelectedSpawnPoint = m_SpawnPointsV.size()-1; } starty += 25; int i=0; for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ) { // selection button char tempStr[32]; sprintf(tempStr, "Location %d", i+1); if(imgui_Button(scrx, starty, 100, 25, tempStr, i==m_SelectedSpawnPoint)) { // shift click on location will set camera to it if(Keyboard->IsPressed(kbsLeftShift)) { extern BaseHUD* HudArray[6]; extern int CurHUDID; HudArray[CurHUDID]->FPS_Position = m_SpawnPointsV[i].pos; HudArray[CurHUDID]->FPS_Position.y += 0.1f; } m_SelectedSpawnPoint = i; } // delete button if(m_SpawnPointsV.size() > 1) { if(imgui_Button(scrx + 110, starty, 100, 25, "DEL")) { it = m_SpawnPointsV.erase(it); continue; } m_SelectedSpawnPoint = R3D_CLAMP(m_SelectedSpawnPoint, 0, (int)m_SpawnPointsV.size()-1); } starty += 25; ++it; ++i; } extern r3dPoint3D UI_TargetPos; if((Mouse->IsPressed(r3dMouse::mLeftButton)) && Keyboard->IsPressed(kbsLeftControl)) m_SpawnPointsV[m_SelectedSpawnPoint].pos = UI_TargetPos; } } return starty-scry; }
//---------------------------------------------------- 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); } } }
//========================================= void CRocketLauncher::UpdateDotEffect(float frameTime) { Vec3 laserPos, dir; CCamera& camera = gEnv->pSystem->GetViewCamera(); laserPos = camera.GetPosition(); dir = camera.GetMatrix().GetColumn1(); dir.Normalize(); const float nearClipPlaneLimit = 10.0f; Vec3 hitPos(0,0,0); float laserLength = 0.0f; float dotScale=1.0f; { IPhysicalEntity* pSkipEntity = NULL; if(GetOwner()) pSkipEntity = GetOwner()->GetPhysics(); const int objects = ent_all; 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(laserPos, dir*m_LaserRange, objects, flags, &hit, 1, &pSkipEntity, pSkipEntity?1:0)) { //Clamp distance below near clip plane limits, if not dot will be overdrawn during rasterization if(hit.dist>nearClipPlaneLimit) { laserLength = nearClipPlaneLimit; hitPos = laserPos + (nearClipPlaneLimit*dir); } else { laserLength = hit.dist; hitPos = hit.pt; } if(GetOwnerActor() && GetOwnerActor()->GetActorParams()) dotScale *= GetOwnerActor()->GetActorParams()->viewFoVScale; } else { hitPos = laserPos - (3.0f*dir); laserLength = 3.0f; } } if (m_dotEffectSlot>=0) { Matrix34 worldMatrix = GetEntity()->GetWorldTM(); if(laserLength<=0.7f) hitPos = laserPos+(0.7f*dir); if(IsWeaponLowered()) { hitPos = laserPos+(2.0f*dir); laserLength = 2.0f; } if(laserLength<=2.0f) dotScale *= min(1.0f,(0.35f + ((laserLength-0.7f)*0.5f))); Matrix34 localMatrix = worldMatrix.GetInverted()*Matrix34::CreateTranslationMat(hitPos-(0.2f*dir)); localMatrix.Scale(Vec3(dotScale,dotScale,dotScale)); GetEntity()->SetSlotLocalTM(m_dotEffectSlot, localMatrix); } }