diff options
Diffstat (limited to 'src/rw/VisibilityPlugins.cpp')
-rw-r--r-- | src/rw/VisibilityPlugins.cpp | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp new file mode 100644 index 00000000..f8b1f6b2 --- /dev/null +++ b/src/rw/VisibilityPlugins.cpp @@ -0,0 +1,889 @@ +#include "common.h" +#include "patcher.h" +#include "templates.h" +#include "Entity.h" +#include "ModelInfo.h" +#include "Lights.h" +#include "Renderer.h" +#include "Camera.h" +#include "VisibilityPlugins.h" +#include "World.h" + +#define FADE_DISTANCE 20.0f + +/* +CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList; +CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList; + +int32 CVisibilityPlugins::ms_atomicPluginOffset = -1; +int32 CVisibilityPlugins::ms_framePluginOffset = -1; +int32 CVisibilityPlugins::ms_clumpPluginOffset = -1; +*/ +CLinkList<CVisibilityPlugins::AlphaObjectInfo> &CVisibilityPlugins::m_alphaList = *(CLinkList<CVisibilityPlugins::AlphaObjectInfo>*)0x8F42E4; +CLinkList<CVisibilityPlugins::AlphaObjectInfo> &CVisibilityPlugins::m_alphaEntityList = *(CLinkList<CVisibilityPlugins::AlphaObjectInfo>*)0x943084; + +int32 &CVisibilityPlugins::ms_atomicPluginOffset = *(int32*)0x600124; +int32 &CVisibilityPlugins::ms_framePluginOffset = *(int32*)0x600128; +int32 &CVisibilityPlugins::ms_clumpPluginOffset = *(int32*)0x60012C; + +RwCamera *&CVisibilityPlugins::ms_pCamera = *(RwCamera**)0x8F2514; +RwV3d *&CVisibilityPlugins::ms_pCameraPosn = *(RwV3d**)0x8F6270; +float &CVisibilityPlugins::ms_cullCompsDist = *(float*)0x8F2BC4; +float &CVisibilityPlugins::ms_vehicleLod0Dist = *(float*)0x885B28; +float &CVisibilityPlugins::ms_vehicleLod1Dist = *(float*)0x885B30; +float &CVisibilityPlugins::ms_vehicleFadeDist = *(float*)0x8E28B4; +float &CVisibilityPlugins::ms_bigVehicleLod0Dist = *(float*)0x8E2A84; +float &CVisibilityPlugins::ms_bigVehicleLod1Dist = *(float*)0x8E2A8C; +float &CVisibilityPlugins::ms_pedLod0Dist = *(float*)0x8F2BD4; +float &CVisibilityPlugins::ms_pedLod1Dist = *(float*)0x8F2BD8; +float &CVisibilityPlugins::ms_pedFadeDist = *(float*)0x8E2C34; + +void +CVisibilityPlugins::Initialise(void) +{ + m_alphaList.Init(20); + m_alphaList.head.item.sort = 0.0f; + m_alphaList.tail.item.sort = 100000000.0f; + m_alphaEntityList.Init(150); + m_alphaEntityList.head.item.sort = 0.0f; + m_alphaEntityList.tail.item.sort = 100000000.0f; +} + +void +CVisibilityPlugins::Shutdown(void) +{ + m_alphaList.Shutdown(); + m_alphaEntityList.Shutdown(); +} + +void +CVisibilityPlugins::InitAlphaEntityList(void) +{ + m_alphaEntityList.Clear(); +} + +bool +CVisibilityPlugins::InsertEntityIntoSortedList(CEntity *e, float dist) +{ + AlphaObjectInfo item; + item.entity = e; + item.sort = dist; + bool ret = !!m_alphaEntityList.InsertSorted(item); +// if(!ret) +// printf("list full %d\n", m_alphaEntityList.Count()); + return ret; +} + +void +CVisibilityPlugins::InitAlphaAtomicList(void) +{ + m_alphaList.Clear(); +} + +bool +CVisibilityPlugins::InsertAtomicIntoSortedList(RpAtomic *a, float dist) +{ + AlphaObjectInfo item; + item.atomic = a; + item.sort = dist; + bool ret = !!m_alphaList.InsertSorted(item); +// if(!ret) +// printf("list full %d\n", m_alphaList.Count()); + return ret; +} + +void +CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera) +{ + ms_pCamera = camera; + ms_pCameraPosn = RwMatrixGetPos(RwFrameGetMatrix(RwCameraGetFrame(camera))); + + if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || + TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) + ms_cullCompsDist = 1000000.0f; + 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_pedLod0Dist = sq(25.0f * TheCamera.LODDistMultiplier); + ms_pedLod1Dist = sq(60.0f * TheCamera.LODDistMultiplier); + ms_pedFadeDist = sq(70.0f * TheCamera.LODDistMultiplier); +} + +RpMaterial* +SetAlphaCB(RpMaterial *material, void *data) +{ + ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uint32)data; + return material; +} + +RpMaterial* +SetTextureCB(RpMaterial *material, void *data) +{ + RpMaterialSetTexture(material, (RwTexture*)data); + return material; +} + +void +CVisibilityPlugins::RenderAlphaAtomics(void) +{ + CLink<AlphaObjectInfo> *node; + for(node = m_alphaList.tail.prev; + node != &m_alphaList.head; + node = node->prev) + AtomicDefaultRenderCallBack(node->item.atomic); +} + +void +CVisibilityPlugins::RenderFadingEntities(void) +{ + CLink<AlphaObjectInfo> *node; + CSimpleModelInfo *mi; + for(node = m_alphaEntityList.tail.prev; + node != &m_alphaEntityList.head; + node = node->prev){ + CEntity *e = node->item.entity; + if(e->m_rwObject == nil) + continue; + mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(e->m_modelIndex); + if(mi->m_noZwrite) + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + + if(e->bDistanceFade){ + DeActivateDirectional(); + SetAmbientColours(); + e->bImBeingRendered = true; + RenderFadingAtomic((RpAtomic*)e->m_rwObject, node->item.sort); + e->bImBeingRendered = false; + }else + CRenderer::RenderOneNonRoad(e); + + if(mi->m_noZwrite) + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + } +} + +RpAtomic* +CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic) +{ + RpAtomic *lodatm; + RwMatrix *m; + RwV3d view; + float len; + CSimpleModelInfo *mi; + + mi = GetAtomicModelInfo(atomic); + m = RwFrameGetLTM(RpAtomicGetFrame(atomic)); + RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn); + len = RwV3dLength(&view); + lodatm = mi->GetAtomicFromDistance(len); + if(lodatm){ + if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic)) + RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE); + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic) +{ + RwMatrix *m; + RwV3d view; + float len; + + m = RwFrameGetLTM(RpAtomicGetFrame(atomic)); + RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn); + len = RwV3dLength(&view); + if(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f) + return atomic; + AtomicDefaultRenderCallBack(atomic); + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha) +{ + RpGeometry *geo; + uint32 flags; + + geo = RpAtomicGetGeometry(atomic); + flags = RpGeometryGetFlags(geo); + RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR); + RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha); + AtomicDefaultRenderCallBack(atomic); + RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255); + RpGeometrySetFlags(geo, flags); + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist) +{ + RpAtomic *lodatm; + float fadefactor; + uint8 alpha; + CSimpleModelInfo *mi; + + mi = GetAtomicModelInfo(atomic); + lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE); + if(mi->m_additive){ + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + AtomicDefaultRenderCallBack(atomic); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + }else{ + fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE; + if(fadefactor > 1.0f) + fadefactor = 1.0f; + alpha = mi->m_alpha * fadefactor; + if(alpha == 255) + AtomicDefaultRenderCallBack(atomic); + else{ + RpGeometry *geo = RpAtomicGetGeometry(lodatm); + uint32 flags = RpGeometryGetFlags(geo); + RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR); + RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha); + if(geo != RpAtomicGetGeometry(atomic)) + RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) + AtomicDefaultRenderCallBack(atomic); + RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255); + RpGeometrySetFlags(geo, flags); + } + } + return atomic; +} + + + +RpAtomic* +CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_vehicleLod0Dist){ + flags = GetAtomicId(atomic); + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){ + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot)) + return atomic; + } + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_vehicleLod0Dist){ + flags = GetAtomicId(atomic); + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0) + if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot)) + return atomic; + + if(flags & ATOMIC_FLAG_DRAWLAST){ + // sort before clump + if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f)) + AtomicDefaultRenderCallBack(atomic); + }else{ + if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) + AtomicDefaultRenderCallBack(atomic); + } + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_bigVehicleLod0Dist){ + flags = GetAtomicId(atomic); + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){ + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(dot > 0.0f) + return atomic; + } + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_bigVehicleLod0Dist){ + flags = GetAtomicId(atomic); + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(dot > 0.0f) + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0) + return atomic; + + if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_bigVehicleLod1Dist) + AtomicDefaultRenderCallBack(atomic); + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq >= ms_bigVehicleLod0Dist && + distsq < ms_bigVehicleLod1Dist){ + flags = GetAtomicId(atomic); + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){ + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(dot > 0.0f) + return atomic; + } + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq >= ms_bigVehicleLod0Dist && + distsq < ms_bigVehicleLod1Dist){ + flags = GetAtomicId(atomic); + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(dot > 0.0f) + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0) + return atomic; + + if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic) +{ + RpClump *clump; + float dist; + int32 alpha; + + clump = RpAtomicGetClump(atomic); + dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump)); + if(dist >= ms_vehicleLod0Dist){ + alpha = GetClumpAlpha(clump); + if(alpha == 255) + AtomicDefaultRenderCallBack(atomic); + else + RenderAlphaAtomic(atomic, alpha); + } + return atomic; + +} + +RpAtomic* +CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq >= ms_bigVehicleLod1Dist) + AtomicDefaultRenderCallBack(atomic); + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_bigVehicleLod1Dist){ + flags = GetAtomicId(atomic); + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){ + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot)) + return atomic; + } + AtomicDefaultRenderCallBack(atomic); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic) +{ + RwFrame *clumpframe; + float distsq, dot; + uint32 flags; + + clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); + distsq = GetDistanceSquaredFromCamera(clumpframe); + if(distsq < ms_bigVehicleLod1Dist){ + flags = GetAtomicId(atomic); + dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)), + RwFrameGetLTM(clumpframe), flags); + if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0) + if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot)) + return atomic; + + if(flags & ATOMIC_FLAG_DRAWLAST){ + // sort before clump + if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f)) + AtomicDefaultRenderCallBack(atomic); + }else{ + if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) + AtomicDefaultRenderCallBack(atomic); + } + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic) +{ + if(CWorld::Players[0].m_pSkinTexture) + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture); + AtomicDefaultRenderCallBack(atomic); + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic) +{ + RpClump *clump; + float dist; + int32 alpha; + + clump = RpAtomicGetClump(atomic); + dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump)); + if(dist >= ms_pedLod0Dist){ + alpha = GetClumpAlpha(clump); + if(alpha == 255) + AtomicDefaultRenderCallBack(atomic); + else + RenderAlphaAtomic(atomic, alpha); + } + return atomic; +} + +RpAtomic* +CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic) +{ + RpClump *clump; + float dist; + int32 alpha; + + clump = RpAtomicGetClump(atomic); + dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump)); + if(dist < ms_pedLod0Dist){ + alpha = GetClumpAlpha(clump); + if(alpha == 255) + AtomicDefaultRenderCallBack(atomic); + else + RenderAlphaAtomic(atomic, alpha); + } + return atomic; +} + +float +CVisibilityPlugins::GetDistanceSquaredFromCamera(RwFrame *frame) +{ + RwMatrix *m; + RwV3d dist; + m = RwFrameGetLTM(frame); + RwV3dSub(&dist, RwMatrixGetPos(m), ms_pCameraPosn); + return RwV3dDotProduct(&dist, &dist); +} + +float +CVisibilityPlugins::GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags) +{ + RwV3d dist; + float dot, dotdoor; + + // Vehicle forward is the y axis (RwMatrix.up) + // Vehicle right is the x axis (RwMatrix.right) + + RwV3dSub(&dist, RwMatrixGetPos(atomicMat), ms_pCameraPosn); + // forward/backward facing + if(flags & (ATOMIC_FLAG_FRONT | ATOMIC_FLAG_REAR)) + dot = RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat)); + // left/right facing + else if(flags & (ATOMIC_FLAG_LEFT | ATOMIC_FLAG_RIGHT)) + dot = RwV3dDotProduct(&dist, RwMatrixGetRight(clumpMat)); + else + dot = 0.0f; + if(flags & (ATOMIC_FLAG_LEFT | ATOMIC_FLAG_REAR)) + dot = -dot; + + if(flags & (ATOMIC_FLAG_REARDOOR | ATOMIC_FLAG_FRONTDOOR)){ + if(flags & ATOMIC_FLAG_REARDOOR) + dotdoor = -RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat)); + else if(flags & ATOMIC_FLAG_FRONTDOOR) + dotdoor = RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat)); + else + dotdoor = 0.0f; + + if(dot < 0.0f && dotdoor < 0.0f) + dot += dotdoor; + if(dot > 0.0f && dotdoor > 0.0f) + dot += dotdoor; + } + + return dot; +} + +/* These are all unused */ + +bool +CVisibilityPlugins::DefaultVisibilityCB(RpClump *clump) +{ + return true; +} + +bool +CVisibilityPlugins::FrustumSphereCB(RpClump *clump) +{ + RwSphere sphere; + RwFrame *frame = RpClumpGetFrame(clump); + + CClumpModelInfo *modelInfo = (CClumpModelInfo*)GetFrameHierarchyId(frame); + sphere.radius = modelInfo->GetColModel()->boundingSphere.radius; + sphere.center.x = modelInfo->GetColModel()->boundingSphere.center.x; + sphere.center.y = modelInfo->GetColModel()->boundingSphere.center.y; + sphere.center.z = modelInfo->GetColModel()->boundingSphere.center.z; + RwV3dTransformPoints(&sphere.center, &sphere.center, 1, RwFrameGetLTM(frame)); + return RwCameraFrustumTestSphere(ms_pCamera, &sphere) != rwSPHEREOUTSIDE; +} + +bool +CVisibilityPlugins::VehicleVisibilityCB(RpClump *clump) +{ + if (GetDistanceSquaredFromCamera(RpClumpGetFrame(clump)) <= ms_vehicleLod1Dist) + return FrustumSphereCB(clump); + return false; +} + +bool +CVisibilityPlugins::VehicleVisibilityCB_BigVehicle(RpClump *clump) +{ + return FrustumSphereCB(clump); +} + + + + +// +// RW Plugins +// + +enum +{ + ID_VISIBILITYATOMIC = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x00), + ID_VISIBILITYCLUMP = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x01), + ID_VISIBILITYFRAME = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x02), +}; + +bool +CVisibilityPlugins::PluginAttach(void) +{ + ms_atomicPluginOffset = RpAtomicRegisterPlugin(sizeof(AtomicExt), + ID_VISIBILITYATOMIC, + AtomicConstructor, AtomicDestructor, AtomicCopyConstructor); + + ms_framePluginOffset = RwFrameRegisterPlugin(sizeof(FrameExt), + ID_VISIBILITYFRAME, + FrameConstructor, FrameDestructor, FrameCopyConstructor); + + ms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt), + ID_VISIBILITYCLUMP, + ClumpConstructor, ClumpDestructor, ClumpCopyConstructor); + return ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1; +} + +#define ATOMICEXT(o) (RWPLUGINOFFSET(AtomicExt, o, ms_atomicPluginOffset)) +#define FRAMEEXT(o) (RWPLUGINOFFSET(FrameExt, o, ms_framePluginOffset)) +#define CLUMPEXT(o) (RWPLUGINOFFSET(ClumpExt, o, ms_clumpPluginOffset)) + +// +// Atomic +// + +void* +CVisibilityPlugins::AtomicConstructor(void *object, int32, int32) +{ + ATOMICEXT(object)->modelInfo = nil; + return object; +} + +void* +CVisibilityPlugins::AtomicDestructor(void *object, int32, int32) +{ + return object; +} + +void* +CVisibilityPlugins::AtomicCopyConstructor(void *dst, const void *src, int32, int32) +{ + *ATOMICEXT(dst) = *ATOMICEXT(src); + return dst; +} + +void +CVisibilityPlugins::SetAtomicModelInfo(RpAtomic *atomic, + CSimpleModelInfo *modelInfo) +{ + AtomicExt *ext = ATOMICEXT(atomic); + ext->modelInfo = modelInfo; + switch(modelInfo->m_type) + case MITYPE_SIMPLE: + case MITYPE_TIME: + if(modelInfo->m_normalCull) + SetAtomicRenderCallback(atomic, RenderObjNormalAtomic); +} + +CSimpleModelInfo* +CVisibilityPlugins::GetAtomicModelInfo(RpAtomic *atomic) +{ + return ATOMICEXT(atomic)->modelInfo; +} + +void +CVisibilityPlugins::SetAtomicFlag(RpAtomic *atomic, int f) +{ + ATOMICEXT(atomic)->flags |= f; +} + +void +CVisibilityPlugins::ClearAtomicFlag(RpAtomic *atomic, int f) +{ + ATOMICEXT(atomic)->flags &= ~f; +} + +int +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 + RpAtomicSetRenderCallBack(atomic, cb); +} + +// +// Frame +// + +void* +CVisibilityPlugins::FrameConstructor(void *object, int32, int32) +{ + FRAMEEXT(object)->id = 0; + return object; +} + +void* +CVisibilityPlugins::FrameDestructor(void *object, int32, int32) +{ + return object; +} + +void* +CVisibilityPlugins::FrameCopyConstructor(void *dst, const void *src, int32, int32) +{ + *FRAMEEXT(dst) = *FRAMEEXT(src); + return dst; +} + +void +CVisibilityPlugins::SetFrameHierarchyId(RwFrame *frame, int32 id) +{ + FRAMEEXT(frame)->id = id; +} + +int32 +CVisibilityPlugins::GetFrameHierarchyId(RwFrame *frame) +{ + return FRAMEEXT(frame)->id; +} + + +// +// Clump +// + +void* +CVisibilityPlugins::ClumpConstructor(void *object, int32, int32) +{ + ClumpExt *ext = CLUMPEXT(object); + ext->visibilityCB = DefaultVisibilityCB; + ext->alpha = 0xFF; + return object; +} + +void* +CVisibilityPlugins::ClumpDestructor(void *object, int32, int32) +{ + return object; +} + +void* +CVisibilityPlugins::ClumpCopyConstructor(void *dst, const void *src, int32, int32) +{ + CLUMPEXT(dst)->visibilityCB = CLUMPEXT(src)->visibilityCB; + return dst; +} + +void +CVisibilityPlugins::SetClumpModelInfo(RpClump *clump, CClumpModelInfo *modelInfo) +{ + CVehicleModelInfo *vmi; + SetFrameHierarchyId(RpClumpGetFrame(clump), (int32)modelInfo); + + // Unused + switch(modelInfo->m_type){ + // ignore MLO + case MITYPE_VEHICLE: + vmi = (CVehicleModelInfo*)modelInfo; + if(vmi->m_vehicleType == VEHICLE_TYPE_TRAIN || + vmi->m_vehicleType == VEHICLE_TYPE_HELI || + vmi->m_vehicleType == VEHICLE_TYPE_PLANE) + CLUMPEXT(clump)->visibilityCB = VehicleVisibilityCB_BigVehicle; + else + CLUMPEXT(clump)->visibilityCB = VehicleVisibilityCB; + break; + } +} + +void +CVisibilityPlugins::SetClumpAlpha(RpClump *clump, int alpha) +{ + CLUMPEXT(clump)->alpha = alpha; +} + +int +CVisibilityPlugins::GetClumpAlpha(RpClump *clump) +{ + return CLUMPEXT(clump)->alpha; +} + + +STARTPATCHES + InjectHook(0x527E50, CVisibilityPlugins::Initialise, PATCH_JUMP); + InjectHook(0x527EA0, CVisibilityPlugins::Shutdown, PATCH_JUMP); + InjectHook(0x528F90, CVisibilityPlugins::InitAlphaEntityList, PATCH_JUMP); + InjectHook(0x528FF0, CVisibilityPlugins::InsertEntityIntoSortedList, PATCH_JUMP); + InjectHook(0x528F80, CVisibilityPlugins::InitAlphaAtomicList, PATCH_JUMP); + InjectHook(0x528FA0, CVisibilityPlugins::InsertAtomicIntoSortedList, PATCH_JUMP); + InjectHook(0x528C50, CVisibilityPlugins::SetRenderWareCamera, PATCH_JUMP); + + InjectHook(0x527F60, SetAlphaCB, PATCH_JUMP); + InjectHook(0x529040, CVisibilityPlugins::RenderAlphaAtomics, PATCH_JUMP); + InjectHook(0x529070, CVisibilityPlugins::RenderFadingEntities, PATCH_JUMP); + + InjectHook(0x527F70, CVisibilityPlugins::RenderWheelAtomicCB, PATCH_JUMP); + InjectHook(0x528000, CVisibilityPlugins::RenderObjNormalAtomic, PATCH_JUMP); + InjectHook(0x5280B0, CVisibilityPlugins::RenderAlphaAtomic, PATCH_JUMP); + InjectHook(0x528100, CVisibilityPlugins::RenderFadingAtomic, PATCH_JUMP); + + InjectHook(0x5283E0, CVisibilityPlugins::RenderVehicleHiDetailCB, PATCH_JUMP); + InjectHook(0x5284B0, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB, PATCH_JUMP); + InjectHook(0x5288A0, CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle, PATCH_JUMP); + InjectHook(0x528A10, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle, PATCH_JUMP); + InjectHook(0x528AD0, CVisibilityPlugins::RenderVehicleHiDetailCB_Boat, PATCH_JUMP); + InjectHook(0x5287F0, CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle, PATCH_JUMP); + InjectHook(0x528940, CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle, PATCH_JUMP); + InjectHook(0x528240, CVisibilityPlugins::RenderVehicleReallyLowDetailCB, PATCH_JUMP); + InjectHook(0x5287B0, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle, PATCH_JUMP); + InjectHook(0x5285D0, CVisibilityPlugins::RenderTrainHiDetailCB, PATCH_JUMP); + InjectHook(0x5286A0, CVisibilityPlugins::RenderTrainHiDetailAlphaCB, PATCH_JUMP); + + InjectHook(0x528BC0, CVisibilityPlugins::RenderPedHiDetailCB, PATCH_JUMP); + InjectHook(0x528B60, CVisibilityPlugins::RenderPedLowDetailCB, PATCH_JUMP); + + + InjectHook(0x527DC0, CVisibilityPlugins::PluginAttach, PATCH_JUMP); + + InjectHook(0x527EC0, CVisibilityPlugins::SetAtomicModelInfo, PATCH_JUMP); + InjectHook(0x527F00, CVisibilityPlugins::GetAtomicModelInfo, PATCH_JUMP); + InjectHook(0x527F10, CVisibilityPlugins::SetAtomicFlag, PATCH_JUMP); + InjectHook(0x527F30, CVisibilityPlugins::ClearAtomicFlag, PATCH_JUMP); + InjectHook(0x527F50, CVisibilityPlugins::GetAtomicId, PATCH_JUMP); + InjectHook(0x528C20, CVisibilityPlugins::SetAtomicRenderCallback, PATCH_JUMP); + + InjectHook(0x528D60, CVisibilityPlugins::SetFrameHierarchyId, PATCH_JUMP); + InjectHook(0x528D80, CVisibilityPlugins::GetFrameHierarchyId, PATCH_JUMP); + + InjectHook(0x528ED0, CVisibilityPlugins::SetClumpModelInfo, PATCH_JUMP); + InjectHook(0x528F50, CVisibilityPlugins::SetClumpAlpha, PATCH_JUMP); + InjectHook(0x528F70, CVisibilityPlugins::GetClumpAlpha, PATCH_JUMP); + + + InjectHook(0x529120, CVisibilityPlugins::GetDistanceSquaredFromCamera, PATCH_JUMP); + InjectHook(0x5282A0, CVisibilityPlugins::GetDotProductWithCameraVector, PATCH_JUMP); +ENDPATCHES |