From e6ef2f12dea9139c4fb303992c2d8f906e302a49 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 5 Jan 2021 11:12:48 +0100 Subject: first version of new renderer --- src/render/Renderer.cpp | 609 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 601 insertions(+), 8 deletions(-) (limited to 'src/render/Renderer.cpp') diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2559b743..53971f95 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,3 +1,4 @@ +#define WITH_D3D #include "common.h" #include "main.h" @@ -6,6 +7,7 @@ #include "Treadable.h" #include "Ped.h" #include "Vehicle.h" +#include "Boat.h" #include "Heli.h" #include "Object.h" #include "PathFind.h" @@ -68,6 +70,12 @@ int32 CRenderer::ms_nNoOfVisibleEntities; CEntity *CRenderer::ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES]; CEntity *CRenderer::ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES]; int32 CRenderer::ms_nNoOfInVisibleEntities; +#ifdef NEW_RENDERER +int32 CRenderer::ms_nNoOfVisibleVehicles; +CEntity *CRenderer::ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES]; +int32 CRenderer::ms_nNoOfVisibleBuildings; +CEntity *CRenderer::ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES]; +#endif CVector CRenderer::ms_vecCameraPosition; CVehicle *CRenderer::m_pFirstPersonVehicle; @@ -109,6 +117,20 @@ CRenderer::PreRender(void) for(i = 0; i < ms_nNoOfVisibleEntities; i++) ms_aVisibleEntityPtrs[i]->PreRender(); +#ifdef NEW_RENDERER + if(gbNewRenderer){ + for(i = 0; i < ms_nNoOfVisibleVehicles; i++) + ms_aVisibleVehiclePtrs[i]->PreRender(); + // How is this done with cWorldStream? + for(i = 0; i < ms_nNoOfVisibleBuildings; i++) + ms_aVisibleBuildingPtrs[i]->PreRender(); + for(node = CVisibilityPlugins::m_alphaBuildingList.head.next; + node != &CVisibilityPlugins::m_alphaBuildingList.tail; + node = node->next) + ((CEntity*)node->item.entity)->PreRender(); + } +#endif + for (i = 0; i < ms_nNoOfInVisibleEntities; i++) { #ifdef SQUEEZE_PERFORMANCE if (ms_aInVisibleEntityPtrs[i]->IsVehicle() && ((CVehicle*)ms_aInVisibleEntityPtrs[i])->IsHeli()) @@ -241,6 +263,8 @@ CRenderer::RenderFirstPersonVehicle(void) RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); } +inline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable(); } + void CRenderer::RenderRoads(void) { @@ -254,7 +278,7 @@ CRenderer::RenderRoads(void) for(i = 0; i < ms_nNoOfVisibleEntities; i++){ t = (CTreadable*)ms_aVisibleEntityPtrs[i]; - if(t->IsBuilding() && t->GetIsATreadable()){ + if(IsRoad(t)){ #ifndef MASTER if(gbShowCarRoadGroups || gbShowPedRoadGroups){ int ind = 0; @@ -288,7 +312,7 @@ CRenderer::RenderEverythingBarRoads(void) for(i = 0; i < ms_nNoOfVisibleEntities; i++){ e = ms_aVisibleEntityPtrs[i]; - if(e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable()) + if(IsRoad(e)) continue; #ifdef EXTENDED_PIPELINES @@ -349,6 +373,556 @@ CRenderer::RenderBoats(void) } } +#ifdef NEW_RENDERER +#ifndef LIBRW +#error "Need librw for EXTENDED_PIPELINES" +#endif +#include "WaterLevel.h" + +enum { + // blend passes + PASS_NOZ, // no z-write + PASS_ADD, // additive + PASS_BLEND // normal blend +}; + +static RwRGBAReal black; + +static void +SetStencilState(int state) +{ + switch(state){ + // disable stencil + case 0: + rw::SetRenderState(rw::STENCILENABLE, FALSE); + break; + // test against stencil + case 1: + rw::SetRenderState(rw::STENCILENABLE, TRUE); + rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILNOTEQUAL); + rw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFF); + rw::SetRenderState(rw::STENCILFUNCTIONREF, 0xFF); + break; + // write to stencil + case 2: + rw::SetRenderState(rw::STENCILENABLE, TRUE); + rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS); + rw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE); + rw::SetRenderState(rw::STENCILFUNCTIONREF, 0xFF); + break; + } +} + +#ifdef RW_D3D9 +struct BuildingInst +{ + rw::RawMatrix combinedMat; + rw::d3d9::InstanceDataHeader *instHeader; + uint8 fadeAlpha; + bool lighting; +}; +static BuildingInst blendInsts[3][2000]; +static int numBlendInsts[3]; + +static void +SetMatrix(BuildingInst *building, rw::Matrix *worldMat) +{ + using namespace rw; + RawMatrix world, worldview; + Camera *cam = engine->currentCamera; + convMatrix(&world, worldMat); + RawMatrix::mult(&worldview, &world, &cam->devView); + RawMatrix::mult(&building->combinedMat, &worldview, &cam->devProj); +} + +static bool +IsTextureTransparent(RwTexture *tex) +{ + if(tex == nil || tex->raster == nil) + return false; + return PLUGINOFFSET(rw::d3d::D3dRaster, tex->raster, rw::d3d::nativeRasterOffset)->hasAlpha; +} + +// Render all opaque meshes and put atomics that needs blending +// into the deferred list. +static void +AtomicFirstPass(RpAtomic *atomic, int pass) +{ + using namespace rw; + using namespace rw::d3d; + using namespace rw::d3d9; + + BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]]; + + atomic->getPipeline()->instance(atomic); + building->instHeader = (d3d9::InstanceDataHeader*)atomic->geometry->instData; + assert(building->instHeader != nil); + assert(building->instHeader->platform == PLATFORM_D3D9); + building->fadeAlpha = 255; + building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT); + + bool setupDone = false; + bool defer = false; + SetMatrix(building, atomic->getFrame()->getLTM()); + + InstanceData *inst = building->instHeader->inst; + for(rw::uint32 i = 0; i < building->instHeader->numMeshes; i++, inst++){ + Material *m = inst->material; + + if(inst->vertexAlpha || m->color.alpha != 255 || + IsTextureTransparent(m->texture)){ + defer = true; + continue; + } + + // alright we're rendering this atomic + if(!setupDone){ + setStreamSource(0, building->instHeader->vertexStream[0].vertexBuffer, 0, building->instHeader->vertexStream[0].stride); + setIndices(building->instHeader->indexBuffer); + setVertexDeclaration(building->instHeader->vertexDeclaration); + setVertexShader(default_amb_VS); + d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&building->combinedMat, 4); + if(building->lighting) + setAmbient(pAmbient->color); + else + setAmbient(black); + setupDone = true; + } + + setMaterial(m->color, m->surfaceProps); + + if(m->texture){ + d3d::setTexture(0, m->texture); + setPixelShader(default_tex_PS); + }else + setPixelShader(default_PS); + + drawInst(building->instHeader, inst); + } + if(defer) + numBlendInsts[pass]++; +} + +static void +AtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha) +{ + using namespace rw; + using namespace rw::d3d; + using namespace rw::d3d9; + + BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]]; + + atomic->getPipeline()->instance(atomic); + building->instHeader = (d3d9::InstanceDataHeader*)atomic->geometry->instData; + assert(building->instHeader != nil); + assert(building->instHeader->platform == PLATFORM_D3D9); + building->fadeAlpha = fadeAlpha; + building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT); + SetMatrix(building, atomic->getFrame()->getLTM()); + numBlendInsts[pass]++; +} + +static void +RenderBlendPass(int pass) +{ + using namespace rw; + using namespace rw::d3d; + using namespace rw::d3d9; + + setVertexShader(default_amb_VS); + + int i; + for(i = 0; i < numBlendInsts[pass]; i++){ + BuildingInst *building = &blendInsts[pass][i]; + + setStreamSource(0, building->instHeader->vertexStream[0].vertexBuffer, 0, building->instHeader->vertexStream[0].stride); + setIndices(building->instHeader->indexBuffer); + setVertexDeclaration(building->instHeader->vertexDeclaration); + d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&building->combinedMat, 4); + if(building->lighting) + setAmbient(pAmbient->color); + else + setAmbient(black); + + InstanceData *inst = building->instHeader->inst; + for(rw::uint32 j = 0; j < building->instHeader->numMeshes; j++, inst++){ + Material *m = inst->material; + if(!inst->vertexAlpha && m->color.alpha == 255 && !IsTextureTransparent(m->texture) && building->fadeAlpha == 255) + continue; // already done this one + + rw::RGBA color = m->color; + color.alpha = (color.alpha * building->fadeAlpha)/255; + setMaterial(color, m->surfaceProps); + + if(m->texture){ + d3d::setTexture(0, m->texture); + setPixelShader(default_tex_PS); + }else + setPixelShader(default_PS); + + drawInst(building->instHeader, inst); + } + } +} +#endif +#ifdef RW_GL3 +struct BuildingInst +{ + rw::Matrix matrix; + rw::gl3::InstanceDataHeader *instHeader; + uint8 fadeAlpha; + bool lighting; +}; +static BuildingInst blendInsts[3][2000]; +static int numBlendInsts[3]; + +static bool +IsTextureTransparent(RwTexture *tex) +{ + if(tex == nil || tex->raster == nil) + return false; + return PLUGINOFFSET(rw::gl3::Gl3Raster, tex->raster, rw::gl3::nativeRasterOffset)->hasAlpha; +} + +// Render all opaque meshes and put atomics that needs blending +// into the deferred list. +static void +AtomicFirstPass(RpAtomic *atomic, int pass) +{ + using namespace rw; + using namespace rw::gl3; + + BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]]; + + atomic->getPipeline()->instance(atomic); + building->instHeader = (gl3::InstanceDataHeader*)atomic->geometry->instData; + assert(building->instHeader != nil); + assert(building->instHeader->platform == PLATFORM_GL3); + building->fadeAlpha = 255; + building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT); + + WorldLights lights; + lights.numAmbients = 1; + lights.numDirectionals = 0; + lights.numLocals = 0; + if(building->lighting) + lights.ambient = pAmbient->color; + else + lights.ambient = black; + + bool setupDone = false; + bool defer = false; + building->matrix = *atomic->getFrame()->getLTM(); + + InstanceData *inst = building->instHeader->inst; + for(rw::uint32 i = 0; i < building->instHeader->numMeshes; i++, inst++){ + Material *m = inst->material; + + if(inst->vertexAlpha || m->color.alpha != 255 || + IsTextureTransparent(m->texture)){ + defer = true; + continue; + } + + // alright we're rendering this atomic + if(!setupDone){ + defaultShader->use(); + setWorldMatrix(&building->matrix); +#ifdef RW_GL_USE_VAOS + glBindVertexArray(building->instHeader->vao); +#else + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, building->instHeader->ibo); + glBindBuffer(GL_ARRAY_BUFFER, building->instHeader->vbo); + setAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs); +#endif + setLights(&lights); + setupDone = true; + } + + setMaterial(m->color, m->surfaceProps); + + setTexture(0, m->texture); + + drawInst(building->instHeader, inst); + } +#ifndef RW_GL_USE_VAOS + disableAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs); +#endif + if(defer) + numBlendInsts[pass]++; +} + +static void +AtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha) +{ + using namespace rw; + using namespace rw::gl3; + + BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]]; + + atomic->getPipeline()->instance(atomic); + building->instHeader = (gl3::InstanceDataHeader*)atomic->geometry->instData; + assert(building->instHeader != nil); + assert(building->instHeader->platform == PLATFORM_GL3); + building->fadeAlpha = fadeAlpha; + building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT); + building->matrix = *atomic->getFrame()->getLTM(); + numBlendInsts[pass]++; +} + +static void +RenderBlendPass(int pass) +{ + using namespace rw; + using namespace rw::gl3; + + defaultShader->use(); + WorldLights lights; + lights.numAmbients = 1; + lights.numDirectionals = 0; + lights.numLocals = 0; + + int i; + for(i = 0; i < numBlendInsts[pass]; i++){ + BuildingInst *building = &blendInsts[pass][i]; + +#ifdef RW_GL_USE_VAOS + glBindVertexArray(building->instHeader->vao); +#else + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, building->instHeader->ibo); + glBindBuffer(GL_ARRAY_BUFFER, building->instHeader->vbo); + setAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs); +#endif + setWorldMatrix(&building->matrix); + if(building->lighting) + lights.ambient = pAmbient->color; + else + lights.ambient = black; + setLights(&lights); + + InstanceData *inst = building->instHeader->inst; + for(rw::uint32 j = 0; j < building->instHeader->numMeshes; j++, inst++){ + Material *m = inst->material; + if(!inst->vertexAlpha && m->color.alpha == 255 && !IsTextureTransparent(m->texture) && building->fadeAlpha == 255) + continue; // already done this one + + rw::RGBA color = m->color; + color.alpha = (color.alpha * building->fadeAlpha)/255; + setMaterial(color, m->surfaceProps); + + setTexture(0, m->texture); + + drawInst(building->instHeader, inst); + } +#ifndef RW_GL_USE_VAOS + disableAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs); +#endif + } +} +#endif + +void +CRenderer::RenderOneBuilding(CEntity *ent, float camdist) +{ + if(ent->m_rwObject == nil) + return; + + ent->bImBeingRendered = true; // TODO: this seems wrong, but do we even need it? + + assert(RwObjectGetType(ent->m_rwObject) == rpATOMIC); + RpAtomic *atomic = (RpAtomic*)ent->m_rwObject; + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->GetModelIndex()); + + int pass = PASS_BLEND; + if(mi->m_additive) // very questionable + pass = PASS_ADD; + if(mi->m_noZwrite) + pass = PASS_NOZ; + + if(ent->bDistanceFade){ + RpAtomic *lodatm; + float fadefactor; + uint32 alpha; + + lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE); + fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE; + if(fadefactor > 1.0f) + fadefactor = 1.0f; + alpha = mi->m_alpha * fadefactor; + + if(alpha == 255) + AtomicFirstPass(atomic, pass); + else{ + // not quite sure what this is about, do we have to do that? + RpGeometry *geo = RpAtomicGetGeometry(lodatm); + if(geo != RpAtomicGetGeometry(atomic)) + RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); + AtomicFullyTransparent(atomic, pass, alpha); + } + }else + AtomicFirstPass(atomic, pass); + + ent->bImBeingRendered = false; // TODO: this seems wrong, but do we even need it? +} + +void +CRenderer::RenderWorld(int pass) +{ + int i; + CEntity *e; + CLink *node; + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + DeActivateDirectional(); + SetAmbientColours(); + + // Temporary...have to figure out sorting better + switch(pass){ + case 0: + // Roads + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + for(i = 0; i < ms_nNoOfVisibleBuildings; i++){ + e = ms_aVisibleBuildingPtrs[i]; + if(e->bIsBIGBuilding || IsRoad(e)) + RenderOneBuilding(e); + } + for(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev; + node != &CVisibilityPlugins::m_alphaBuildingList.head; + node = node->prev){ + e = node->item.entity; + if(e->bIsBIGBuilding || IsRoad(e)) + RenderOneBuilding(e, node->item.sort); + } + + // KLUDGE for road puddles which have to be rendered at road-time + // only very temporary, there are more rendering issues + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RenderBlendPass(PASS_BLEND); + numBlendInsts[PASS_BLEND] = 0; + break; + case 1: + // Opaque + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + for(i = 0; i < ms_nNoOfVisibleBuildings; i++){ + e = ms_aVisibleBuildingPtrs[i]; + if(!(e->bIsBIGBuilding || IsRoad(e))) + RenderOneBuilding(e); + } + for(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev; + node != &CVisibilityPlugins::m_alphaBuildingList.head; + node = node->prev){ + e = node->item.entity; + if(!(e->bIsBIGBuilding || IsRoad(e))) + RenderOneBuilding(e, node->item.sort); + } + // Now we have iterated through all visible buildings (unsorted and sorted) + // and the transparency list is done. + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + RenderBlendPass(PASS_NOZ); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + break; + case 2: + // Transparent + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RenderBlendPass(PASS_ADD); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RenderBlendPass(PASS_BLEND); + break; + } +} + +void +CRenderer::RenderPeds(void) +{ + int i; + CEntity *e; + + for(i = 0; i < ms_nNoOfVisibleVehicles; i++){ + e = ms_aVisibleVehiclePtrs[i]; + if(e->IsPed()) + RenderOneNonRoad(e); + } +} + +void +CRenderer::RenderVehicles(void) +{ + int i; + CEntity *e; + EntityInfo ei; + CLink *node; + + // not the real thing + for(i = 0; i < ms_nNoOfVisibleVehicles; i++){ + e = ms_aVisibleVehiclePtrs[i]; + if(!e->IsVehicle()) + continue; +// if(PutIntoSortedVehicleList((CVehicle*)e)) +// continue; // boats handled elsewhere + ei.ent = e; + ei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr(); + gSortedVehiclesAndPeds.InsertSorted(ei); + } + + for(node = gSortedVehiclesAndPeds.tail.prev; + node != &gSortedVehiclesAndPeds.head; + node = node->prev) + RenderOneNonRoad(node->item.ent); +} + +void +CRenderer::RenderWater(void) +{ + int i; + CEntity *e; + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + SetStencilState(2); + + for(i = 0; i < ms_nNoOfVisibleVehicles; i++){ + e = ms_aVisibleVehiclePtrs[i]; + if(e->IsVehicle() && ((CVehicle*)e)->IsBoat()) + ((CBoat*)e)->RenderWaterOutPolys(); + } + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + SetStencilState(1); + + CWaterLevel::RenderWater(); + + SetStencilState(0); +} + +void +CRenderer::ClearForFrame(void) +{ + ms_nNoOfVisibleEntities = 0; + ms_nNoOfVisibleVehicles = 0; + ms_nNoOfVisibleBuildings = 0; + ms_nNoOfInVisibleEntities = 0; + gSortedVehiclesAndPeds.Clear(); + + numBlendInsts[PASS_NOZ] = 0; + numBlendInsts[PASS_ADD] = 0; + numBlendInsts[PASS_BLEND] = 0; +} +#endif + void CRenderer::RenderFadingInEntities(void) { @@ -634,9 +1208,14 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) void CRenderer::ConstructRenderList(void) +{ +#ifdef NEW_RENDERER + if(!gbNewRenderer) +#endif { ms_nNoOfVisibleEntities = 0; ms_nNoOfInVisibleEntities = 0; +} ms_vecCameraPosition = TheCamera.GetPosition(); // unused @@ -1122,6 +1701,20 @@ CRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrL } } +void +CRenderer::InsertEntityIntoList(CEntity *ent) +{ +#ifdef NEW_RENDERER + // TODO: there are more flags being checked here + if(gbNewRenderer && (ent->IsVehicle() || ent->IsPed())) + ms_aVisibleVehiclePtrs[ms_nNoOfVisibleVehicles++] = ent; + else if(gbNewRenderer && ent->IsBuilding()) + ms_aVisibleBuildingPtrs[ms_nNoOfVisibleBuildings++] = ent; + else +#endif + ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; +} + void CRenderer::ScanBigBuildingList(CPtrList &list) { @@ -1136,7 +1729,7 @@ CRenderer::ScanBigBuildingList(CPtrList &list) #endif if(!ent->bZoneCulled){ if(SetupBigBuildingVisibility(ent) == VIS_VISIBLE) - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + InsertEntityIntoList(ent); #ifndef MASTER EntitiesRendered++; RenderedBigBuildings++; @@ -1167,7 +1760,7 @@ CRenderer::ScanSectorList(CPtrList *lists) if(IsEntityCullZoneVisible(ent)){ switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + InsertEntityIntoList(ent); break; case VIS_INVISIBLE: if(!IsGlass(ent->GetModelIndex())) @@ -1210,7 +1803,7 @@ CRenderer::ScanSectorList(CPtrList *lists) break; } #endif - }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){ + }else if(IsRoad(ent) && !CStreaming::ms_disableStreaming){ if(SetupEntityVisibility(ent) == VIS_STREAMME) if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) CStreaming::RequestModel(ent->GetModelIndex(), 0); @@ -1243,7 +1836,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) if(IsEntityCullZoneVisible(ent)){ switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + InsertEntityIntoList(ent); break; case VIS_INVISIBLE: if(!IsGlass(ent->GetModelIndex())) @@ -1289,7 +1882,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) break; } #endif - }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){ + }else if(IsRoad(ent) && !CStreaming::ms_disableStreaming){ if(SetupEntityVisibility(ent) == VIS_STREAMME) CStreaming::RequestModel(ent->GetModelIndex(), 0); }else{ @@ -1320,7 +1913,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists) ent->m_scanCode = CWorld::GetCurrentScanCode(); switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + InsertEntityIntoList(ent); break; case VIS_OFFSCREEN: dx = ms_vecCameraPosition.x - ent->GetPosition().x; -- cgit v1.2.3