// Calculates the desired position for the physics box, so that its center will be superimposed with AABB center of provided entity. // Also adjusts upwards to avoid any obvious floor clipping. Returns desired Position for entity. Vec3 CIntersectionAssistanceUnit::CalculateTargetAdjustPoint(const IEntity* pEntity, const Matrix34 &wMat, const Vec3& vStartingPos) const { // (if present + desired) adjust physbox center to that of owner Ent - to make sure centers of PhysBox + focal ent superimposed // at the desired position const IEntity* pFocalEnt = gEnv->pEntitySystem->GetEntity(m_focalEntityId); if(pFocalEnt) { OBB focalOBB; AABB focalAABB; // Compensate for actor/non actor entities that require different paths :( if(CPlayer* pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_focalEntityId))) { EStance playerStance = pPlayer->GetStance(); focalAABB = pPlayer->GetStanceInfo(playerStance)->GetStanceBounds(); } else { pFocalEnt->GetLocalBounds(focalAABB); } focalOBB.SetOBBfromAABB(Quat(IDENTITY), focalAABB); // shift to match focus ent Center (taking into account crouch etc if player). float fVerticalAdjust = focalOBB.h.z; // Additionally.. if the new test pos *would* immediately penetrate the floor (assumption based on any part of the volume being < player AABB z min value) // shift it up. float fFloorPenetrationAdjust = 0.0f; AABB wEntABB; pEntity->GetLocalBounds(wEntABB); wEntABB.SetTransformedAABB(wMat,wEntABB); float fFloorClearance = focalOBB.h.z - (wEntABB.GetSize().z * 0.5f); fFloorPenetrationAdjust += (0.0f - min(fFloorClearance, 0.0f)); // Apply floor clearance + Vertical adjust Vec3 desiredPos = wMat.GetTranslation() + Vec3(0.0f,0.0f,(fFloorPenetrationAdjust) * kFloorAdjustConstant); desiredPos += (fVerticalAdjust * pFocalEnt->GetWorldTM().GetColumn2() * kFloorAdjustConstant); return desiredPos; } return wMat.GetTranslation(); }
void CAreaProxy::SerializeXML( XmlNodeRef &entityNode,bool bLoading ) { if (m_nFlags & FLAG_NOT_SERIALIZE) return; if (bLoading) { XmlNodeRef areaNode = entityNode->findChild( "Area" ); if (!areaNode) return; int nId=0,nGroup=0,nPriority=0; float fProximity = 0; float fHeight = 0; areaNode->getAttr( "Id",nId ); areaNode->getAttr( "Group",nGroup ); areaNode->getAttr( "Proximity",fProximity ); areaNode->getAttr( "Priority",nPriority ); m_pArea->SetID(nId); m_pArea->SetGroup(nGroup); m_pArea->SetProximity(fProximity); m_pArea->SetPriority(nPriority); const char* token(0); XmlNodeRef pointsNode = areaNode->findChild( "Points" ); if (pointsNode) { for (int i = 0; i < pointsNode->getChildCount(); i++) { XmlNodeRef pntNode = pointsNode->getChild(i); Vec3 pos; if (pntNode->getAttr( "Pos",pos )) m_localPoints.push_back(pos); // Get sound obstruction bool bObstructSound = 0; pntNode->getAttr("ObstructSound", bObstructSound); m_abObstructSound.push_back(bObstructSound); } m_pArea->SetAreaType( ENTITY_AREA_TYPE_SHAPE ); areaNode->getAttr( "Height",fHeight ); m_pArea->SetHeight(fHeight); // Set points. OnMove(); } else if (areaNode->getAttr("SphereRadius",m_fRadius)) { // Sphere. areaNode->getAttr("SphereCenter",m_vCenter); m_pArea->SetSphere( m_pEntity->GetWorldTM().TransformPoint(m_vCenter),m_fRadius ); } else if (areaNode->getAttr("VolumeRadius",m_fRadius)) { areaNode->getAttr("Gravity",m_fGravity); areaNode->getAttr("DontDisableInvisible", m_bDontDisableInvisible); AABB box; box.Reset(); // Bezier Volume. pointsNode = areaNode->findChild( "BezierPoints" ); if (pointsNode) { for (int i = 0; i < pointsNode->getChildCount(); i++) { XmlNodeRef pntNode = pointsNode->getChild(i); Vec3 pt; if (pntNode->getAttr( "Pos",pt)) { m_bezierPoints.push_back(pt); box.Add( pt ); } } } m_pArea->SetAreaType( ENTITY_AREA_TYPE_GRAVITYVOLUME ); if (!m_pEntity->GetRenderProxy()) { IEntityRenderProxyPtr pRenderProxy = crycomponent_cast<IEntityRenderProxyPtr>(m_pEntity->CreateProxy( ENTITY_PROXY_RENDER )); m_pEntity->SetFlags(m_pEntity->GetFlags() | ENTITY_FLAG_SEND_RENDER_EVENT); if (box.min.x > box.max.x) box.min = box.max = Vec3(0,0,0); box.min-=Vec3(m_fRadius, m_fRadius, m_fRadius); box.max+=Vec3(m_fRadius, m_fRadius, m_fRadius); Matrix34 tm = m_pEntity->GetWorldTM_Fast(); box.SetTransformedAABB( m_pEntity->GetWorldTM_Fast().GetInverted(),box ); pRenderProxy->SetLocalBounds(box, true); } OnEnable(m_bIsEnable); } else if (areaNode->getAttr("AreaSolidFileName",&token)) { CCryFile file; int nAliasLen = sizeof("%level%")-1; const char* areaSolidFileName; if (strncmp(token,"%level%",nAliasLen) == 0) areaSolidFileName = GetIEntitySystem()->GetSystem()->GetI3DEngine()->GetLevelFilePath(token+nAliasLen); else areaSolidFileName = token; if( file.Open(areaSolidFileName,"rb") ) { int numberOfClosedPolygon = 0; int numberOfOpenPolygon = 0; m_pArea->BeginSettingSolid(m_pEntity->GetWorldTM()); file.ReadType(&numberOfClosedPolygon); file.ReadType(&numberOfOpenPolygon); ReadPolygonsForAreaSolid( file, numberOfClosedPolygon, true ); ReadPolygonsForAreaSolid( file, numberOfOpenPolygon, false ); m_pArea->EndSettingSolid(); } } else { // Box. Vec3 bmin(0,0,0),bmax(0,0,0); areaNode->getAttr("BoxMin",bmin); areaNode->getAttr("BoxMax",bmax); m_pArea->SetBox( bmin,bmax,m_pEntity->GetWorldTM() ); // Get sound obstruction XmlNodeRef const pNodeSoundData = areaNode->findChild("SoundData"); if (pNodeSoundData) { assert(m_abObstructSound.size() == 0); for (int i = 0; i < pNodeSoundData->getChildCount(); ++i) { XmlNodeRef const pNodeSide = pNodeSoundData->getChild(i); if (pNodeSide) { bool bObstructSound = false; pNodeSide->getAttr("ObstructSound", bObstructSound); m_abObstructSound.push_back(bObstructSound); } } } OnMove(); } m_pArea->ClearEntities(); XmlNodeRef entitiesNode = areaNode->findChild( "Entities" ); // Export Entities. if (entitiesNode) { for (int i = 0; i < entitiesNode->getChildCount(); i++) { XmlNodeRef entNode = entitiesNode->getChild(i); EntityId entityId; EntityGUID entityGuid; if(gEnv->pEntitySystem->EntitiesUseGUIDs()) { if (entNode->getAttr( "Guid",entityGuid )) m_pArea->AddEntity( entityGuid ); } else { if (entNode->getAttr( "Id",entityId )) m_pArea->AddEntity( entityId ); } } } } else { // Save points. XmlNodeRef areaNode = entityNode->newChild( "Area" ); areaNode->setAttr( "Id",m_pArea->GetID() ); areaNode->setAttr( "Group",m_pArea->GetGroup() ); areaNode->setAttr( "Proximity",m_pArea->GetProximity() ); areaNode->setAttr( "Priority", m_pArea->GetPriority() ); EEntityAreaType type = m_pArea->GetAreaType(); if (type == ENTITY_AREA_TYPE_SHAPE) { XmlNodeRef pointsNode = areaNode->newChild( "Points" ); for (unsigned int i = 0; i < m_localPoints.size(); i++) { XmlNodeRef pntNode = pointsNode->newChild("Point"); pntNode->setAttr( "Pos",m_localPoints[i] ); pntNode->setAttr("ObstructSound", m_abObstructSound[i]); } areaNode->setAttr( "Height",m_pArea->GetHeight() ); } else if (type == ENTITY_AREA_TYPE_SPHERE) { // Box. areaNode->setAttr("SphereCenter",m_vCenter); areaNode->setAttr("SphereRadius",m_fRadius); } else if (type == ENTITY_AREA_TYPE_BOX) { // Box. Vec3 bmin,bmax; m_pArea->GetBox(bmin,bmax); areaNode->setAttr("BoxMin",bmin); areaNode->setAttr("BoxMax",bmax); // Set sound obstruction XmlNodeRef const pNodeSoundData = areaNode->newChild("SoundData"); if (pNodeSoundData) { assert(m_abObstructSound.size() == 6); size_t nIndex = 0; tSoundObstructionIterConst const ItEnd = m_abObstructSound.end(); for (tSoundObstructionIterConst It = m_abObstructSound.begin(); It != ItEnd ; ++It) { bool const bObstructed = (bool)(*It); stack_string sTemp; sTemp.Format("Side%d", ++nIndex); XmlNodeRef const pNodeSide = pNodeSoundData->newChild(sTemp.c_str()); pNodeSide->setAttr("ObstructSound", bObstructed); } } } else if (type == ENTITY_AREA_TYPE_GRAVITYVOLUME) { areaNode->setAttr("VolumeRadius",m_fRadius); areaNode->setAttr("Gravity",m_fGravity); areaNode->setAttr("DontDisableInvisible", m_bDontDisableInvisible); XmlNodeRef pointsNode = areaNode->newChild( "BezierPoints" ); for (unsigned int i = 0; i < m_bezierPoints.size(); i++) { XmlNodeRef pntNode = pointsNode->newChild("Point"); pntNode->setAttr( "Pos",m_bezierPoints[i] ); } } #ifdef SW_ENTITY_ID_USE_GUID const std::vector<EntityGUID>& entGUIDs=*m_pArea->GetEntitiesGuid(); // Export Entities. if (!entGUIDs.empty()) { XmlNodeRef nodes = areaNode->newChild( "Entities" ); for (uint32 i = 0; i < entGUIDs.size(); i++) { EntityGUID guid = entGUIDs[i]; XmlNodeRef entNode = nodes->newChild( "Entity" ); entNode->setAttr( "Guid",guid ); entNode->setAttr( "Id",gEnv->pEntitySystem->GenerateEntityIdFromGuid(guid) ); } } #else const std::vector<EntityId>& entIDs=*m_pArea->GetEntities(); // Export Entities. if (!entIDs.empty()) { XmlNodeRef nodes = areaNode->newChild( "Entities" ); for (uint32 i = 0; i < entIDs.size(); i++) { int entityId = entIDs[i]; XmlNodeRef entNode = nodes->newChild( "Entity" ); entNode->setAttr( "Id",entityId ); } } #endif } }