//===========================================================================// // File: Map.cpp // // Project: MUNGA Brick: Interest Manager // // Contents: Interface specifications for interest manager // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- -----------------------------------------------------------// // 11/04/94 ECH Initial coding. // // 11/29/94 JMA Changed Identities to IDs // // 02/10/95 CPB Added GaugeInterestType // // 08/25/97 ECH Infrastructure changes. // //---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "AdeptHeaders.hpp" #include "Map.hpp" #include "VideoRenderer.hpp" #include "VideoComponentWeb.hpp" #include "Application.hpp" #include "Zone.hpp" #include #include "GUITextManager.hpp" #include #include #include "CollisionGrid.hpp" #include "Tile.hpp" #include #include #include #include "EntityManager.hpp" //#define HIERARCHY "your_loginname_here" // used to display attachment info #define HUNT_ADD_EFFECT_BUG //############################################################################# //################################### Map ############################### //############################################################################# Map::ClassData* Map::DefaultData = NULL; int Map::LoadRadius = 1; static bool __stdcall CheckFullZoneLoad() {return Map::LoadRadius==4;} static void __stdcall EnableFullZoneLoad() {Map::LoadRadius = 5-Map::LoadRadius;} DECLARE_TIMER(static, Attaching_To_Map); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::InitializeClass(Stuff::NotationFile *startup_ini) { Verify(!DefaultData); Check_Object(ExecutionStateEngine::DefaultData); DefaultData = new ClassData( MapClassID, "Adept::Map", Entity::DefaultData, 0, NULL, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, NULL, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel ); Check_Object(DefaultData); DIRECT_GAME_MODEL_ATTRIBUTE( Map__GameModel, DamageCraterResource, m_damageCraterResourceID, ResourceID ); Initialize_Timer(Attaching_To_Map, "Attaching To Map"); AddDebuggerMenuItem("Libraries\\Adept\\Load All Zones", CheckFullZoneLoad, EnableFullZoneLoad, 0 ); if (startup_ini) { Check_Object(startup_ini); Stuff::Page *page = startup_ini->FindPage("Graphics Options"); if (page) { Check_Object(page); page->GetEntry("LoadRadius", &LoadRadius); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::TerminateClass(Stuff::NotationFile *startup_ini) { if (startup_ini) { Check_Object(startup_ini); Stuff::Page *page = startup_ini->SetPage("Graphics Options"); Check_Object(page); page->SetEntry("LoadRadius", LoadRadius); } Check_Object(DefaultData); delete DefaultData; DefaultData = NULL; } #if 0 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Map* Map::Make( const CreateMessage *message, ReplicatorID *base_id ) { Check_Object(message); // //----------------------------------------------------------------------- // We need to open up the game model specified by the message in order to // find the ResourceID of our grid element //----------------------------------------------------------------------- // Resource model_resource; GetGameModelResourceFromDataListID(&model_resource, message->dataListID); GameModel *model = Cast_Pointer(GameModel*, model_resource.GetPointer()); Check_Object(model); Resource grid_resource(model->m_gridElementResourceID); Check_Object(&grid_resource); Verify(grid_resource.DoesResourceExist()); ElementRenderer::GridElement *grid = Cast_Object( ElementRenderer::GridElement*, ElementRenderer::Element::Create( &grid_resource, ElementRenderer::ReadERFVersion(&grid_resource) ) ); Map *new_entity = new Map(DefaultData, message, base_id, grid); Check_Object(new_entity); return new_entity; } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Replicator::CreateMessage* Map::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file) { Check_Object(this); Check_Object(stream); // //--------------------------------------------------------------------- // Make sure there is enough room for the factory request on the stream //--------------------------------------------------------------------- // stream->AllocateBytes(sizeof(CreateMessage)); Entity::SaveMakeMessage(stream, res_file); CreateMessage *message = Cast_Pointer(CreateMessage*, stream->GetPointer()); message->messageLength = sizeof(*message); // //---------------------------------------- // Create the memory stream for the props //---------------------------------------- // DynamicMemoryStream prop_stream(sizeof(WORD)); ReplicatorID span = ReplicatorID::Null; prop_stream << span.localID; // //-------------------------------------------------------------------- // Tell each prop to save itself and bump the stream pointer afterword //-------------------------------------------------------------------- // ChainIteratorOf iterator(&childEntityChain); Entity *entity; while ((entity = iterator.ReadAndNext()) != NULL) { Check_Object(entity); if (entity->GetPropType() == MapPropType) { Replicator::CreateMessage *create_message = entity->SaveMakeMessage(&prop_stream, NULL); if (create_message) { Check_Object(create_message); prop_stream.AdvancePointer(create_message->messageLength); span += create_message->replicatorID.localID; } } } // //----------------------------------------- // Only save out the stream if there is one //----------------------------------------- // if (prop_stream.GetBytesUsed() > sizeof(WORD)) { prop_stream.Rewind(); Verify(span.localID > 0); prop_stream << span.localID; Resource prop_resource(NULL); prop_resource.Save(&prop_stream, NULL); STOP(("Not updated")); Check_Object(&prop_resource); message->m_propStreamResourceID = prop_resource.GetResourceID(); message->replicatorID += span; } else message->m_propStreamResourceID = ResourceID::Null; return message; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Map::Map( ClassData *class_data, const CreateMessage *message, ReplicatorID *base_id, ElementRenderer::GridElement *element, int execution_slots ): Entity(class_data, message, base_id, element), m_executingZones(NULL), m_renderedZones(NULL), m_renderOrigin(NULL), m_executionSlots(execution_slots) { Check_Pointer(this); Check_Object(message); // //--------------------------------------------------------------------- // We will get our size directly from the .erf file that has the grid // element in it. In the mean time, set up the structures for one zone //--------------------------------------------------------------------- // ElementRenderer::GridElement *grid = Cast_Object(ElementRenderer::GridElement*, entityElement); grid->GetSize(&m_rowZoneCount, &m_columnZoneCount); m_zoneCount = static_cast(m_columnZoneCount * m_rowZoneCount); grid->SetSize(m_zoneCount); Scalar row_size, column_size; grid->GetDimensions( &m_rowZoneOrigin, &m_columnZoneOrigin, &row_size, &column_size ); Verify(!Small_Enough(row_size)); m_rowZoneScale = 1.0f / row_size; Verify(!Small_Enough(column_size)); m_columnZoneScale = 1.0f / column_size; Verify(Close_Enough(m_columnZoneScale, m_rowZoneScale)); // //-------------------------------------------------- // Set up the game model and set up the list of erfs //-------------------------------------------------- // const GameModel *model = GetGameModel(); Check_Object(model); m_zonesResource.FindID(model->m_zoneArrayResourceID); Verify(m_zonesResource.DoesResourceExist()); Verify(m_zoneCount*sizeof(Zone::ResourceData) == m_zonesResource.GetSize()); // //--------------------- // Create the supergrid //--------------------- // Verify(!CollisionGrid::Instance); gos_PushCurrentHeap(s_CollisionHeap); CollisionGrid::Instance = new CollisionGrid( static_cast(m_rowZoneCount*e_TilesPerZone), static_cast(m_columnZoneCount*e_TilesPerZone), m_rowZoneOrigin, m_columnZoneOrigin, row_size * m_rowZoneCount, column_size * m_columnZoneCount, model->m_waterLevel ); Check_Object(CollisionGrid::Instance); gos_PopCurrentHeap(); // //------------------------------------ // Build the Texture logistics manager //------------------------------------ // bool manage_textures = model->m_textureDataResourceID != ResourceID::Null; bool dedicated_server = Application::GetInstance()->m_localMissionParameters->m_runDedicated!=0 ? true : false; if (manage_textures && Compost::TerrainTextureLogistic::GetResolution()>0 && !dedicated_server) { gos_PushCurrentHeap(Compost::Heap); Compost::TexturePool::Instance = new Compost::TexturePool; Check_Object(Compost::TexturePool::Instance); // //----------------------------------------------------------- // Set up the texture path until texture data stream is coded //----------------------------------------------------------- // char name[1024]; gos_GetCurrentPath(name, 1024); Compost::TexturePool::Instance->SetTexturePath("Content\\Textures\\CompostTexture"); Verify(model->m_tcfResourceID!=ResourceID::Null); Resource tcf_resource(model->m_tcfResourceID); NotationFile tcf_data(&tcf_resource); Compost::TexturePool::Instance->LoadIndex(&tcf_data); Resource texture_spec(model->m_textureDataResourceID); Verify(texture_spec.DoesResourceExist()); Compost::TerrainTextureLogistic::Instance = new Compost::TerrainTextureLogistic( m_columnZoneCount*e_TilesPerZone, m_rowZoneCount*e_TilesPerZone, c_TileSize, c_TileSize, &texture_spec ); Check_Object(Compost::TerrainTextureLogistic::Instance); Compost::TerrainTextureLogistic::Instance->SetOffset( m_rowZoneOrigin, m_columnZoneOrigin ); gos_PopCurrentHeap(); } // //---------------------------- // Allocate the array of Zones //---------------------------- // Verify(m_zoneCount > 0 && m_zoneCount == m_columnZoneCount * m_rowZoneCount); m_zones = new Zone[m_zoneCount]; Check_Pointer(m_zones); Zone *zone=m_zones; WORD index=0; for (BYTE row=0; rowm_row = row; zone->m_column = column; zone->LockBounds(); zone->CreateTileGrid( m_rowZoneOrigin + row*c_ZoneSize, m_columnZoneOrigin + column*c_ZoneSize ); grid->AttachIndexedChild(row, column, zone); } } // //----------------- // Create the props //----------------- // propListResourceID = ResourceID::Null; if (message->m_propStreamResourceID != ResourceID::Null) { Resource stream(message->m_propStreamResourceID); Verify(stream.DoesResourceExist()); stream.AdvancePointer(replicatorID.localID); while (stream.GetBytesRemaining() > 0) { Entity::CreateMessage *message = Cast_Pointer(Entity::CreateMessage*, stream.GetPointer()); Check_Object(message); Entity *entity = CreateEntity(&stream, base_id); Check_Object(entity); entity->SetPropType(MapPropType); AddChild(entity); stream.AdvancePointer(message->messageLength); } propListResourceID = message->m_propStreamResourceID; } // //------------------------ // Build the cultural data //------------------------ // bool manage_culturals = model->m_culturalDataResourceID != ResourceID::Null; if (manage_culturals) // switch to turn off cuturals { Resource culturalData_resource(model->m_culturalDataResourceID); int mlr_version = MidLevelRenderer::ReadMLRVersion(&culturalData_resource); OBB obb; culturalData_resource >> obb; if(mlr_version>13) { RegisteredClass::ClassID class_id; culturalData_resource >> class_id; } MidLevelRenderer::MLRCulturShape::culturalRevolution = MidLevelRenderer::MLRShape::Make(&culturalData_resource, mlr_version); } else { if(MidLevelRenderer::MLRCulturShape::culturalRevolution!=NULL) { MidLevelRenderer::MLRCulturShape::culturalRevolution->DetachReference(); MidLevelRenderer::MLRCulturShape::culturalRevolution = NULL; } } // //------------------------ //Set up the footstep pool //------------------------ // Verify(!MidLevelRenderer::MLRFootStep::Instance); MidLevelRenderer::MLRFootStep::Instance = new MidLevelRenderer::MLRFootStep(64); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Map::~Map() { Check_Object(this); GlobalPointers::ClearPointer(MapGlobalPointerIndex); // //---------------------------------------------- // Tell all the children to become uninteresting //---------------------------------------------- // ChainIteratorOf children(&childEntityChain); Entity *entity; while ((entity = children.ReadAndNext()) != NULL) { Check_Object(entity); entity->BecomeUninteresting(); } // //--------------------------------------------- // Turn off the terrain compositing controllers //--------------------------------------------- // if (Compost::TerrainTextureLogistic::Instance) { Check_Object(Compost::TerrainTextureLogistic::Instance); delete Compost::TerrainTextureLogistic::Instance; Compost::TerrainTextureLogistic::Instance = NULL; } if (Compost::TexturePool::Instance) { Check_Object(Compost::TexturePool::Instance); delete Compost::TexturePool::Instance; Compost::TexturePool::Instance = NULL; } // //----------------- // Delete our zones //----------------- // Check_Pointer(m_zones); delete[] m_zones; // //------------------------------------------------------------------- // Delete our collision grid - our parent class will take care of our // child entities //------------------------------------------------------------------- // Check_Object(CollisionGrid::Instance); delete CollisionGrid::Instance; CollisionGrid::Instance = NULL; // //---------------------- //Kill the FootStep pool //---------------------- // if (MidLevelRenderer::MLRFootStep::Instance) { delete MidLevelRenderer::MLRFootStep::Instance; MidLevelRenderer::MLRFootStep::Instance = NULL; } // //------------------------ //Kill the cultural meshes //------------------------ // if(MidLevelRenderer::MLRCulturShape::culturalRevolution!=NULL) { MidLevelRenderer::MLRCulturShape::culturalRevolution->DetachReference(); MidLevelRenderer::MLRCulturShape::culturalRevolution = NULL; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::AddChild(Entity *entity) { Check_Object(this); Check_Object(entity); // //------------------------------------------ // Find the zone that this entity belongs to //------------------------------------------ // Start_Timer(Attaching_To_Map); ElementRenderer::Element *child_element = entity->GetElement(); Check_Object(child_element); #ifdef HUNT_ADD_EFFECT_BUG if (entity == NULL) { STOP(("ADDING OBJECT FAILED : ENTITY NULL")); } if (child_element == NULL) { STOP(("ADDING OBJECT FAILED : CHILD ELEMENT NULL")); } #endif Point3D translation(child_element->GetNewLocalToParent()); int index = FindZone(translation); Verify(static_cast(index) < m_zoneCount); Zone *zone = &m_zones[index]; Check_Object(zone); #ifdef HUNT_ADD_EFFECT_BUG if (zone == NULL) { STOP(("ADDING OBJECT FAILED : location : %f %f %f Zone : %d", translation.x, translation.y, translation.z, index)); } if (static_cast(index) >= m_zoneCount) { STOP(("ADDING OBJECT FAILED : location : %f %f %f Zone : %d", translation.x, translation.y, translation.z, index)); } #endif // //----------------------------- // Hook up the entity hierarchy //----------------------------- // Verify(!entity->parentEntity); entity->parentEntity = this; childEntityChain.Add(entity); entity->NeedMatrixSync(); #if defined(HIERARCHY) SPEW((0, "Attaching %s(+", entity->GetClassString())); Spew(0, entity->GetReplicatorID()); SPEW((0, ") to %s(+", GetClassString())); Spew(0, GetReplicatorID()); SPEW((0, ")")); #endif zone->AttachChild(child_element); Stop_Timer(Attaching_To_Map); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::RemoveChild(Entity *entity) { Check_Object(this); Check_Object(entity); // //-------------------------------- // Unhook the entity from the zone //-------------------------------- // ElementRenderer::Element *element = entity->GetElement(); Check_Object(element); ElementRenderer::Element *parent_ele=element->GetParentElement(); Check_Object(parent_ele); Zone *zone; if(parent_ele->GetClassID() == TileClassID) { Verify(parent_ele->IsDerivedFrom(Tile::DefaultData)); zone = Cast_Object(Zone*, parent_ele->GetParentElement()->GetParentElement()); } else { zone = Cast_Object(Zone*, parent_ele); } zone->DetachChild(element); // //--------------------------------- // Unook the entity from the parent //--------------------------------- // entity->parentEntity = NULL; childEntityChain.Remove(entity); entity->NeedMatrixSync(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::ChildPreCollisionChanged(Entity *entity) { Check_Object(this); Check_Object(entity); // //----------------------------- // Find the zone for the entity //----------------------------- // ElementRenderer::Element *element = entity->GetElement(); Check_Object(element); ElementRenderer::Element *parent_ele=element->GetParentElement(); Check_Object(parent_ele); Zone *zone; if(parent_ele->GetClassID() == TileClassID) { Verify(parent_ele->IsDerivedFrom(Tile::DefaultData)); zone = Cast_Object(Zone*, parent_ele->GetParentElement()->GetParentElement()); } else { zone = Cast_Object(Zone*, parent_ele); } // //------------------- // Turn the entity on //------------------- // if((entity->executionState->GetOldState() == ExecutionStateEngine::NeverExecuteState) &&(entity->executionState->GetState() != ExecutionStateEngine::NeverExecuteState)) { zone->AddExecutor(entity); } // //-------------------- // Turn off the entity //-------------------- // else if((entity->executionState->GetOldState() != ExecutionStateEngine::NeverExecuteState) &&(entity->executionState->GetState() == ExecutionStateEngine::NeverExecuteState)) { zone->RemoveExecutor(entity); } } #if defined(NDEBUG) #pragma optimize("a",off) #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::UpdateZone(Entity *entity) { Check_Object(this); Check_Object(entity); Verify(entity->parentEntity == this); Verify(this == Map::GetInstance()); Verify(!entity->IsTileBound()); // //------------------------------------------ // Find out where the child wants to move to //------------------------------------------ // ElementRenderer::Element *child_element = entity->GetElement(); Check_Object(child_element); Zone *old_zone = Cast_Object(Zone*, child_element->GetParentElement()); Point3D translation(entity->GetLocalToWorld()); // //------------------ // Find the new zone //------------------ // Scalar column = translation.x - m_columnZoneOrigin; Scalar row = translation.z - m_rowZoneOrigin; column *= m_columnZoneScale; row *= m_rowZoneScale; Verify(column>=0.0f && column=0.0f && row(index) < m_zoneCount); Zone *new_zone = &m_zones[index]; Check_Object(new_zone); if (old_zone != new_zone || entity->GetCollisionMask() == EditorIsMovingFlag) { AbstractEvent *event = entity->m_pendingInterestMessage.GetCurrent(); if (event) event->Process(); InterestLevel level = entity->GetInterestLevel(); unsigned element_state = child_element->GetElementState(); old_zone->DetachChild(child_element); new_zone->AttachChild(child_element); if (level == entity->GetInterestLevel()) child_element->SetElementState(element_state); } // //------------------------------ // Clear the entity's dirty flag //------------------------------ // entity->replicatorFlags &= ~DirtyZoneFlag; } #if defined(NDEBUG) #pragma optimize("a",on) #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Map::FindZone(const Stuff::Point3D &where) { Check_Object(this); Verify( Close_Enough( GetElement()->GetLocalToWorld(), LinearMatrix4D::Identity ) ); Verify( Close_Enough( GetElement()->GetNewLocalToParent(), LinearMatrix4D::Identity ) ); unsigned index = GetElement()->FindElementIndex(where.z, where.x); if (index < GetElement()->GetActiveCount()) return index; return -1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::GetMapExtents( Stuff::Scalar *min_z, Stuff::Scalar *max_z, Stuff::Scalar *min_x, Stuff::Scalar *max_x ) { Check_Object(this); Check_Pointer(min_z); Check_Pointer(max_z); Check_Pointer(min_x); Check_Pointer(max_x); *min_x = m_columnZoneOrigin; *max_x = m_columnZoneOrigin + m_columnZoneCount/m_columnZoneScale; *min_z = m_rowZoneOrigin; *max_z = m_rowZoneOrigin + m_rowZoneCount/m_rowZoneScale; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::PreCollisionExecute(Time till) { Check_Object(this); PRECOLLISION_LOGIC("Map"); // //--------------------------------- // Verify that this always executes //--------------------------------- // Check_Object(executionState); Verify( executionState->GetState() != ExecutionStateEngine::NeverExecuteState ); Entity::PreCollisionExecute(till); // //------------------------------- // Clear out the execution hashes //------------------------------- // int i; for (i=0; i zones(&m_executingZones); Zone *zone; while ((zone = zones.ReadAndNext()) != NULL) { Check_Object(zone); Verify(zone->GetInterestLevel() != DormantInterestLevel); zone->PreCollisionExecute(till); } // //------------------------- // Now execute the entities //------------------------- // for (i=0; iPreCollisionExecute(till); Verify(!entity->IsUsingPostCollision() || EntityManager::GetInstance()->IsInPostCollisionExecution(entity)); entity = entity->nextPreExecution; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::SyncMatrices(bool update_matrix) { Check_Object(this); SYNC_LOGIC("Map"); #if defined(HIERARCHY) if (update_matrix) { SPEW((HIERARCHY, "Map::SyncMatrices %s(+", GetClassString())); Spew(HIERARCHY, GetReplicatorID()); SPEW((HIERARCHY, ")")); } #endif // //----------------------------------------- // If we have a dirty locator, sync with it //----------------------------------------- // if (IsMatrixDirty()) { if (update_matrix) { Check_Object(entityElement); entityElement->Sync(); update_matrix = false; } ClearNeedMatrixSync(); } // //------------------------- // Sync the executing zones //------------------------- // ChainIteratorOf zones(&m_executingZones); Zone *zone; while ((zone = zones.ReadAndNext()) != NULL) { Check_Object(zone); Verify(zone->GetInterestLevel() != DormantInterestLevel); zone->SyncMatrices(update_matrix); } #if defined(HIERARCHY) if (update_matrix) SPEW((0, "")); #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::UpdateRenderOrigin(const Stuff::Point3D &location) { Check_Object(this); Check_Object(&location); // //------------------------------------------------------------------ // Find the zone that this entity belongs to, and if the zone hasn't // changed, we are done //------------------------------------------------------------------ // int index = FindZone(location); Verify(static_cast(index) < m_zoneCount); Zone *new_zone = &m_zones[index]; Check_Object(new_zone); if (new_zone == m_renderOrigin) return; // //-------------------------------------------- // Find the bounds on where the render will be //-------------------------------------------- // unsigned row = index / m_columnZoneCount; unsigned column = index - row*m_columnZoneCount; unsigned min_column = (column>=LoadRadius) ? column-LoadRadius : 0; unsigned min_row = (row>=LoadRadius) ? row-LoadRadius : 0; unsigned max_column = (column+LoadRadius >= m_columnZoneCount) ? m_columnZoneCount : column+LoadRadius+1; unsigned max_row = (row+LoadRadius >= m_rowZoneCount) ? m_rowZoneCount : row+LoadRadius+1; // //---------------------------------------------------------- // Make any active zone not in the active zone uninteresting //---------------------------------------------------------- // ChainIteratorOf zones(&m_renderedZones); Zone *zone; while ((zone = zones.ReadAndNext()) != NULL) { Check_Object(zone); if ( zone->m_row < min_row || zone->m_row >= max_row || zone->m_column < min_column || zone->m_column >= max_column ) zone->DisableRendering(); } // //------------------------------------- // Tell each zone to become interesting //------------------------------------- // m_renderOrigin = new_zone; for (row=min_row; rowGetInterestLevel() != RenderingInterestLevel) zone->EnableRendering(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Map::ActivateZones() { Check_Object(this); // //------------------------------------- // Tell each zone to become interesting //------------------------------------- // for (int row=0; rowm_rowZoneScale }