diff options
Diffstat (limited to 'src/modelinfo/SimpleModelInfo.cpp')
-rw-r--r-- | src/modelinfo/SimpleModelInfo.cpp | 212 |
1 files changed, 187 insertions, 25 deletions
diff --git a/src/modelinfo/SimpleModelInfo.cpp b/src/modelinfo/SimpleModelInfo.cpp index 9ca4d292..1199c200 100644 --- a/src/modelinfo/SimpleModelInfo.cpp +++ b/src/modelinfo/SimpleModelInfo.cpp @@ -1,38 +1,60 @@ #include "common.h" +#include "main.h" #include "General.h" +#include "Renderer.h" #include "Camera.h" #include "ModelInfo.h" #include "AnimManager.h" #include "custompipes.h" +#include "Streaming.h" +#include "smallHeap.h" +#include "Leeds.h" -#define LOD_DISTANCE (300.0f) +TempIdeData m_sTempIdeData[800]; + +base::cRelocatableChunkClassInfo CSimpleModelInfo::msClassInfo("CSimpleModelInfo", VTABLE_ADDR(&msClassInstance), sizeof(msClassInstance)); +CSimpleModelInfo CSimpleModelInfo::msClassInstance; void CSimpleModelInfo::DeleteRwObject(void) { int i; RwFrame *f; - for(i = 0; i < m_numAtomics; i++) - if(m_atomics[i]){ - f = RpAtomicGetFrame(m_atomics[i]); - RpAtomicDestroy(m_atomics[i]); - RwFrameDestroy(f); - m_atomics[i] = nil; - RemoveTexDictionaryRef(); - if(GetAnimFileIndex() != -1) - CAnimManager::RemoveAnimBlockRef(GetAnimFileIndex()); - } + if(m_atomics == nil) + return; + if(!gUseChunkFiles){ + for(i = 0; i < m_numAtomics; i++) + if(m_atomics[i]){ + f = RpAtomicGetFrame(m_atomics[i]); + RpAtomicDestroy(m_atomics[i]); + RwFrameDestroy(f); + m_atomics[i] = nil; + RemoveTexDictionaryRef(); + if(GetAnimFileIndex() != -1) + CAnimManager::RemoveAnimBlockRef(GetAnimFileIndex()); + } + }else if(m_chunk){ + CStreaming::UnregisterPointer(&m_atomics, 2); + for(i = 0; i < m_numAtomics; i++) + CStreaming::UnregisterAtomic(m_atomics[i], nil); + DeleteChunk(); + RemoveTexDictionaryRef(); + if(GetAnimFileIndex() != -1) + CAnimManager::RemoveAnimBlockRef(GetAnimFileIndex()); + } + m_atomics = nil; } RwObject* CSimpleModelInfo::CreateInstance(void) { RpAtomic *atomic; - if(m_atomics[0] == nil) + if(m_atomics && m_atomics[0] == nil) return nil; atomic = RpAtomicClone(m_atomics[0]); RpAtomicSetFrame(atomic, RwFrameCreate()); + CStreaming::RegisterInstance(atomic, nil); return (RwObject*)atomic; } @@ -42,21 +64,20 @@ CSimpleModelInfo::CreateInstance(RwMatrix *matrix) RpAtomic *atomic; RwFrame *frame; - if(m_atomics[0] == nil) + if(m_atomics && m_atomics[0] == nil) return nil; atomic = RpAtomicClone(m_atomics[0]); frame = RwFrameCreate(); *RwFrameGetMatrix(frame) = *matrix; RpAtomicSetFrame(atomic, frame); + CStreaming::RegisterInstance(atomic, nil); return (RwObject*)atomic; } void CSimpleModelInfo::Init(void) { - m_atomics[0] = nil; - m_atomics[1] = nil; - m_atomics[2] = nil; + m_atomics = new RpAtomic*[3]; m_numAtomics = 0; m_firstDamaged = 0; m_wetRoadReflection = 0; @@ -72,21 +93,30 @@ CSimpleModelInfo::Init(void) m_ignoreDrawDist = 0; m_isCodeGlass = 0; m_isArtistGlass = 0; + m_relatedModel = nil; } void CSimpleModelInfo::SetAtomic(int n, RpAtomic *atomic) { - AddTexDictionaryRef(); + if(m_atomics == nil){ + m_atomics = new RpAtomic*[3]; + m_atomics[0] = nil; + m_atomics[1] = nil; + m_atomics[2] = nil; + } m_atomics[n] = atomic; + AddTexDictionaryRef(); if(GetAnimFileIndex() != -1) CAnimManager::AddAnimBlockRef(GetAnimFileIndex()); RpGeometry *geo = RpAtomicGetGeometry(atomic); if(m_ignoreLight) RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) & ~rpGEOMETRYLIGHT); +/* if(RpGeometryGetFlags(geo) & rpGEOMETRYNORMALS && RpGeometryGetNumTriangles(geo) > 200) debug("%s has %d polys\n", m_name, RpGeometryGetNumTriangles(geo)); +*/ #ifdef EXTENDED_PIPELINES if(m_wetRoadReflection) @@ -137,6 +167,40 @@ CSimpleModelInfo::GetLargestLodDistance(void) } RpAtomic* +CSimpleModelInfo::GetLodAtomic(int n) +{ + if(m_atomics == nil || n >= m_numAtomics) + return nil; + return m_atomics[n]; +} + +RpAtomic* +CSimpleModelInfo::GetLastAtomic(void) +{ + if(m_atomics == nil) + return nil; + if(m_firstDamaged == 0 || m_isDamaged) + return m_atomics[m_numAtomics-1]; + else + return m_atomics[m_firstDamaged-1]; +} + +RpAtomic* +CSimpleModelInfo::GetLastAtomic(float dist) +{ + int n; + if(m_atomics == nil) + return nil; + if(m_firstDamaged == 0 || m_isDamaged) + n = m_numAtomics-1; + else + n = m_firstDamaged-1; + if(dist < m_lodDistances[n] * TheCamera.LODDistMultiplier) + return m_atomics[n]; + return nil; +} + +RpAtomic* CSimpleModelInfo::GetAtomicFromDistance(float dist) { int i; @@ -152,20 +216,40 @@ CSimpleModelInfo::GetAtomicFromDistance(float dist) RpAtomic* CSimpleModelInfo::GetFirstAtomicFromDistance(float dist) { +// HACk until we figure out what's going on +if(m_atomics == nil) return nil; if(dist < m_lodDistances[0] * TheCamera.LODDistMultiplier) return m_atomics[0]; return nil; } void -CSimpleModelInfo::FindRelatedModel(int32 minID, int32 maxID) +CSimpleModelInfo::FindRelatedModel(void) { - int i; CBaseModelInfo *mi; - for(i = minID; i <= maxID; i++){ - mi = CModelInfo::GetModelInfo(i); + int thisIndex, otherIndex; + + // find our own index in temp data + for(thisIndex = 0; thisIndex < ARRAY_SIZE(m_sTempIdeData); thisIndex++){ + if(m_sTempIdeData[thisIndex].id == -1) + break; + if(this == CModelInfo::GetModelInfo(m_sTempIdeData[thisIndex].id)) + goto found; + } + thisIndex = -1; +found: +#ifdef FIX_BUGS + if(thisIndex == -1) + return; +#endif + + for(otherIndex = 0; otherIndex < ARRAY_SIZE(m_sTempIdeData); otherIndex++){ + if(m_sTempIdeData[otherIndex].id == -1) + break; + + mi = CModelInfo::GetModelInfo(m_sTempIdeData[otherIndex].id); if(mi && mi != this && - !CGeneral::faststrcmp(GetModelName()+3, mi->GetModelName()+3)){ + !CGeneral::faststrcmp(m_sTempIdeData[thisIndex].name+3, m_sTempIdeData[otherIndex].name+3)){ assert(mi->IsSimple()); this->SetRelatedModel((CSimpleModelInfo*)mi); return; @@ -176,12 +260,14 @@ CSimpleModelInfo::FindRelatedModel(int32 minID, int32 maxID) #define NEAR_DRAW_DIST 100.0f // 0.0f in vice city void -CSimpleModelInfo::SetupBigBuilding(int32 minID, int32 maxID) +CSimpleModelInfo::SetupBigBuilding(void) { CSimpleModelInfo *related; - if(m_lodDistances[0] > LOD_DISTANCE && GetRelatedModel() == nil){ + if(m_lodDistances[0] < 0.0f) + m_lodDistances[0] = -m_lodDistances[0]; // what? + else if(m_lodDistances[0] > LOD_DISTANCE && GetRelatedModel() == nil){ m_isBigBuilding = 1; - FindRelatedModel(minID, maxID); + FindRelatedModel(); related = GetRelatedModel(); if(related){ m_lodDistances[2] = related->GetLargestLodDistance()/TheCamera.LODDistMultiplier; @@ -193,3 +279,79 @@ CSimpleModelInfo::SetupBigBuilding(int32 minID, int32 maxID) m_lodDistances[2] = NEAR_DRAW_DIST; } } + + +void +CSimpleModelInfo::LoadModel(void *atomics, const void *chunk) +{ + int i; + m_chunk = (void*)chunk; + m_atomics = (RpAtomic**)atomics; + CStreaming::RegisterPointer(m_chunk, 2, true); + CStreaming::RegisterPointer(m_atomics, 2, true); + for(i = 0; i < m_numAtomics; i++){ + LoadResource(m_atomics[i]); + CStreaming::RegisterAtomic(m_atomics[i], nil); + } +} + +void +CSimpleModelInfo::Write(base::cRelocatableChunkWriter &writer) +{ + CBaseModelInfo::Write(writer); + if(WriteModel(writer)) + writer.AddPatch(&m_atomics); + else + m_atomics = nil; + if(m_isBigBuilding) + writer.AddPatch(&m_relatedModel); +} + +void* +CSimpleModelInfo::WriteModel(base::cRelocatableChunkWriter &writer) +{ + int i; + if(m_atomics == nil || m_atomics[0] == nil) + return nil; + + // remove empty atomics + int numAtomics = 0; + for(i = 0; i < m_numAtomics; i++) + if(m_atomics[i]){ + m_atomics[numAtomics] = m_atomics[i]; +#ifdef FIX_BUGS + m_lodDistances[numAtomics] = m_lodDistances[i]; +#endif + numAtomics++; + } + if(m_firstDamaged){ + int firstDam = m_firstDamaged - m_numAtomics + numAtomics; + if(firstDam < numAtomics) + m_firstDamaged = firstDam; + else + m_firstDamaged = 0; + } + m_numAtomics = numAtomics; + + // write the actual models + writer.AllocateRaw(m_atomics, m_numAtomics*sizeof(void*), sizeof(void*), false, true); + for(i = 0; m_numAtomics; i++){ + writer.AddPatch(&m_atomics[i]); + SaveResource(m_atomics[i], writer); + } + return m_atomics; +} + +void +CSimpleModelInfo::RcWriteThis(base::cRelocatableChunkWriter &writer) +{ + writer.AllocateRaw(this, sizeof(*this), 0x10, false, true); + writer.Class(VTABLE_ADDR(this), msClassInfo); +} + +void +CSimpleModelInfo::RcWriteEmpty(base::cRelocatableChunkWriter &writer) +{ + writer.AllocateRaw(this, sizeof(*this), 0x10, false, true); + writer.Class(VTABLE_ADDR(this), msClassInfo); +} |