summaryrefslogtreecommitdiffstats
path: root/src/rw/VisibilityPlugins.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rw/VisibilityPlugins.cpp')
-rw-r--r--src/rw/VisibilityPlugins.cpp200
1 files changed, 167 insertions, 33 deletions
diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp
index b2e252a0..21e00725 100644
--- a/src/rw/VisibilityPlugins.cpp
+++ b/src/rw/VisibilityPlugins.cpp
@@ -1,5 +1,6 @@
#include "common.h"
+#include "RwHelper.h"
#include "templates.h"
#include "Entity.h"
#include "ModelInfo.h"
@@ -9,8 +10,7 @@
#include "VisibilityPlugins.h"
#include "World.h"
#include "custompipes.h"
-
-#define FADE_DISTANCE 20.0f
+#include "MemoryHeap.h"
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList;
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList;
@@ -31,6 +31,119 @@ float CVisibilityPlugins::ms_pedLod0Dist;
float CVisibilityPlugins::ms_pedLod1Dist;
float CVisibilityPlugins::ms_pedFadeDist;
+#ifdef GTA_PS2 // maybe something else?
+// if wanted, delete the original geometry data after rendering
+// and only keep the instanced data
+bool
+rpDefaultGeometryInstance(RpGeometry *geo, void *atomic, int del)
+{
+#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
+ if(RpGeometryGetNumMorphTargets(geo) != 1)
+ return false;
+
+ // this needs R*'s modification that geometry data is
+ // allocated separately from the geometry itself
+ geo->instanceFlags = rpGEOMETRYINSTANCE;
+ AtomicDefaultRenderCallBack((RpAtomic*)atomic);
+
+ if(!del)
+ return true;
+
+ // New mesh without indices
+ RpMeshHeader *newheader = _rpMeshHeaderCreate(sizeof(RpMesh)*geo->mesh->numMeshes + sizeof(RpMeshHeader));
+ newheader->numMeshes = geo->mesh->numMeshes;
+ newheader->serialNum = 1;
+ newheader->totalIndicesInMesh = 0;
+ newheader->firstMeshOffset = 0;
+ RpMesh *oldmesh = (RpMesh*)(geo->mesh+1);
+ RpMesh *newmesh = (RpMesh*)(newheader+1);
+ for(int i = 0; i < geo->mesh->numMeshes; i++){
+ newmesh[i].indices = nil;
+ newmesh[i].numIndices = 0;
+ newmesh[i].material = oldmesh[i].material;
+ }
+
+ geo->refCount++;
+ RpGeometryLock(geo, rpGEOMETRYLOCKPOLYGONS | rpGEOMETRYLOCKVERTICES |
+ rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT |
+ rpGEOMETRYLOCKTEXCOORDS1 | rpGEOMETRYLOCKTEXCOORDS2);
+
+ // vertices and normals
+ RpMorphTarget *mt = RpGeometryGetMorphTarget(geo, 0);
+ if(mt->verts){
+ RwFree(mt->verts);
+ mt->verts = nil;
+ mt->normals = nil;
+ }
+ geo->numVertices = 0;
+
+ // triangles
+ for(int i = 0; i < RpGeometryGetNumTriangles(geo); i++){
+ if(RpGeometryGetTriangles(geo)->matIndex == -1)
+ continue;
+ RpMaterialDestroy(_rpMaterialListGetMaterial(&geo->matList, RpGeometryGetTriangles(geo)->matIndex));
+ }
+ if(RpGeometryGetTriangles(geo)){
+ RwFree(RpGeometryGetTriangles(geo));
+ geo->triangles = nil;
+ geo->numTriangles = 0;
+ }
+
+ // tex coords
+ if(RpGeometryGetVertexTexCoords(geo, 1)){
+ RwFree(RpGeometryGetVertexTexCoords(geo, 1));
+ geo->texCoords[1] = nil;
+ }
+ if(RpGeometryGetVertexTexCoords(geo, 0)){
+ RwFree(RpGeometryGetVertexTexCoords(geo, 0));
+ geo->texCoords[0] = nil;
+ }
+
+ // vertex colors
+ if(RpGeometryGetPreLightColors(geo)){
+ RwFree(RpGeometryGetPreLightColors(geo));
+ geo->preLitLum = nil;
+ }
+
+ RpGeometryUnlock(geo);
+
+ geo->instanceFlags = rpGEOMETRYPERSISTENT;
+ // BUG? don't we have to free the old mesh?
+ geo->mesh = newheader;
+ geo->refCount--;
+#else
+ // We can do something for librw here actually, maybe later
+ AtomicDefaultRenderCallBack((RpAtomic*)atomic);
+#endif
+
+ return true;
+}
+
+RpAtomic*
+PreInstanceRenderCB(RpAtomic *atomic)
+{
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ if(RpGeometryGetTriangles(geo)){
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ rpDefaultGeometryInstance(geo, atomic, 1);
+ POP_MEMID();
+ }else
+ AtomicDefaultRenderCallBack(atomic);
+ return atomic;
+}
+#define RENDERCALLBACK PreInstanceRenderCB
+#else
+RpAtomic*
+DefaultRenderCB_pushid(RpAtomic *atomic)
+{
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ AtomicDefaultRenderCallBack(atomic);
+ POP_MEMID();
+ return atomic;
+}
+#define RENDERCALLBACK DefaultRenderCB_pushid
+#endif
+
void
CVisibilityPlugins::Initialise(void)
{
@@ -90,6 +203,10 @@ CVisibilityPlugins::InsertAtomicIntoSortedList(RpAtomic *a, float dist)
return ret;
}
+// can't increase this yet unfortunately...
+// probably have to fix fading for this so material alpha isn't overwritten
+#define VEHICLE_LODDIST_MULTIPLIER (TheCamera.GenerationDistMultiplier)
+
void
CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)
{
@@ -102,11 +219,11 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)
else
ms_cullCompsDist = sq(TheCamera.LODDistMultiplier * 20.0f);
- ms_vehicleLod0Dist = sq(70.0f * TheCamera.GenerationDistMultiplier);
- ms_vehicleLod1Dist = sq(90.0f * TheCamera.GenerationDistMultiplier);
- ms_vehicleFadeDist = sq(100.0f * TheCamera.GenerationDistMultiplier);
- ms_bigVehicleLod0Dist = sq(60.0f * TheCamera.GenerationDistMultiplier);
- ms_bigVehicleLod1Dist = sq(150.0f * TheCamera.GenerationDistMultiplier);
+ ms_vehicleLod0Dist = sq(70.0f * VEHICLE_LODDIST_MULTIPLIER);
+ ms_vehicleLod1Dist = sq(90.0f * VEHICLE_LODDIST_MULTIPLIER);
+ ms_vehicleFadeDist = sq(100.0f * VEHICLE_LODDIST_MULTIPLIER);
+ ms_bigVehicleLod0Dist = sq(60.0f * VEHICLE_LODDIST_MULTIPLIER);
+ ms_bigVehicleLod1Dist = sq(150.0f * VEHICLE_LODDIST_MULTIPLIER);
ms_pedLod0Dist = sq(25.0f * TheCamera.LODDistMultiplier);
ms_pedLod1Dist = sq(60.0f * TheCamera.LODDistMultiplier);
ms_pedFadeDist = sq(70.0f * TheCamera.LODDistMultiplier);
@@ -133,7 +250,7 @@ CVisibilityPlugins::RenderAlphaAtomics(void)
for(node = m_alphaList.tail.prev;
node != &m_alphaList.head;
node = node->prev)
- AtomicDefaultRenderCallBack(node->item.atomic);
+ RENDERCALLBACK(node->item.atomic);
}
void
@@ -158,6 +275,10 @@ CVisibilityPlugins::RenderFadingEntities(void)
if(mi->m_noZwrite)
#endif
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
+#ifdef EXTRA_MODEL_FLAGS
+ else if(mi->m_bIsTree)
+ SetAlphaRef(128);
+#endif
if(e->bDistanceFade){
DeActivateDirectional();
@@ -168,6 +289,10 @@ CVisibilityPlugins::RenderFadingEntities(void)
}else
CRenderer::RenderOneNonRoad(e);
+#ifdef EXTRA_MODEL_FLAGS
+ if(mi->m_bIsTree)
+ SetAlphaRef(2);
+#endif
#ifdef FIX_BUGS
if(mi->GetModelType() == MITYPE_SIMPLE && mi->m_noZwrite)
#else
@@ -190,11 +315,16 @@ CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic)
m = RwFrameGetLTM(RpAtomicGetFrame(atomic));
RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);
len = RwV3dLength(&view);
+#ifdef FIX_BUGS
+ // from VC
+ lodatm = mi->GetAtomicFromDistance(len * TheCamera.LODDistMultiplier / VEHICLE_LODDIST_MULTIPLIER);
+#else
lodatm = mi->GetAtomicFromDistance(len);
+#endif
if(lodatm){
if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic))
RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -211,7 +341,7 @@ CVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic)
len = RwV3dLength(&view);
if(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f)
return atomic;
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -225,7 +355,7 @@ CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha)
flags = RpGeometryGetFlags(geo);
RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
RpGeometrySetFlags(geo, flags);
return atomic;
@@ -243,7 +373,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);
if(mi->m_additive){
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}else{
fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
@@ -251,7 +381,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
fadefactor = 1.0f;
alpha = mi->m_alpha * fadefactor;
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else{
RpGeometry *geo = RpAtomicGetGeometry(lodatm);
uint32 flags = RpGeometryGetFlags(geo);
@@ -259,7 +389,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
if(geo != RpAtomicGetGeometry(atomic))
RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
RpGeometrySetFlags(geo, flags);
}
@@ -286,7 +416,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic)
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -311,10 +441,10 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic)
if(flags & ATOMIC_FLAG_DRAWLAST){
// sort before clump
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}else{
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
}
return atomic;
@@ -337,7 +467,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic)
if(dot > 0.0f)
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -360,7 +490,7 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)
return atomic;
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -374,7 +504,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic)
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
distsq = GetDistanceSquaredFromCamera(clumpframe);
if(distsq < ms_bigVehicleLod1Dist)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -396,7 +526,7 @@ CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic)
if(dot > 0.0f)
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -420,7 +550,7 @@ CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic)
return atomic;
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -437,7 +567,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)
if(dist >= ms_vehicleLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -454,7 +584,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic)
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
distsq = GetDistanceSquaredFromCamera(clumpframe);
if(distsq >= ms_bigVehicleLod1Dist)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -475,7 +605,7 @@ CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic)
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -500,10 +630,10 @@ CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)
if(flags & ATOMIC_FLAG_DRAWLAST){
// sort before clump
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}else{
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
}
return atomic;
@@ -514,7 +644,7 @@ CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)
{
if(CWorld::Players[0].m_pSkinTexture)
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -530,7 +660,7 @@ CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic)
if(dist >= ms_pedLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -549,7 +679,7 @@ CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic)
if(dist < ms_pedLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -568,7 +698,7 @@ CVisibilityPlugins::RenderPedCB(RpAtomic *atomic)
if(RwV3dDotProduct(&cam2atm, &cam2atm) < ms_pedLod1Dist){
alpha = GetClumpAlpha(RpAtomicGetClump(atomic));
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -698,6 +828,11 @@ CVisibilityPlugins::PluginAttach(void)
ms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt),
ID_VISIBILITYCLUMP,
ClumpConstructor, ClumpDestructor, ClumpCopyConstructor);
+
+#if GTA_VERSION <= GTA3_PS2_160
+ Initialise();
+#endif
+
return ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1;
}
@@ -768,12 +903,11 @@ CVisibilityPlugins::GetAtomicId(RpAtomic *atomic)
return ATOMICEXT(atomic)->flags;
}
-// This is rather useless, but whatever
void
CVisibilityPlugins::SetAtomicRenderCallback(RpAtomic *atomic, RpAtomicCallBackRender cb)
{
if(cb == nil)
- cb = AtomicDefaultRenderCallBack; // not necessary
+ cb = RENDERCALLBACK;
RpAtomicSetRenderCallBack(atomic, cb);
}