void CItemCommCrystal::OnMoveFrom() { // Being removed from the top level. CSector * pSector = GetTopPoint().GetSector(); ASSERT(pSector); pSector->RemoveListenItem(); }
/// Funktion erteilt einen Terraformbefehl, sofern dies auch möglich ist. /// @param pShip Zeiger des Schiffes /// @return <code>true</code> wenn ein Terraformbefehl gegeben werden könnte bool CShipAI::DoTerraform(CShips* pShip) { if (!pShip) { ASSERT(pShip); return false; } // Es wird jeder Planet sofort genommen, welcher weniger als 8 Runden zum Terraformen // benötigt. Planeten welche mehr Runden zum Terraformen benötigen werden nur ausgewählt, // wenn in dem Sektor kein Planet zum sofortigen Kolonisieren zur Verfügung steht int nTerraPoints = pShip->GetColonizePoints(); if (nTerraPoints <= 0) return false; CSector* pSector = &m_pDoc->GetSector(pShip->GetKO().x, pShip->GetKO().y); // nur wenn der Sektor noch niemandem gehört bzw. uns selbst ist, sollen Planeten terraformt werden if (pSector->GetOwnerOfSector() != "" && pSector->GetOwnerOfSector() != pShip->GetOwnerOfShip()) return false; int nMinTerraPoints = INT_MAX; short nPlanet = -1; bool bColonizable = false; for (int j = 0; j < pSector->GetNumberOfPlanets(); j++) { const CPlanet* pPlanet = pSector->GetPlanet(j); // Planet überhaupt bewohnbar? if (!pPlanet->GetHabitable()) continue; // Planet schon terraformt? if (pPlanet->GetTerraformed()) { // und noch nicht kolonisiert? if (!pPlanet->GetColonized()) bColonizable = true; } else if (pPlanet->GetNeededTerraformPoints() < nMinTerraPoints) { nMinTerraPoints = pPlanet->GetNeededTerraformPoints(); nPlanet = j; } } // Wurde ein zu terraformender Planet gefunden und würden weniger als 6 Runden // zum Terraformen benötigt werden oder es gibt keinen Planeten, der // sofort kolonisiert werden könnte, dann den gefundenen Planeten terraformen if (nPlanet != -1 && (!bColonizable || nMinTerraPoints / nTerraPoints < 8)) { // Hier muss als erstes ein möglicher neuer Kurs gelöscht werden pShip->SetTargetKO(CPoint(-1, -1)); pShip->SetTerraform(nPlanet); return true; } return false; }
bool CRegionBase::RealizeRegion() { ADDTOCALLSTACK("CRegionBase::RealizeRegion"); // Link the region to the world. RETURN: false = not valid. if ( IsRegionEmpty() ) return false; if ( !m_pt.IsValidPoint() ) m_pt = GetRegionCorner( DIR_QTY ); // center // Attach to all sectors that i overlap. ASSERT( m_iLinkedSectors == 0 ); for ( long l = 0; l < g_MapList.GetSectorQty(m_pt.m_map); l++ ) { CSector *pSector = g_World.GetSector(m_pt.m_map, l); if ( pSector && IsOverlapped(pSector->GetRect()) ) { // Yes, this sector overlapped, so add it to the sector list if ( !pSector->LinkRegion(this) ) { g_Log.EventError("Linking sector #%ld for map %d for region %s failed (fatal for this region).\n", l, m_pt.m_map, GetName()); return false; } m_iLinkedSectors++; } } return true; }
void CSector::GoAwake() { ADDTOCALLSTACK("CSector::GoAwake"); ProfileTask charactersTask(PROFILE_TIMERS); CTimedObject::GoAwake(); // Awake it first, otherwise other things won't work. CChar * pCharNext = nullptr; CChar * pChar = static_cast <CChar*>(m_Chars_Active.GetHead()); for (; pChar != nullptr; pChar = pCharNext) { pCharNext = pChar->GetNext(); if (pChar->IsSleeping()) pChar->GoAwake(); } pChar = static_cast<CChar*>(m_Chars_Disconnect.GetHead()); for (; pChar != nullptr; pChar = pCharNext) { pCharNext = pChar->GetNext(); if (pChar->IsSleeping()) pChar->GoAwake(); } CItem * pItemNext = nullptr; CItem * pItem = static_cast <CItem*>(m_Items_Timer.GetHead()); for (; pItem != nullptr; pItem = pItemNext) { pItemNext = pItem->GetNext(); if (pItem->IsSleeping()) pItem->GoAwake(); } pItem = static_cast <CItem*>(m_Items_Inert.GetHead()); for (; pItem != nullptr; pItem = pItemNext) { pItemNext = pItem->GetNext(); if (pItem->IsSleeping()) pItem->GoAwake(); } /* * Awake adjacent sectors when awaking this one to avoid the effect * of NPCs being stop until you enter the sector, or all the spawns * generating NPCs at once. */ static CSector *pCentral = nullptr; // do this only for the awaken sector if (!pCentral) { pCentral = this; for (int i = 0; i < (int)DIR_QTY; ++i) { CSector *pSector = GetAdjacentSector((DIR_TYPE)i); if (pSector && !pSector->IsSleeping()) { pSector->GoAwake(); } } pCentral = nullptr; } OnTick(); // Unknown time passed, make the sector tick now to reflect any possible environ changes. }
void CItemCommCrystal::OnMoveFrom() { ADDTOCALLSTACK("CItemCommCrystal::OnMoveFrom"); // Being removed from the top level. CSector *pSector = GetTopSector(); if ( pSector ) pSector->RemoveListenItem(); }
void __fastcall TfraSector::ebCaptureInsideVolumeClick(TObject *Sender) { CSector* S = PortalUtils.GetSelectedSector(); if (S){ S->CaptureInsideVolume(); Scene->UndoSave(); } }
// Move this item to it's point in the world. (ground/top level) bool CItemCommCrystal::MoveTo(CPointMap pt, bool bForceFix) { ADDTOCALLSTACK("CItemCommCrystal::MoveTo"); CSector *pSector = pt.GetSector(); ASSERT(pSector); pSector->AddListenItem(); return CItem::MoveTo(pt, bForceFix); }
void __fastcall TfraSector::ebDistributeObjectsClick(TObject *Sender) { CSector* S = PortalUtils.GetSelectedSector(); if (S){ S->DistributeInsideObjects (); Scene->UndoSave (); } }
bool CItemCommCrystal::MoveTo( CPointMap pt ) // Put item on the ground here. { // Move this item to it's point in the world. (ground/top level) CSector * pSector = pt.GetSector(); ASSERT(pSector); pSector->AddListenItem(); return CItem::MoveTo(pt); }
bool CItemCommCrystal::MoveTo(CPointMap pt, bool bForceFix ) // Put item on the ground here. { ADDTOCALLSTACK("CItemCommCrystal::MoveTo"); // Move this item to it's point in the world. (ground/top level) CSector * pSector = pt.GetSector(); ASSERT(pSector); pSector->AddListenItem(); return CItem::MoveTo(pt, bForceFix); }
bool CTeleport::RealizeTeleport() { ADDTOCALLSTACK("CTeleport::RealizeTeleport"); if ( !IsValidPoint() || !m_ptDst.IsValidPoint() ) { DEBUG_ERR(("Bad teleport coords %s\n", WriteUsed())); return false; } CSector *pSector = GetSector(); return pSector ? pSector->AddTeleport(this) : false; }
//////new version database read and save bool CAirportsManager::loadDatabase(CAirportDatabase* pAirportDatabase) { ASSERT(pAirportDatabase); if(!pAirportDatabase) return false; Clear(); CString strSQL(_T("")); CADORecordset adoAirportRecordset; long lCount = 0 ; strSQL.Format(_T("SELECT * FROM TB_AIRPORTDB_AIRPORT")); try { CDatabaseADOConnetion::ExecuteSQLStatement(strSQL,lCount,adoAirportRecordset,pAirportDatabase->GetAirportConnection()) ; } catch (CADOException& e) { e.ErrorMessage(); return false; } while(!adoAirportRecordset.IsEOF()) { CAirport* pAirport = new CAirport; pAirport->loadDatabase(adoAirportRecordset); m_vAirports.push_back(pAirport); adoAirportRecordset.MoveNextData(); } //read all sector CADORecordset adoSectorRecordset; strSQL.Format(_T("SELECT * FROM TB_AIRPORTDB_SECTOR")); try { CDatabaseADOConnetion::ExecuteSQLStatement(strSQL,lCount,adoSectorRecordset,pAirportDatabase->GetAirportConnection()); } catch (CADOException& e) { e.ErrorMessage(); return false; } while(!adoSectorRecordset.IsEOF()) { CSector* pSector = new CSector(this); pSector->loadDatabase(adoSectorRecordset,pAirportDatabase); m_vSectors.push_back(pSector); adoSectorRecordset.MoveNextData(); } return true; }
size_t CPointBase::GetRegions( DWORD dwType, CRegionLinks & rlinks ) const { ADDTOCALLSTACK("CPointBase::GetRegions"); if ( !IsValidPoint() ) return 0; CSector *pSector = GetSector(); if ( pSector ) return pSector->GetRegions(*this, dwType, rlinks); return 0; }
void CAirportsManager::AddSector(CString sSectorName, CAIRPORTFILTER airportFilter) { for(unsigned i=0; i<m_vSectors.size(); i++) { CSector* pSector = m_vSectors[i]; if(pSector->m_sName.Compare(sSectorName) == 0) { //found sector pSector->AddFilter(airportFilter); return; } } CSector* pSector = new CSector( this ); pSector->m_sName = sSectorName; pSector->AddFilter(airportFilter); m_vSectors.push_back(pSector); }
bool CTeleport::RealizeTeleport() { ADDTOCALLSTACK("CTeleport::RealizeTeleport"); if ( ! IsCharValid() || ! m_ptDst.IsCharValid()) { DEBUG_ERR(( "CTeleport bad coords %s\n", WriteUsed() )); return false; } CSector *pSector = GetSector(); if ( pSector ) return pSector->AddTeleport(this); else return false; }
bool CFat32Device::ReadFromCache(unsigned long sector, unsigned char *buffer) { // round sector size down to page size unsigned long page = sector & ~(FAT_PAGE_SIZE / m_sectorsize - 1); FATCACHE::iterator it = m_cache.find(page); if (it != m_cache.end()) { cacheHit++; CSector *cacheSector = (*it).second; cacheSector->IncrementUsage(timeGetTime()); fast_memcpy(buffer, cacheSector->Get() + (sector - page)*m_sectorsize, m_sectorsize); return true; } return false; }
CRegionBase * CPointBase::GetRegion( DWORD dwType ) const { ADDTOCALLSTACK("CPointBase::GetRegion"); // What region in the current CSector am i in ? // We only need to update this every 8 or so steps ? // REGION_TYPE_AREA if ( ! IsValidPoint()) return NULL; CSector *pSector = GetSector(); if ( pSector ) return pSector->GetRegion(*this, dwType); return NULL; }
void CRegionBase::UnRealizeRegion() { ADDTOCALLSTACK("CRegionBase::UnRealizeRegion"); // remove myself from the world. // used in the case of a ship where the region will move. for ( int i=0; ; i++ ) { CSector * pSector = GetSector(i); if ( pSector == NULL ) break; // Does the rect overlap ? if ( ! IsOverlapped( pSector->GetRect())) continue; if ( pSector->UnLinkRegion( this )) m_iLinkedSectors--; } }
bool CRegionBase::SendSectorsVerb( LPCTSTR pszVerb, LPCTSTR pszArgs, CTextConsole * pSrc ) { ADDTOCALLSTACK("CRegionBase::SendSectorsVerb"); // Send a command to all the CSectors in this region. bool fRet = false; for ( int i=0; ; i++ ) { CSector * pSector = GetSector(i); if ( pSector == NULL ) break; // Does the rect overlap ? if ( IsOverlapped( pSector->GetRect() ) ) { CScript script( pszVerb, pszArgs ); fRet |= pSector->r_Verb( script, pSrc ); } } return( fRet ); }
/// Funktion erteilt einen Kolonisierungsbefehl, sofern dies auch möglich ist. /// @param pShip Zeiger des Schiffes /// @return <code>true</code> wenn ein Kolonisierungsbefehl gegeben werden könnte bool CShipAI::DoColonize(CShips* pShip) { if (!pShip) { ASSERT(pShip); return false; } // Kolonieschiffe eine Kolonisierung vorschlagen if (pShip->GetShipType() != SHIP_TYPE::COLONYSHIP) return false; CSector* pSector = &m_pDoc->GetSector(pShip->GetKO().x, pShip->GetKO().y); // Gehört der Sektor aktuell auch keiner Minorrace (also niemanden oder uns selbst) if (pSector->GetOwnerOfSector() != "" && pSector->GetOwnerOfSector() != pShip->GetOwnerOfShip()) return false; // Kolonisierungsbefehl geben for (int i = 0; i < pSector->GetNumberOfPlanets(); i++) { if (pSector->GetPlanet(i)->GetTerraformed() && !pSector->GetPlanet(i)->GetColonized()) { // Hier muss als erstes ein möglicher neuer Kurs gelöscht werden pShip->SetTargetKO(CPoint(-1, -1)); pShip->SetCurrentOrder(SHIP_ORDER::COLONIZE); return true; } } return false; }
void CRender::Load3DFluid() { //if (strstr(Core.Params,"-no_volumetric_fog")) if (!RImplementation.o.volumetricfog) return; string_path fn_game; if ( FS.exist( fn_game, "$level$", "level.fog_vol" ) ) { IReader *F = FS.r_open( fn_game ); u16 version = F->r_u16(); if(version == 3) { u32 cnt = F->r_u32(); for(u32 i=0; i<cnt; ++i) { dx103DFluidVolume *pVolume = xr_new<dx103DFluidVolume>(); pVolume->Load("", F, 0); // Attach to sector's static geometry CSector *pSector = (CSector*)detectSector(pVolume->getVisData().sphere.P); // 3DFluid volume must be in render sector VERIFY(pSector); dxRender_Visual* pRoot = pSector->root(); // Sector must have root VERIFY(pRoot); VERIFY(pRoot->getType() == MT_HIERRARHY); ((FHierrarhyVisual*)pRoot)->children.push_back(pVolume); } } FS.r_close(F); } }
void CFat32Device::CachePage(unsigned long page, unsigned char *buffer) { DWORD time = timeGetTime(); if (m_cache.size() >= CACHE_SIZE) { // remove the last used cache FATCACHE::iterator lastUsed = m_cache.begin(); //CStdString usage; unsigned long smallest = 0; for (FATCACHE::iterator it = m_cache.begin(); it != m_cache.end(); ++it) { if ((*it).second->Usage(time) > (*lastUsed).second->Usage(time)) lastUsed = it; if ((*it).second->Usage(time) < smallest) smallest = (*it).second->Usage(time); /* CStdString log; if ((*it).second->Usage(time) > 0xFF) log = "FF "; else log.Format("%02x ", (*it).second->Usage()); usage += log;*/ } //CLog::Log(LOGDEBUG, "%s", usage.c_str()); // lastUsed is the one we remove unsigned long oldpage = (*lastUsed).first; CSector *sector = (*lastUsed).second; m_cache.erase(lastUsed); // CLog::Log(LOGDEBUG, "Swapping page %i for page %i, oldest usage: %d (%d)", oldpage, page, sector->Usage(time), smallest); #ifdef FAT32_ALLOW_WRITING // write it out to disk if dirty if (sector->IsDirty()) WritePage(oldpage, sector->Get()); #endif delete sector; } // cache our page m_cache.insert(pair<unsigned int, CSector *>(page, new CSector(buffer, time))); }
void CNgcScene::plat_post_load() { // Now turn the temporary mesh lists into mesh arrays. mp_sector_table->IterateStart(); CSector* pSector = mp_sector_table->IterateNext(); while( pSector ) { CNgcGeom *p_Ngc_geom = static_cast<CNgcGeom*>(pSector->GetGeom()); p_Ngc_geom->CreateMeshArray(); // First time through we just want to count the meshes, p_Ngc_geom->RegisterMeshArray( true ); pSector = mp_sector_table->IterateNext(); } // Now we have counted all the meshes, tell the engine to create the arrays to hold them. GetEngineScene()->CreateMeshArrays(); // Now go through and actually add the meshes. mp_sector_table->IterateStart(); pSector = mp_sector_table->IterateNext(); while( pSector ) { // Access platform dependent data. CNgcGeom *p_Ngc_geom = static_cast<CNgcGeom*>(pSector->GetGeom()); p_Ngc_geom->RegisterMeshArray( false ); pSector = mp_sector_table->IterateNext(); } // Now all meshes are registered, tell the engine to sort them. GetEngineScene()->SortMeshes(); }
void CRender::render_main (Fmatrix& m_ViewProjection, bool _fportals) { // Msg ("---begin"); marker ++; // Calculate sector(s) and their objects if (pLastSector) { //!!! //!!! BECAUSE OF PARALLEL HOM RENDERING TRY TO DELAY ACCESS TO HOM AS MUCH AS POSSIBLE //!!! { // Traverse object database g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE + STYPE_LIGHTSOURCE, ViewBase ); // (almost) Exact sorting order (front-to-back) std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); // Determine visibility for dynamic part of scene set_Object (0); u32 uID_LTRACK = 0xffffffff; if (phase==PHASE_NORMAL) { uLastLTRACK ++; if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); // update light-vis for current entity / actor CObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { CROS_impl* R = (CROS_impl*) O->ROS(); if (R) R->update (O); } // update light-vis for selected entity // track lighting environment if (lstRenderables.size()) { IRenderable* renderable = lstRenderables[uID_LTRACK]->dcast_Renderable (); if (renderable) { CROS_impl* T = (CROS_impl*)renderable->renderable_ROS (); if (T) T->update (renderable); } } } } // Traverse sector/portal structure PortalTraverser.traverse ( pLastSector, ViewBase, Device.vCameraPosition, m_ViewProjection, CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE //. disabled scissoring (HW.Caps.bScissor?CPortalTraverser::VQ_SCISSOR:0) // generate scissoring info ); // Determine visibility for static geometry hierrarhy for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; IRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } // Traverse frustums for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; spatial->spatial_updatesector (); CSector* sector = (CSector*)spatial->spatial.sector; if (0==sector) continue; // disassociated from S/P structure if (spatial->spatial.type & STYPE_LIGHTSOURCE) { // lightsource light* L = (light*) (spatial->dcast_Light()); VERIFY (L); float lod = L->get_LOD (); if (lod>EPS_L) { vis_data& vis = L->get_homdata ( ); if (HOM.visible(vis)) Lights.add_light (L); } continue ; } if (PortalTraverser.i_marker != sector->r_marker) continue; // inactive (untouched) sector for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { CFrustum& view = sector->r_frustums[v_it]; if (!view.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R)) continue; if (spatial->spatial.type & STYPE_RENDERABLE) { // renderable IRenderable* renderable = spatial->dcast_Renderable (); VERIFY (renderable); // Occlusion vis_data& v_orig = renderable->renderable.visual->vis; vis_data v_copy = v_orig; v_copy.box.xform (renderable->renderable.xform); BOOL bVisible = HOM.visible(v_copy); v_orig.marker = v_copy.marker; v_orig.accept_frame = v_copy.accept_frame; v_orig.hom_frame = v_copy.hom_frame; v_orig.hom_tested = v_copy.hom_tested; if (!bVisible) break; // exit loop on frustums // Rendering set_Object (renderable); renderable->renderable_Render (); set_Object (0); } break; // exit loop on frustums } } if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD } else { set_Object (0); if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD } }
void CRandomEventCtrl::CalcShipEvents() const { if (!IsActivated()) return; CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); // Hüllenvirus for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++) { for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++) { // 0.1% Wahrscheinlichkeit für einen Hüllenvirus pro Sektor if (rand()%1000 != 0) continue; // gibt es keine Schiffe im Sektor, dann macht ein Hüllenvirus auch nichts CSector* pSector = &(pDoc->GetSystem(x, y)); if (!pSector->GetIsShipInSector()) continue; // allen Schiffe im Sektor die Hülle auf 1 reduzieren (außer Aliens) for (CShipMap::iterator i = pDoc->m_ShipMap.begin(); i != pDoc->m_ShipMap.end(); ++i) { if (i->second->IsAlien()) continue; if (i->second->GetCo() != pSector->GetCo()) continue; int nCurrentHull = i->second->GetHull()->GetCurrentHull(); i->second->GetHull()->SetCurrentHull(-(nCurrentHull - 1), true); // allen Schiffen in der Flotte ebenfalls die Hülle auf 1 setzen for (CShips::iterator j = i->second->begin(); j != i->second->end(); ++j) { nCurrentHull = j->second->GetHull()->GetCurrentHull(); j->second->GetHull()->SetCurrentHull(-(nCurrentHull - 1), true); } } // Nachrichten an alle Major welche Schiffe in diesem Sektor hatten const std::map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); for (map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { if (!pSector->GetOwnerOfShip(it->first, true)) continue; CMajor* pMajor = it->second; if (!pMajor) continue; const CString& sSectorName = pSector->CoordsName(true); CString sMessageText = CLoc::GetString("EVENTHULLVIRUS", false, sSectorName); CEmpireNews message; message.CreateNews(sMessageText,EMPIRE_NEWS_TYPE::MILITARY,pSector->GetName(),pSector->GetCo()); pMajor->GetEmpire()->AddMsg(message); if (pMajor->IsHumanPlayer()) { resources::pClientWorker->SetToEmpireViewFor(*pMajor); pMajor->GetEmpire()->PushEvent(boost::make_shared<CEventRandom>(pMajor->GetRaceID(), "HullVirus", sMessageText, "")); } } } } }
void CSector::traverse (CFrustum &F, _scissor& R_scissor) { // Register traversal process if (r_marker != PortalTraverser.i_marker) { r_marker = PortalTraverser.i_marker; PortalTraverser.r_sectors.push_back (this); r_frustums.clear (); r_scissors.clear (); } r_frustums.push_back (F); r_scissors.push_back (R_scissor); // Search visible portals and go through them sPoly S,D; for (u32 I=0; I<m_portals.size(); I++) { if (m_portals[I]->marker == PortalTraverser.i_marker) continue; CPortal* PORTAL = m_portals[I]; CSector* pSector; // Select sector (allow intersecting portals to be finely classified) if (PORTAL->bDualRender) { pSector = PORTAL->getSector (this); } else { pSector = PORTAL->getSectorBack (PortalTraverser.i_vBase); if (pSector==this) continue; if (pSector==PortalTraverser.i_start) continue; } // Early-out sphere if (!F.testSphere_dirty(PORTAL->S.P,PORTAL->S.R)) continue; // SSA (if required) if (PortalTraverser.i_options&CPortalTraverser::VQ_SSA) { Fvector dir2portal; dir2portal.sub (PORTAL->S.P, PortalTraverser.i_vBase); float R = PORTAL->S.R ; float distSQ = dir2portal.square_magnitude(); float ssa = R*R/distSQ; dir2portal.div (_sqrt(distSQ)); ssa *= _abs(PORTAL->P.n.dotproduct(dir2portal)); if (ssa<r_ssaDISCARD) continue; if (PortalTraverser.i_options&CPortalTraverser::VQ_FADE) { if (ssa<r_ssaLOD_A) PortalTraverser.fade_portal (PORTAL,ssa); if (ssa<r_ssaLOD_B) continue ; } } // Clip by frustum svector<Fvector,8>& POLY = PORTAL->getPoly(); S.assign (&*POLY.begin(),POLY.size()); D.clear(); sPoly* P = F.ClipPoly(S,D); if (0==P) continue; // Scissor and optimized HOM-testing _scissor scissor ; if (PortalTraverser.i_options&CPortalTraverser::VQ_SCISSOR && (!PORTAL->bDualRender)) { // Build scissor rectangle in projection-space Fbox2 bb; bb.invalidate(); float depth = flt_max; sPoly& p = *P; for (u32 vit=0; vit<p.size(); vit++) { Fvector4 t; Fmatrix& M = PortalTraverser.i_mXFORM_01; Fvector& v = p[vit]; t.x = v.x*M._11 + v.y*M._21 + v.z*M._31 + M._41; t.y = v.x*M._12 + v.y*M._22 + v.z*M._32 + M._42; t.z = v.x*M._13 + v.y*M._23 + v.z*M._33 + M._43; t.w = v.x*M._14 + v.y*M._24 + v.z*M._34 + M._44; t.mul (1.f/t.w); if (t.x < bb.min.x) bb.min.x = t.x; if (t.x > bb.max.x) bb.max.x = t.x; if (t.y < bb.min.y) bb.min.y = t.y; if (t.y > bb.max.y) bb.max.y = t.y; if (t.z < depth) depth = t.z; } // Msg ("bb(%s): (%f,%f)-(%f,%f), d=%f", PORTAL->bDualRender?"true":"false",bb.min.x, bb.min.y, bb.max.x, bb.max.y,depth); if (depth<EPS) { scissor = R_scissor; // Cull by HOM (slower algo) if ( (PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && (!RImplementation.HOM.visible(*P)) ) continue; } else { // perform intersection (this is just to be sure, it is probably clipped in 3D already) if (bb.min.x > R_scissor.min.x) scissor.min.x = bb.min.x; else scissor.min.x = R_scissor.min.x; if (bb.min.y > R_scissor.min.y) scissor.min.y = bb.min.y; else scissor.min.y = R_scissor.min.y; if (bb.max.x < R_scissor.max.x) scissor.max.x = bb.max.x; else scissor.max.x = R_scissor.max.x; if (bb.max.y < R_scissor.max.y) scissor.max.y = bb.max.y; else scissor.max.y = R_scissor.max.y; scissor.depth = depth; // Msg ("scissor: (%f,%f)-(%f,%f)", scissor.min.x, scissor.min.y, scissor.max.x, scissor.max.y); // Check if box is non-empty if (scissor.min.x >= scissor.max.x) continue; if (scissor.min.y >= scissor.max.y) continue; // Cull by HOM (faster algo) if ( (PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && (!RImplementation.HOM.visible(scissor,depth)) ) continue; } } else { scissor = R_scissor; // Cull by HOM (slower algo) if ( (PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && (!RImplementation.HOM.visible(*P)) ) continue; } // Create _new_ frustum and recurse CFrustum Clip; Clip.CreateFromPortal (P, PORTAL->P.n, PortalTraverser.i_vBase,PortalTraverser.i_mXFORM); PORTAL->marker = PortalTraverser.i_marker; PORTAL->bDualRender = FALSE; pSector->traverse (Clip,scissor); } }
bool CPointBase::r_WriteVal( LPCTSTR pszKey, CGString & sVal ) const { ADDTOCALLSTACK("CPointBase::r_WriteVal"); if ( !strnicmp( pszKey, "STATICS", 7 ) ) { pszKey += 7; const CGrayMapBlock * pBlock = g_World.GetMapBlock( *(this) ); if ( !pBlock ) return false; if ( *pszKey == '\0' ) { int iStaticQty = 0; for ( size_t i = 0; i < pBlock->m_Statics.GetStaticQty(); i++ ) { const CUOStaticItemRec * pStatic = pBlock->m_Statics.GetStatic( i ); CPointMap ptTest( pStatic->m_x+pBlock->m_x, pStatic->m_y+pBlock->m_y, pStatic->m_z, this->m_map ); if ( this->GetDist( ptTest ) > 0 ) continue; iStaticQty++; } sVal.FormatVal( iStaticQty ); return true; } SKIP_SEPARATORS( pszKey ); const CUOStaticItemRec * pStatic = NULL; int iStatic = 0; int type = 0; if ( !strnicmp( pszKey, "FINDID", 6 ) ) { pszKey += 6; SKIP_SEPARATORS( pszKey ); iStatic = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iStatic ); if ( type == 0 ) type = RES_ITEMDEF; SKIP_SEPARATORS( pszKey ); } else { iStatic = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iStatic ); } if ( type == RES_ITEMDEF ) { const CItemBase * pItemDef = CItemBase::FindItemBase(static_cast<ITEMID_TYPE>(RES_GET_INDEX(iStatic))); if ( !pItemDef ) { sVal.FormatVal( 0 ); return false; } for ( size_t i = 0; i < pBlock->m_Statics.GetStaticQty(); pStatic = NULL, i++ ) { pStatic = pBlock->m_Statics.GetStatic( i ); CPointMap ptTest( pStatic->m_x+pBlock->m_x, pStatic->m_y+pBlock->m_y, pStatic->m_z, this->m_map); if ( this->GetDist( ptTest ) > 0 ) continue; if ( pStatic->GetDispID() == pItemDef->GetDispID() ) break; } } else { for ( size_t i = 0; i < pBlock->m_Statics.GetStaticQty(); pStatic = NULL, i++ ) { pStatic = pBlock->m_Statics.GetStatic( i ); CPointMap ptTest( pStatic->m_x+pBlock->m_x, pStatic->m_y+pBlock->m_y, pStatic->m_z, this->m_map); if ( this->GetDist( ptTest ) > 0 ) continue; if ( iStatic == 0 ) break; iStatic--; } } if ( !pStatic ) { sVal.FormatHex(0); return true; } SKIP_SEPARATORS( pszKey ); if ( !*pszKey ) pszKey = "ID"; ITEMID_TYPE idTile = pStatic->GetDispID(); if ( !strnicmp( pszKey, "COLOR", 5 ) ) { sVal.FormatHex( pStatic->m_wHue ); return true; } else if ( !strnicmp( pszKey, "ID", 2 ) ) { sVal.FormatHex( idTile ); return true; } else if ( !strnicmp( pszKey, "Z", 1 ) ) { sVal.FormatVal( pStatic->m_z ); return true; } // Check the script def for the item. CItemBase * pItemDef = CItemBase::FindItemBase( idTile ); if ( pItemDef == NULL ) { DEBUG_ERR(("Must have ITEMDEF section for item ID 0%x\n", idTile )); return false; } return pItemDef->r_WriteVal( pszKey, sVal, &g_Serv ); } else if ( !strnicmp( pszKey, "COMPONENTS", 10) ) { pszKey += 10; CRegionLinks rlinks; const CRegionBase* pRegion = NULL; CItem* pItem = NULL; const CGrayMulti* pMulti = NULL; const CUOMultiItemRec2* pMultiItem = NULL; size_t iMultiQty = GetRegions(REGION_TYPE_MULTI, rlinks); if ( *pszKey == '\0' ) { int iComponentQty = 0; for (size_t i = 0; i < iMultiQty; i++) { pRegion = rlinks.GetAt(i); if (pRegion == NULL) continue; pItem = pRegion->GetResourceID().ItemFind(); if (pItem == NULL) continue; const CPointMap ptMulti = pItem->GetTopPoint(); pMulti = g_Cfg.GetMultiItemDefs(pItem); if (pMulti == NULL) continue; size_t iQty = pMulti->GetItemCount(); for (size_t ii = 0; ii < iQty; ii++) { pMultiItem = pMulti->GetItem(ii); if (pMultiItem == NULL) break; if (pMultiItem->m_visible == 0) continue; CPointMap ptTest(static_cast<WORD>(ptMulti.m_x + pMultiItem->m_dx), static_cast<WORD>(ptMulti.m_y + pMultiItem->m_dy), static_cast<signed char>(ptMulti.m_z + pMultiItem->m_dz), this->m_map); if (GetDist(ptTest) > 0) continue; iComponentQty++; } } sVal.FormatVal( iComponentQty ); return true; } SKIP_SEPARATORS( pszKey ); int iComponent = 0; int type = 0; if ( strnicmp( pszKey, "FINDID", 6 ) == 0 ) { pszKey += 6; SKIP_SEPARATORS( pszKey ); iComponent = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iComponent ); if ( type == 0 ) type = RES_ITEMDEF; SKIP_SEPARATORS( pszKey ); } else { iComponent = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iComponent ); } if ( type == RES_ITEMDEF ) { const CItemBase * pItemDef = CItemBase::FindItemBase(static_cast<ITEMID_TYPE>(RES_GET_INDEX(iComponent))); if ( pItemDef == NULL ) { sVal.FormatVal( 0 ); return false; } for (size_t i = 0; i < iMultiQty; i++) { pRegion = rlinks.GetAt(i); if (pRegion == NULL) continue; pItem = pRegion->GetResourceID().ItemFind(); if (pItem == NULL) continue; const CPointMap ptMulti = pItem->GetTopPoint(); pMulti = g_Cfg.GetMultiItemDefs(pItem); if (pMulti == NULL) continue; size_t iQty = pMulti->GetItemCount(); for (size_t ii = 0; ii < iQty; pMultiItem = NULL, ii++) { pMultiItem = pMulti->GetItem(ii); if (pMultiItem == NULL) break; if (pMultiItem->m_visible == 0) continue; CPointMap ptTest(static_cast<WORD>(ptMulti.m_x + pMultiItem->m_dx), static_cast<WORD>(ptMulti.m_y + pMultiItem->m_dy), static_cast<signed char>(ptMulti.m_z + pMultiItem->m_dz), this->m_map); if (GetDist(ptTest) > 0) continue; const CItemBase* pMultiItemDef = CItemBase::FindItemBase(pMultiItem->GetDispID()); if (pMultiItemDef != NULL && pMultiItemDef->GetDispID() == pItemDef->GetDispID()) break; } if (pMultiItem != NULL) break; } } else { for (size_t i = 0; i < iMultiQty; i++) { pRegion = rlinks.GetAt(i); if (pRegion == NULL) continue; pItem = pRegion->GetResourceID().ItemFind(); if (pItem == NULL) continue; const CPointMap ptMulti = pItem->GetTopPoint(); pMulti = g_Cfg.GetMultiItemDefs(pItem); if (pMulti == NULL) continue; size_t iQty = pMulti->GetItemCount(); for (size_t ii = 0; ii < iQty; pMultiItem = NULL, ii++) { pMultiItem = pMulti->GetItem(ii); if (pMultiItem == NULL) break; if (pMultiItem->m_visible == 0) continue; CPointMap ptTest(static_cast<WORD>(ptMulti.m_x + pMultiItem->m_dx), static_cast<WORD>(ptMulti.m_y + pMultiItem->m_dy), static_cast<signed char>(ptMulti.m_z + pMultiItem->m_dz), this->m_map); if (GetDist(ptTest) > 0) continue; if (iComponent == 0) break; iComponent--; } if (pMultiItem != NULL) break; } } if ( pMultiItem == NULL ) { sVal.FormatHex(0); return true; } SKIP_SEPARATORS( pszKey ); if ( !*pszKey ) pszKey = "ID"; ITEMID_TYPE idTile = pMultiItem->GetDispID(); if ( strnicmp( pszKey, "ID", 2 ) == 0 ) { sVal.FormatHex( idTile ); return true; } else if ( strnicmp( pszKey, "MULTI", 5 ) == 0 ) { pszKey += 5; if (*pszKey != '\0') { SKIP_SEPARATORS(pszKey); return pItem->r_WriteVal( pszKey, sVal, &g_Serv ); } sVal.FormatHex( pItem->GetUID() ); return true; } else if ( strnicmp( pszKey, "Z", 1 ) == 0 ) { sVal.FormatVal( pItem->GetTopZ() + pMultiItem->m_dz ); return true; } // Check the script def for the item. CItemBase * pItemDef = CItemBase::FindItemBase( idTile ); if ( pItemDef == NULL ) { DEBUG_ERR(("Must have ITEMDEF section for item ID 0%x\n", idTile )); return false; } return pItemDef->r_WriteVal( pszKey, sVal, &g_Serv ); } int index = FindTableHeadSorted( pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys)-1 ); if ( index < 0 ) return false; switch ( index ) { case PT_M: case PT_MAP: sVal.FormatVal(m_map); break; case PT_X: sVal.FormatVal(m_x); break; case PT_Y: sVal.FormatVal(m_y); break; case PT_Z: sVal.FormatVal(m_z); break; case PT_ISNEARTYPE: { pszKey += 10; SKIP_SEPARATORS( pszKey ); SKIP_ARGSEP( pszKey ); int iType = g_Cfg.ResourceGetIndexType( RES_TYPEDEF, pszKey ); int iDistance = 0; bool bCheckMulti = false; SKIP_IDENTIFIERSTRING( pszKey ); SKIP_SEPARATORS( pszKey ); SKIP_ARGSEP( pszKey ); if ( *pszKey ) iDistance = Exp_GetVal(pszKey); if ( *pszKey ) bCheckMulti = Exp_GetVal(pszKey) != 0; sVal.FormatVal( g_World.IsItemTypeNear(*this, static_cast<IT_TYPE>(iType), iDistance, bCheckMulti)); break; } case PT_REGION: { // Check that the syntax is correct. if ( pszKey[6] && pszKey[6] != '.' ) return false; CRegionWorld * pRegionTemp = dynamic_cast <CRegionWorld*>(this->GetRegion(REGION_TYPE_AREA | REGION_TYPE_MULTI)); if ( !pszKey[6] ) { // We're just checking if the reference is valid. sVal.FormatVal( pRegionTemp? 1:0 ); return true; } // We're trying to retrieve a property from the region. pszKey += 7; if ( pRegionTemp ) return pRegionTemp->r_WriteVal( pszKey, sVal, &g_Serv ); return false; } case PT_ROOM: { if ( pszKey[4] && pszKey[4] != '.' ) return false; CRegionBase * pRegionTemp = this->GetRegion( REGION_TYPE_ROOM ); if ( !pszKey[4] ) { sVal.FormatVal( pRegionTemp? 1:0 ); return true; } pszKey += 5; if ( pRegionTemp ) return pRegionTemp->r_WriteVal( pszKey, sVal, &g_Serv ); return false; } case PT_SECTOR: { if ( pszKey[6] == '.' ) { pszKey += 7; CSector * pSectorTemp = this->GetSector(); if (pSectorTemp) return pSectorTemp->r_WriteVal(pszKey, sVal, &g_Serv); } return false; } default: { const CUOMapMeter * pMeter = g_World.GetMapMeter(*this); if ( pMeter ) { switch( index ) { case PT_TYPE: { CItemTypeDef * pTypeDef = g_World.GetTerrainItemTypeDef( pMeter->m_wTerrainIndex ); if ( pTypeDef != NULL ) sVal = pTypeDef->GetResourceName(); else sVal = ""; } return true; case PT_TERRAIN: { pszKey += strlen(sm_szLoadKeys[index]); if ( *pszKey == '.' ) // do we have an argument? { SKIP_SEPARATORS( pszKey ); if ( !strnicmp( pszKey, "Z", 1 )) { sVal.FormatVal( pMeter->m_z ); return( true ); } return( false ); } else { sVal.FormatHex( pMeter->m_wTerrainIndex ); } } return true; } } return false; } } return true; }
void CRender::Calculate () { #ifdef _GPA_ENABLED TAL_SCOPED_TASK_NAMED( "CRender::Calculate()" ); #endif // _GPA_ENABLED Device.Statistic->RenderCALC.Begin(); // Transfer to global space to avoid deep pointer access IRender_Target* T = getTarget (); float fov_factor = _sqr (90.f / Device.fFOV); g_fSCREEN = float(T->get_width()*T->get_height())*fov_factor*(EPS_S+ps_r__LOD); r_ssaDISCARD = _sqr(ps_r__ssaDISCARD) /g_fSCREEN; r_ssaDONTSORT = _sqr(ps_r__ssaDONTSORT/3) /g_fSCREEN; r_ssaLOD_A = _sqr(ps_r1_ssaLOD_A/3) /g_fSCREEN; r_ssaLOD_B = _sqr(ps_r1_ssaLOD_B/3) /g_fSCREEN; r_ssaGLOD_start = _sqr(ps_r__GLOD_ssa_start/3)/g_fSCREEN; r_ssaGLOD_end = _sqr(ps_r__GLOD_ssa_end/3) /g_fSCREEN; r_ssaHZBvsTEX = _sqr(ps_r__ssaHZBvsTEX/3) /g_fSCREEN; // Frustum & HOM rendering ViewBase.CreateFromMatrix (Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); View = 0; HOM.Enable (); HOM.Render (ViewBase); gm_SetNearer (FALSE); phase = PHASE_NORMAL; // Detect camera-sector if (!vLastCameraPos.similar(Device.vCameraPosition,EPS_S)) { CSector* pSector = (CSector*)detectSector(Device.vCameraPosition); if (pSector && (pSector!=pLastSector)) g_pGamePersistent->OnSectorChanged( translateSector(pSector) ); if (0==pSector) pSector = pLastSector; pLastSector = pSector; vLastCameraPos.set(Device.vCameraPosition); } // Check if camera is too near to some portal - if so force DualRender if (rmPortals) { Fvector box_radius; box_radius.set(EPS_L*2,EPS_L*2,EPS_L*2); Sectors_xrc.box_options (CDB::OPT_FULL_TEST); Sectors_xrc.box_query (rmPortals,Device.vCameraPosition,box_radius); for (int K=0; K<Sectors_xrc.r_count(); K++) { CPortal* pPortal = (CPortal*) Portals[rmPortals->get_tris()[Sectors_xrc.r_begin()[K].id].dummy]; pPortal->bDualRender = TRUE; } } // if (L_DB) L_DB->Update(); // Main process marker ++; if (pLastSector) { // Traverse sector/portal structure PortalTraverser.traverse ( pLastSector, ViewBase, Device.vCameraPosition, Device.mFullTransform, CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE ); // Determine visibility for static geometry hierrarhy if (psDeviceFlags.test(rsDrawStatic)) { for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; dxRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } } // Traverse object database if (psDeviceFlags.test(rsDrawDynamic)) { g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE + STYPE_LIGHTSOURCE, ViewBase ); // Exact sorting order (front-to-back) std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); // Determine visibility for dynamic part of scene set_Object (0); g_hud->Render_First ( ); // R1 shadows g_hud->Render_Last ( ); u32 uID_LTRACK = 0xffffffff; if (phase==PHASE_NORMAL) { uLastLTRACK ++; if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); // update light-vis for current entity / actor CObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { CROS_impl* R = (CROS_impl*) O->ROS(); if (R) R->update (O); } } for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; spatial->spatial_updatesector (); CSector* sector = (CSector*)spatial->spatial.sector ; if (0==sector) continue; // disassociated from S/P structure // Filter only not light spatial if (PortalTraverser.i_marker != sector->r_marker && (spatial->spatial.type & STYPE_RENDERABLE) ) continue; // inactive (untouched) sector if (spatial->spatial.type & STYPE_RENDERABLE) { for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); if (!View->testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) /*&& (spatial->spatial.type & STYPE_RENDERABLE)*/) continue; // renderable IRenderable* renderable = spatial->dcast_Renderable (); if (0==renderable) { // It may be an glow CGlow* glow = dynamic_cast<CGlow*>(spatial); VERIFY (glow); L_Glows->add (glow); } else { // Occlusiond vis_data& v_orig = renderable->renderable.visual->getVisData(); vis_data v_copy = v_orig; v_copy.box.xform (renderable->renderable.xform); BOOL bVisible = HOM.visible(v_copy); v_orig.accept_frame = v_copy.accept_frame; v_orig.marker = v_copy.marker; v_orig.hom_frame = v_copy.hom_frame; v_orig.hom_tested = v_copy.hom_tested; if (!bVisible) break; // exit loop on frustums // rendering if (o_it==uID_LTRACK && renderable->renderable_ROS()) { // track lighting environment CROS_impl* T = (CROS_impl*)renderable->renderable_ROS(); T->update (renderable); } set_Object (renderable); renderable->renderable_Render (); set_Object (0); //? is it needed at all } break; // exit loop on frustums } } else { if ( ViewBase.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) ) { VERIFY (spatial->spatial.type & STYPE_LIGHTSOURCE); // lightsource light* L = (light*) spatial->dcast_Light (); VERIFY (L); if (L->spatial.sector) { vis_data& vis = L->get_homdata ( ); if (HOM.visible(vis)) L_DB->add_light (L); } } } } } // Calculate miscelaneous stuff L_Shadows->calculate (); L_Projector->calculate (); } else { set_Object (0); /* g_pGameLevel->pHUD->Render_First (); g_pGameLevel->pHUD->Render_Last (); // Calculate miscelaneous stuff L_Shadows->calculate (); L_Projector->calculate (); */ } // End calc Device.Statistic->RenderCALC.End (); }
void R_dsgraph_structure::r_dsgraph_render_R1_box (IRender_Sector* _S, Fbox& BB, int sh) { CSector* S = (CSector*)_S; lstVisuals.clear (); lstVisuals.push_back (S->root()); for (u32 test=0; test<lstVisuals.size(); test++) { IRender_Visual* V = lstVisuals[test]; // Visual is 100% visible - simply add it xr_vector<IRender_Visual*>::iterator I,E; // it may be usefull for 'hierrarhy' visuals switch (V->Type) { case MT_HIERRARHY: { // Add all children FHierrarhyVisual* pV = (FHierrarhyVisual*)V; I = pV->children.begin (); E = pV->children.end (); for (; I!=E; I++) { IRender_Visual* T = *I; if (BB.intersect(T->vis.box)) lstVisuals.push_back(T); } } break; case MT_SKELETON_ANIM: case MT_SKELETON_RIGID: { // Add all children (s) CKinematics * pV = (CKinematics*)V; pV->CalculateBones (TRUE); I = pV->children.begin (); E = pV->children.end (); for (; I!=E; I++) { IRender_Visual* T = *I; if (BB.intersect(T->vis.box)) lstVisuals.push_back(T); } } break; case MT_LOD: { FLOD * pV = (FLOD*) V; I = pV->children.begin (); E = pV->children.end (); for (; I!=E; I++) { IRender_Visual* T = *I; if (BB.intersect(T->vis.box)) lstVisuals.push_back(T); } } break; default: { // Renderable visual ShaderElement* E = V->shader->E[sh]._get(); if (E) { for (u32 pass=0; pass<E->passes.size(); pass++) { RCache.set_Element (E,pass); V->Render (-1.f); } } } break; } } }
// sub-space rendering - main procedure void R_dsgraph_structure::r_dsgraph_render_subspace (IRender_Sector* _sector, CFrustum* _frustum, Fmatrix& mCombined, Fvector& _cop, BOOL _dynamic, BOOL _precise_portals) { VERIFY (_sector); RImplementation.marker ++; // !!! critical here // Save and build new frustum, disable HOM CFrustum ViewSave = ViewBase; ViewBase = *_frustum; View = &ViewBase; if (_precise_portals && RImplementation.rmPortals) { // Check if camera is too near to some portal - if so force DualRender Fvector box_radius; box_radius.set (EPS_L*20,EPS_L*20,EPS_L*20); RImplementation.Sectors_xrc.box_options (CDB::OPT_FULL_TEST); RImplementation.Sectors_xrc.box_query (RImplementation.rmPortals,_cop,box_radius); for (int K=0; K<RImplementation.Sectors_xrc.r_count(); K++) { CPortal* pPortal = (CPortal*) RImplementation.Portals[RImplementation.rmPortals->get_tris()[RImplementation.Sectors_xrc.r_begin()[K].id].dummy]; pPortal->bDualRender = TRUE; } } // Traverse sector/portal structure PortalTraverser.traverse ( _sector, ViewBase, _cop, mCombined, 0 ); // Determine visibility for static geometry hierrarhy for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; IRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } if (_dynamic) { set_Object (0); // Traverse object database g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE, ViewBase ); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; CSector* sector = (CSector*)spatial->spatial.sector; if (0==sector) continue; // disassociated from S/P structure if (PortalTraverser.i_marker != sector->r_marker) continue; // inactive (untouched) sector for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); if (!View->testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R)) continue; // renderable IRenderable* renderable = spatial->dcast_Renderable (); if (0==renderable) continue; // unknown, but renderable object (r1_glow???) renderable->renderable_Render (); } } } // Restore ViewBase = ViewSave; View = 0; }