void VertexCoordRemapper::Tree::GetInputCoordinates(const unsigned int node_num, double coords[2][2][2]) { // find the coordinates of each point at the vertices in the original image. // this is used to look up the remapped coordinates and provide texture // coordinates. // it halves in size several times depending on depth. unsigned int x, y, row_size, depth; GetPosition(node_num, x, y, row_size, depth); // now we can locate the upper right corner double row_spacing = 1.0 / (double) row_size; coords[0][0][0] = row_spacing * (double) x; coords[0][0][1] = row_spacing * (double) y; // the extent is dependent on the direction of the subdivisions. // at least one direction has an extent of row_spacing. It can double up // if the parent did not subdivide in a direction, recursively up the tree. bool scale_x = false; double opp = 1.0; if (node_num != 0) { unsigned int parent_id = GetParentId(x, y, row_size, depth); if (!(nodes[parent_id].flags & split_flag_x)) { while (!(nodes[parent_id].flags & split_flag_x)) { parent_id = GetParentId(parent_id); opp *= 2.0; } scale_x = true; } else { while (!(nodes[parent_id].flags & split_flag_y)) { parent_id = GetParentId(parent_id); opp *= 2.0; } } } opp *= row_spacing; coords[1][0][0] = coords[0][0][0] + (scale_x ? opp : row_spacing); coords[1][0][1] = coords[0][0][1]; coords[0][1][0] = coords[0][0][0]; coords[0][1][1] = coords[0][0][1] + (scale_x ? row_spacing : opp); coords[1][1][0] = coords[1][0][0]; coords[1][1][1] = coords[0][1][1]; // now we transform the results so that we map to the cropped region instead // of the whole image. for (unsigned int i = 0; i < 2; i++) { for (unsigned int j = 0; j < 2; j++) { coords[i][j][0] = coords[i][j][0] * x_crop_scale + x_crop_offs; coords[i][j][1] = coords[i][j][1] * y_crop_scale + y_crop_offs; } } }
wxTreeItemId BrushSelector::GetParentId( Ogre::String &catalog, CatalogMap &map ) { // 如果送入的相对路径为空,说明这个纹理放在资源目录的根目录下 if ( catalog == "" ) // 所以,它的节点应该被建在根目录下 return mBrushesTree->GetRootItem(); else { // 否则,先试图找它的上一级目录,如果有的话(说明这个目录在树中已经建好,可能是因为有同个目录下的纹理 // 被处理过了),就返回这个目录 CatalogMap::iterator i = map.find(catalog); if ( i != map.end() ) return i->second; // 如果没有,就得递归往上找,并建树 else { Ogre::String path, baseName; Ogre::StringUtil::splitFilename(catalog, baseName, path); if (!path.empty() && path[path.length()-1] == '/') path.erase(path.length() - 1); wxTreeItemId id = mBrushesTree->AppendItem( GetParentId(path, map), wxT(baseName) ); map.insert( CatalogMap::value_type( catalog, id ) ); mCatalogMap.insert(CatalogMap::value_type( baseName, id )); return id; } } }
int TagEntry::Update(wxSQLite3Statement& updatePerepareStmnt) { // If this node is a dummy, (IsOk() == false) we dont update it to database if( !IsOk() ) return TagOk; try { // see TagsDatabase::GetUpdateOneStatement() function for the order of binding updatePerepareStmnt.Bind(1, GetParentId()); updatePerepareStmnt.Bind(2, GetName()); updatePerepareStmnt.Bind(3, GetFile()); updatePerepareStmnt.Bind(4, GetLine()); updatePerepareStmnt.Bind(5, GetAccess()); updatePerepareStmnt.Bind(6, GetPattern()); updatePerepareStmnt.Bind(7, GetParent()); updatePerepareStmnt.Bind(8, GetInherits()); updatePerepareStmnt.Bind(9, GetTyperef()); updatePerepareStmnt.Bind(10, GetScope()); updatePerepareStmnt.Bind(11, GetKind()); updatePerepareStmnt.Bind(12, GetSignature()); updatePerepareStmnt.Bind(13, GetPath()); updatePerepareStmnt.ExecuteUpdate(); updatePerepareStmnt.Reset(); } catch(wxSQLite3Exception& exc) { wxLogMessage(exc.GetMessage()); return TagError; } return TagOk; }
int TagEntry::Store(wxSQLite3Statement& insertPerepareStmnt) { // If this node is a dummy, (IsOk() == false) we dont insert it to database if( !IsOk() ) return TagOk; try { // see TagsDatabase::GetInsertOneStatement() for the order of binding insertPerepareStmnt.Bind(1, GetParentId()); insertPerepareStmnt.Bind(2, GetName()); insertPerepareStmnt.Bind(3, GetFile()); insertPerepareStmnt.Bind(4, GetLine()); insertPerepareStmnt.Bind(5, GetKind()); insertPerepareStmnt.Bind(6, GetAccess()); insertPerepareStmnt.Bind(7, GetSignature()); insertPerepareStmnt.Bind(8, GetPattern()); insertPerepareStmnt.Bind(9, GetParent()); insertPerepareStmnt.Bind(10, GetInherits()); insertPerepareStmnt.Bind(11, GetPath()); insertPerepareStmnt.Bind(12, GetTyperef()); insertPerepareStmnt.Bind(13, GetScope()); insertPerepareStmnt.ExecuteUpdate(); insertPerepareStmnt.Reset(); } catch(wxSQLite3Exception& exc) { if(exc.ErrorCodeAsString(exc.GetErrorCode()) == wxT("SQLITE_CONSTRAINT")) return TagExist; wxLogMessage(exc.GetMessage()); return TagError; } return TagOk; }
unsigned int VertexCoordRemapper::Tree::GetParentId(const unsigned int nodenum) { // get the parent id of a node specifed by its index. unsigned int x, y, row_size, depth; GetPosition(nodenum, x, y, row_size, depth); return GetParentId(x, y, row_size, depth); }
//--------------------------------------------- CWeapon* CLaser::GetWeapon() const { IItem* pParentItem = m_pItemSystem->GetItem(GetParentId()); if(pParentItem == NULL) return 0; CWeapon* pParentWeapon = static_cast<CWeapon*>(pParentItem->GetIWeapon()); return pParentWeapon; }
//------------------------------------------------------------------------- void CLam::ActivateLight(bool activate, bool aiRequest /* = false */) { //GameWarning("CLam::ActivateLight(%i)", activate); CItem *pParent = NULL; EntityId ownerId = 0; if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) { pParent = (CItem *)pOwnerItem; IWeapon *pWeapon = pOwnerItem->GetIWeapon(); if(pWeapon) ownerId = pOwnerItem->GetOwnerId(); } else { pParent = this; ownerId = GetOwnerId(); } IActor *pOwnerActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(ownerId); if (activate && !pOwnerActor) return; //Special FP stuff if(pOwnerActor && pOwnerActor->IsPlayer() && !m_lamparams.isFlashLight) return; //For AI must be deactivated by default (if they don't request) if(activate && !m_lightWasOn && !aiRequest && !pOwnerActor->IsPlayer()) return; m_lightActivated = activate; //Activate or deactivate effect if (!m_lightActivated) { AttachLAMLight(false, pParent, eIGS_FirstPerson); AttachLAMLight(false, pParent, eIGS_ThirdPerson); //GameWarning("Global light count = %d", s_lightCount); } else { uint8 id = pOwnerActor->IsThirdPerson() ? 1 : 0; if (m_lightID[id] == 0) { AttachLAMLight(true, pParent, id?eIGS_ThirdPerson:eIGS_FirstPerson); } } if (m_laserActivated || m_lightActivated) GetGameObject()->EnablePostUpdates(this); if (!m_laserActivated && !m_lightActivated) GetGameObject()->DisablePostUpdates(this); }
CWeapon* CFlashLight::GetWeapon() const { IItem* pParentItem = m_pItemSystem->GetItem(GetParentId()); if (pParentItem == NULL) { return 0; } CWeapon* pParentWeapon = static_cast<CWeapon*>(pParentItem->GetIWeapon()); return pParentWeapon; }
//--------------------------------------------------------------------------- void CLam::PostUpdate(float frameTime) { if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) { CItem* pParentItem = (CItem *)pOwnerItem; if(!pParentItem->IsOwnerFP() && pParentItem->IsSelected()) UpdateTPLaser(frameTime,pParentItem); else if(pParentItem->IsOwnerFP()) UpdateFPLaser(frameTime,pParentItem); } }
CItem::ePhysicalization CAccessory::FindPhysicalisationType( bool enable, bool rigid ) { const bool isMounted = (GetParentId() != 0); ePhysicalization physType = eIPhys_NotPhysicalized; if(enable && !isMounted) { physType = rigid ? eIPhys_PhysicalizedRigid : eIPhys_PhysicalizedStatic; } return physType; }
//------------------------------------------------------------------------- void CLam::OnAttach(bool attach) { CAccessory::OnAttach(attach); if(CItem* pItem = static_cast<CItem*>(m_pItemSystem->GetItem(GetParentId()))) { if(pItem->GetOwnerActor() && pItem->GetOwnerActor()->IsPlayer()) { ActivateLaser(attach); ActivateLight(attach); } } }
void CAccessory::Physicalize( bool enable, bool rigid ) { const bool isMounted = (GetParentId() != 0); int profile = eIPhys_NotPhysicalized; if (enable && !isMounted) { profile = rigid ? eIPhys_PhysicalizedRigid : eIPhys_PhysicalizedStatic; } if (IsServer()) { GetGameObject()->SetAspectProfile(eEA_Physics, profile); } m_deferPhysicalization = eIPhys_Max; }
//------------------------------------------------------------------ void CLam::UpdateAILightAndLaser(const Vec3& pos, const Vec3& dir, float lightRange, float fov, float laserRange) { if (!gEnv->pAISystem) return; EntityId userId = 0; if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) { CItem* pParentItem = (CItem *)pOwnerItem; userId = pParentItem->GetOwnerId(); } if (lightRange > 0.0001f) { gEnv->pAISystem->DynSpotLightEvent(pos, dir, lightRange, DEG2RAD(fov)/2, AILE_FLASH_LIGHT, userId, 1.0f); gEnv->pAISystem->DynOmniLightEvent(pos - dir*0.5f, 1.5f, AILE_FLASH_LIGHT, userId, 2.0f); } // [Mikko] 4.10.2007 Removed as per design request. /* if (laserRange > 0.0001f) { gEnv->pAISystem->DynSpotLightEvent(pos, dir, max(0.0f, laserRange - 0.1f), DEG2RAD(0.25f), AILE_LASER, pUserAI, 2.0f); }*/ }
//------------------------------------------------------------------------- void CLam::ActivateLaser(bool activate, bool aiRequest /* = false */) { if (m_laserActivated == activate) return; CItem *pParent = NULL; EntityId ownerId = 0; bool ok = false; if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) { pParent = (CItem *)pOwnerItem; IWeapon *pWeapon = pOwnerItem->GetIWeapon(); if(pWeapon) ownerId = pOwnerItem->GetOwnerId(); ok = true; } else { pParent = this; ownerId = GetOwnerId(); } IActor *pOwnerActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(ownerId); if(!pOwnerActor) return; if(activate && !aiRequest && !pOwnerActor->IsPlayer()) return; //Special FP stuff if(pOwnerActor->IsPlayer() && !m_lamparams.isLaser) return; m_laserActivated = activate; //Activate or deactivate effect?? if (!m_laserActivated) { AttachLAMLaser(false, eIGS_FirstPerson); AttachLAMLaser(false, eIGS_ThirdPerson); } else { bool tp = pOwnerActor->IsThirdPerson(); if(!tp && ok) { SAccessoryParams *params = pParent->GetAccessoryParams(GetEntity()->GetClass()->GetName()); if (!params) return; m_laserHelperFP.clear(); m_laserHelperFP = params->attach_helper.c_str(); m_laserHelperFP.replace("_LAM",""); } AttachLAMLaser(true, tp?eIGS_ThirdPerson:eIGS_FirstPerson); } if (m_laserActivated || m_lightActivated) GetGameObject()->EnablePostUpdates(this); if (!m_laserActivated && !m_lightActivated) GetGameObject()->DisablePostUpdates(this); }
//------------------------------------------------------------------------ bool CItem::SetGeometry(int slot, const ItemString& name, const ItemString& material, bool useParentMaterial, const Vec3& poffset, const Ang3& aoffset, float scale, bool forceReload) { assert(slot >= 0 && slot < eIGS_Last); bool changedfp=false; switch(slot) { case eIGS_Owner: break; case eIGS_FirstPerson: case eIGS_ThirdPerson: default: { if (name.empty() || forceReload) { GetEntity()->FreeSlot(slot); #ifndef ITEM_USE_SHAREDSTRING m_geometry[slot].resize(0); #else m_geometry[slot].reset(); #endif } DestroyAttachmentHelpers(slot); if (!name.empty()) { if (m_geometry[slot] != name) { const char* ext = PathUtil::GetExt(name.c_str()); if ((stricmp(ext, "chr") == 0) || (stricmp(ext, "cdf") == 0) || (stricmp(ext, "cga") == 0) ) GetEntity()->LoadCharacter(slot, name.c_str(), 0); else GetEntity()->LoadGeometry(slot, name.c_str(), 0, 0); changedfp=slot==eIGS_FirstPerson; } CreateAttachmentHelpers(slot); } /* if (slot == eIGS_FirstPerson) { ICharacterInstance *pCharacter = GetEntity()->GetCharacter(eIGS_FirstPerson); if (pCharacter) { pCharacter->SetFlags(pCharacter->GetFlags()&(~CS_FLAG_UPDATE)); } } else */if (slot == eIGS_Destroyed) DrawSlot(eIGS_Destroyed, false); } break; } Matrix34 slotTM; slotTM = Matrix34::CreateRotationXYZ(aoffset); slotTM.ScaleColumn(Vec3(scale, scale, scale)); slotTM.SetTranslation(poffset); GetEntity()->SetSlotLocalTM(slot, slotTM); if (changedfp && m_stats.mounted) { if (m_sharedparams->pMountParams && !m_sharedparams->pMountParams->pivot.empty()) { Matrix34 tm=GetEntity()->GetSlotLocalTM(eIGS_FirstPerson, false); Vec3 pivot = GetSlotHelperPos(eIGS_FirstPerson, m_sharedparams->pMountParams->pivot.c_str(), false); tm.AddTranslation(pivot); GetEntity()->SetSlotLocalTM(eIGS_FirstPerson, tm); } GetEntity()->InvalidateTM(); } m_geometry[slot] = name ? name : ItemString(); ReAttachAccessories(); IEntity* pParentEntity = gEnv->pEntitySystem->GetEntity(GetParentId()); IMaterial* pOverrideMaterial = 0; if (!material.empty()) { pOverrideMaterial = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(material.c_str()); } else if (useParentMaterial && pParentEntity) { ICharacterInstance* pParentCharacter = pParentEntity->GetCharacter(slot); IEntityRenderProxy* pParentRenderProxy = static_cast<IEntityRenderProxy*>(pParentEntity->GetProxy(ENTITY_PROXY_RENDER)); if (pParentCharacter) pOverrideMaterial = pParentCharacter->GetIMaterial(); else if (pParentRenderProxy) pOverrideMaterial = pParentRenderProxy->GetSlotMaterial(slot); } if (pOverrideMaterial) { ICharacterInstance* pCharacter = GetEntity()->GetCharacter(slot); IEntityRenderProxy* pRenderProxy = static_cast<IEntityRenderProxy*>(GetEntity()->GetProxy(ENTITY_PROXY_RENDER)); OverrideAttachmentMaterial(pOverrideMaterial, this, slot); if (pCharacter) pCharacter->SetIMaterial_Instance(pOverrideMaterial); else if (pRenderProxy) pRenderProxy->SetSlotMaterial(slot, pOverrideMaterial); } if(slot == eIGS_FirstPerson && IsSelected()) { CActor* pOwnerActor = GetOwnerActor(); IActionController *pActionController = GetActionController(); if(pActionController && pOwnerActor && pOwnerActor->IsClient()) { UpdateScopeContexts(pActionController); } } return true; }
void BrushSelector::ReloadTextureList(void) { CatalogMap catalogMap; mCatalogMap.clear(); if (!Ogre::ResourceGroupManager::getSingletonPtr()) return; mBrushesTree->Freeze(); mBrushesTree->DeleteAllItems(); wxTreeItemId rootId = mBrushesTree->AddRoot(/*_("Brushes")*/wxT("画刷列表")); // 重新解析定义文件 GetSceneManipulator()->reloadPaintInfo(); const Fairy::TerrainPaintInfoContainer *paintInfoContainer = GetSceneManipulator()->getTerrainPaintInfoContainer(); assert (paintInfoContainer); const Fairy::TextureInfoMap &textureInfoMap = paintInfoContainer->getTextureInfoMap(); OwnerTexs ownerTextures; Fairy::TextureInfoMap::const_iterator it = textureInfoMap.begin(); // 遍历画刷数组 while ( it != textureInfoMap.end() ) { const Fairy::TextureInfos &textureInfos = it->second; // 遍历该画刷下的所有纹理 for ( size_t i=0; i<textureInfos.size(); ++i ) { // 取出所属的大纹理的名称 Ogre::String ownerTexName = textureInfos[i].ownerTextureName; // 记录大纹理的名称 ownerTextures.insert(OwnerTexs::value_type(ownerTexName, ownerTexName)); // 如果该纹理名称中包含了/,说明它是在一个文件夹中的 size_t pos = ownerTexName.find_last_of('/'); // 在文件夹中 if (pos != Ogre::String::npos) { // 先去除纹理文件名,剩下路径名 ownerTexName.erase(pos+1); // 加上画刷的名称 ownerTexName.append(textureInfos[i].brushName); wxTreeItemId id = mBrushesTree->AppendItem( GetParentId(ownerTexName, catalogMap), wxT(textureInfos[i].textureName) ); mCatalogMap.insert(CatalogMap::value_type( textureInfos[i].textureName, id )); } else { Ogre::String brushName = textureInfos[i].brushName; // 如果是在根目录下,就直接用画刷名称来作为路径名 wxTreeItemId id = mBrushesTree->AppendItem( GetParentId(brushName, catalogMap), wxT(textureInfos[i].textureName) ); mCatalogMap.insert(CatalogMap::value_type( textureInfos[i].textureName, id )); } } ++it; } wxString lostTexNames = wxEmptyString; for (OwnerTexs::iterator ownerIt = ownerTextures.begin(); ownerIt != ownerTextures.end(); ++ownerIt) { Ogre::String texName = ownerIt->first; Ogre::FileInfoListPtr fileInfoList = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("Brushes",texName); Ogre::FileInfoList::const_iterator itBegin = fileInfoList->begin(); Ogre::FileInfoList::const_iterator itEnd = fileInfoList->end(); if (itBegin == itEnd) { lostTexNames+=wxT("\n"); lostTexNames+=texName.c_str(); continue; } Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName(texName); if (!texture.isNull()) { Ogre::TextureManager::getSingleton().remove(texName); Ogre::Image image; image.load(texName, Fairy::BRUSH_RESOURCE_GROUP_NAME); texture = Ogre::TextureManager::getSingleton() .loadImage(texName, Fairy::BRUSH_RESOURCE_GROUP_NAME, image); } } if (!lostTexNames.empty()) { wxMessageBox(wxT("以下贴图无法找到:")+lostTexNames); } mBrushesTree->Thaw(); }
//------------------------------------------------------------------ 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); }