#define RPWORLDSECTORMAKEOBJID(meshHeader) \ (((RwUInt16)((meshHeader)->serialNum)) | \ (((RwUInt8)(RpWorldGetFlags((RpWorld *)RWSRCGLOBAL(curWorld)) & WORLDRENDERTYPEMASK)) << 16)) #define RPWORLDSECTOROBJIDGETSERIALNUM(objID) ((RwUInt16)(objID)) #define RPWORLDSECTOROBJIDGETFLAGS(objID) ((RwUInt8)((objID) >> 16)) /* TRUE if the pointer points to an RpWorldSector, FALSE if an RpAtomic */ #define RPWORLDSECTORVERIFY(_object) (*(RwUInt8 *)(_object) == (RwUInt8)-1) /* Used as RpWorldSectorPS2AllGetMeshHeaderMeshCache (function in debug) */ #define RpWorldSectorPS2AllGetMeshHeaderMeshCacheMacro(_sector, _ps2AllPipeData) \ MACRO_START \ { \ RxPS2AllPipeData *_p2apd = (_ps2AllPipeData); \ RpWorldSector *_sctr = (_sector); \ \ PS2ALLMACROASSERT(NULL != _p2apd); \ PS2ALLMACROASSERT(RPWORLDSECTORVERIFY(_p2apd->sourceObject)); \ PS2ALLMACROASSERT(NULL != _sctr); \ PS2ALLMACROASSERT(_sctr == (RpWorldSector *)(_p2apd->sourceObject)); \ \ _p2apd->meshHeader = _sctr->mesh; \ PS2ALLMACROASSERT(NULL != _p2apd->meshHeader); \ \ /* Get the RwMeshCache from the sector */ \ _p2apd->meshCache = rpWorldSectorGetMeshCache(_sctr, _p2apd->meshHeader->numMeshes); \ PS2ALLMACROASSERT(NULL != _p2apd->meshCache); \ } \ MACRO_STOP /* Used as RpPS2AllWorldSectorGatherObjMetrics (function in debug) */ #if (defined(RWMETRICS)) #define RpWorldSectorPS2AllGatherObjMetricsMacro(_sector) \ MACRO_START \ { \ RpWorldSector *_sctr = (_sector); \ \ PS2ALLMACROASSERT(NULL != _sctr); \ PS2ALLMACROASSERT(RPWORLDSECTORVERIFY(_sctr)); \ \ /* Update our metrics statistics */ \ RWSRCGLOBAL(metrics)->numVertices += RpWorldSectorGetNumVertices(_sctr); \ RWSRCGLOBAL(metrics)->numTriangles += RpWorldSectorGetNumPolygons(_sctr); \ } \ MACRO_STOP #else /* (defined(RWMETRICS)) */ #define RpWorldSectorPS2AllGatherObjMetricsMacro(_sector) /* No op */ #endif /* (defined(RWMETRICS)) */ /* Used as RpWorldSectorPS2AllObjInstanceTest (function in debug) */ #define RpWorldSectorPS2AllObjInstanceTestMacro(_ps2AllPipeData) \ MACRO_START \ { \ RxPS2AllPipeData *_p2apd = (_ps2AllPipeData); \ \ PS2ALLMACROASSERT(NULL != _p2apd); \ PS2ALLMACROASSERT(RPWORLDSECTORVERIFY(_p2apd->sourceObject)); \ PS2ALLMACROASSERT(NULL != RWSRCGLOBAL(curWorld)); \ \ if ( !(rpWORLDNATIVE & RpWorldGetFlags((RpWorld *)RWSRCGLOBAL(curWorld))) ) \ { \ RwResEntry *_rsnt; \ \ /* The per-mesh identifier will be identical for all meshes */ \ /* in an object. Regardless, we allow per-material reinstance */ \ /* tests to override/replace the per-object ones done here */ \ \ /* Make a new object identifier */ \ _p2apd->objIdentifier = RPWORLDSECTORMAKEOBJID(_p2apd->meshHeader); \ \ /* Remove DONTINSTANCE so meshes are free to do their tests */ \ /* (and we don't skip instancing if (resEntry == NULL)) */ \ _p2apd->objInstance = (RxInstanceFlags) \ (_p2apd->objInstance & ~rxINSTANCEDONTINSTANCE); \ \ /* The same object identifier goes into every mesh's resEntry, so just grab the first one */ \ _rsnt = *rwMeshCacheGetEntryRef(_p2apd->meshCache, 0); \ if (NULL != _rsnt) \ { \ /* Test our new identifier against the old one to see how much reinstancing needs doing */ \ rwPS2AllResEntryHeader *ps2AllResHeader = \ RWPS2ALLRESENTRYHEADERFROMRESENTRY(_rsnt); \ \ if (_p2apd->objIdentifier != ps2AllResHeader->objIdentifier) \ { \ if (RPWORLDSECTOROBJIDGETFLAGS(_p2apd->objIdentifier) != \ RPWORLDSECTOROBJIDGETFLAGS(ps2AllResHeader->objIdentifier)) \ { \ /* Changing object flags causes a full reinstance */ \ _p2apd->objInstance = (RxInstanceFlags) \ (_p2apd->objInstance | rxINSTANCEFULLINSTANCE); \ } \ else \ { \ /* Only a congruent reinstance for other changes (serialNum atm) */ \ _p2apd->objInstance = (RxInstanceFlags) \ (_p2apd->objInstance | rxINSTANCECONGRUENTINSTANCE); \ REDEBUGPrintf(("objIdentifier change caused congruent reinstancing: (%x)\n", \ _p2apd->objIdentifier)); \ } \ } \ /* Currently in-place instancing won't occur because */ \ /* because we don't expect/support editing of sector data */ \ } \ else \ { \ /* Reinstancing will always occur if (resEntry == NULL) */ \ } \ } \ else \ { \ /* Make sure this "persistent instance data" malarky's not just a bluff. */ \ PS2ALLMACROASSERT((RwResEntry *)NULL != \ *rwMeshCacheGetEntryRef(_p2apd->meshCache, 0)); \ } \ } \ MACRO_STOP /* Used as RpWorldSectorPS2AllTransformSetup (function in debug) */ #define RpWorldSectorPS2AllTransformSetupMacro(_transform) \ MACRO_START \ { \ RwMatrix **_tnfm = (_transform); \ \ PS2ALLMACROASSERT(NULL != _tnfm); \ \ /* We just cache the camera matrix */ \ *_tnfm = &(((RwCamera *)RWSRCGLOBAL(curCamera))->viewMatrix); \ PS2ALLMACROASSERT(RWMATRIXALIGNMENT(*_tnfm)); \ } \ MACRO_STOP /* Used as RpWorldSectorPS2AllFrustumTest (function in debug) */ #define RpWorldSectorPS2AllFrustumTestMacro(_sector, _inFrustum) \ MACRO_START \ { \ RpWorldSector *_sctr = (_sector); \ RwFrustumTestResult *_infm = (_inFrustum); \ \ RwFrustumPlane *_frustPlane; \ RwUInt32 _numPlanes; \ \ PS2ALLMACROASSERT(NULL != _sctr); \ PS2ALLMACROASSERT(RPWORLDSECTORVERIFY(_sctr)); \ PS2ALLMACROASSERT(NULL != _infm); \ \ /* Assume innocent until proven guilty */ \ *_infm = rwSPHEREINSIDE; \ \ _frustPlane = CAMERAEXTFROMCAMERA(RWSRCGLOBAL(curCamera))->largeFrustumPlanes; \ \ _numPlanes = 6; \ while (_numPlanes--) \ { \ RwV3d vCorner; \ RwReal dot; \ \ /* Check against plane */ \ vCorner.x = ((RwV3d *)&_sctr->tightBoundingBox)[1 - _frustPlane->closestX].x; \ vCorner.y = ((RwV3d *)&_sctr->tightBoundingBox)[1 - _frustPlane->closestY].y; \ vCorner.z = ((RwV3d *)&_sctr->tightBoundingBox)[1 - _frustPlane->closestZ].z; \ dot = RwV3dDotProduct(&vCorner, &_frustPlane->plane.normal); \ dot -= _frustPlane->plane.distance; \ \ /* We only need to detect a boundary case, we should never be wholly outside here. */ \ if (dot > 0) \ { \ /* Its outside the plane */ \ *_infm = rwSPHEREBOUNDARY; \ break; \ } \ _frustPlane++; \ } \ } \ MACRO_STOP /* Used as RpWorldSectorPS2AllMatModulateSetup (function in debug) */ #define RpWorldSectorPS2AllMatModulateSetupMacro(_ps2AllPipeData) \ MACRO_START \ { \ PS2ALLMACROASSERT(NULL != RWSRCGLOBAL(curWorld)); \ (_ps2AllPipeData)->matModulate = \ (RpWorldGetFlags((RpWorld *) RWSRCGLOBAL(curWorld)) & \ rpWORLDMODULATEMATERIALCOLOR) ? TRUE : FALSE; \ } \ MACRO_STOP /* Used as RpWorldSectorPS2AllLightingSetup (function in debug) */ #define RpWorldSectorPS2AllLightingSetupMacro(_ps2AllPipeData) \ MACRO_START \ { \ RxPS2AllPipeData *_p2apd = (_ps2AllPipeData); \ RpWorldSector *_sctr; \ RpWorld *_wrld = (RpWorld *)RWSRCGLOBAL(curWorld); \ \ PS2ALLMACROASSERT(NULL != _p2apd); \ _sctr = (RpWorldSector *)_p2apd->sourceObject; \ PS2ALLMACROASSERT(NULL != _sctr); \ PS2ALLMACROASSERT(RPWORLDSECTORVERIFY(_sctr)); \ /* If we are rendering atomic sectors we must have a world! */ \ PS2ALLMACROASSERT(NULL != _wrld); \ \ if (rpWORLDLIGHT & RpWorldGetFlags(_wrld)) \ { \ /* Ideally I'd like to use the code in baworld.c but */ \ /* the function _rpWorldSectorLight isn't exposed */ \ rpWorldForAllGlobalLights(_rpWorldSectorPS2AllDoApplyLight, NULL); \ rpWorldSectorForAllLocalLights(_sctr, _rpWorldSectorPS2AllDoApplyLight, NULL); \ } \ } \ MACRO_STOP /* Used as RpWorldSectorPS2AllResEntryAlloc (function in debug) */ #define RpWorldSectorPS2AllResEntryAllocMacro(_ps2AllPipeData, _repEntry, _size, _destroyCallBack) \ MACRO_START \ { \ RxPS2AllPipeData *_p2apd = (_ps2AllPipeData); \ RwResEntry **_rsny = (_repEntry); \ RwResEntryDestroyNotify _dycb = (_destroyCallBack); \ RwUInt32 _cyze = (_size); \ RpWorld *_wrld; \ \ PS2ALLMACROASSERT(NULL != _p2apd); \ PS2ALLMACROASSERT(RPWORLDSECTORVERIFY((RpWorldSector *)_p2apd->sourceObject)); \ PS2ALLMACROASSERT(NULL != _rsny); \ \ _wrld = (RpWorld *)RWSRCGLOBAL(curWorld); \ PS2ALLMACROASSERT(NULL != _wrld); \ if (rpWORLDNATIVEINSTANCE & RpWorldGetFlags(_wrld)) \ { \ RpWorldSector *_ws; \ \ _ws = (RpWorldSector *)(_p2apd->sourceObject); \ PS2ALLMACROASSERT(NULL != _ws); \ \ /* Allocate the memory */ \ *_rsny = (RwResEntry *)RwMalloc(sizeof(RwResEntry) + _cyze); \ PS2ALLMACROASSERT(NULL != (*_rsny)); \ \ /* We have an entry */ \ (*_rsny)->link.next = (RwLLLink *)NULL; \ (*_rsny)->link.prev = (RwLLLink *)NULL; \ (*_rsny)->owner = (void *)_ws; \ (*_rsny)->size = _cyze; \ (*_rsny)->ownerRef = _rsny; \ (*_rsny)->destroyNotify = _dycb; \ } \ else \ { \ *_rsny = RwResourcesAllocateResEntry( \ (_ps2AllPipeData)->sourceObject, _rsny, _cyze, _dycb); \ } \ } \ MACRO_STOP #if (defined(__cplusplus)) extern "C" { #endif /* (defined(__cplusplus)) */ /* Default RW callbacks */ extern RwBool RpWorldSectorPS2AllObjectSetupCallBack( RxPS2AllPipeData *ps2AllPipeData, RwMatrix **transform); /* Standard instance func for sectors */ extern RwBool RpWorldSectorPS2AllInstance(RxPS2AllPipeData *ps2AllPipeData); /* Callbacks used by the standard lighting func */ extern RpLight * _rpWorldSectorPS2AllDoApplyLight(RpLight *light, void *pData); /* Callback components, for use in user callbacks */ /* ObjectSetupCB */ extern void RpWorldSectorPS2AllGetMeshHeaderMeshCacheFunc( RpWorldSector *sector, RxPS2AllPipeData *ps2AllPipeData); extern void RpWorldSectorPS2AllGatherObjMetricsFunc( RpWorldSector *sector); extern void RpWorldSectorPS2AllObjInstanceTestFunc( RxPS2AllPipeData *ps2AllPipeData); extern void RpWorldSectorPS2AllTransformSetupFunc( RwMatrix **transform); extern void RpWorldSectorPS2AllFrustumTestFunc( RpWorldSector *sector, RwFrustumTestResult *inFrustum); extern void RpWorldSectorPS2AllMatModulateSetupFunc( RxPS2AllPipeData *ps2AllPipeData); extern void RpWorldSectorPS2AllLightingSetupFunc( RxPS2AllPipeData *ps2AllPipeData); extern void RpWorldSectorPS2AllResEntryAllocFunc( RxPS2AllPipeData *ps2AllPipeData, RwResEntry **repEntry, RwUInt32 size, RwResEntryDestroyNotify destroyCallBack); #if (defined(__cplusplus)) } #endif /* (defined(__cplusplus)) */ #if (defined(RWDEBUG)) #define RpWorldSectorPS2AllGetMeshHeaderMeshCache RpWorldSectorPS2AllGetMeshHeaderMeshCacheFunc #define RpWorldSectorPS2AllGatherObjMetrics RpWorldSectorPS2AllGatherObjMetricsFunc #define RpWorldSectorPS2AllObjInstanceTest RpWorldSectorPS2AllObjInstanceTestFunc #define RpWorldSectorPS2AllTransformSetup RpWorldSectorPS2AllTransformSetupFunc #define RpWorldSectorPS2AllFrustumTest RpWorldSectorPS2AllFrustumTestFunc #define RpWorldSectorPS2AllMatModulateSetup RpWorldSectorPS2AllMatModulateSetupFunc #define RpWorldSectorPS2AllLightingSetup RpWorldSectorPS2AllLightingSetupFunc #define RpWorldSectorPS2AllResEntryAlloc RpWorldSectorPS2AllResEntryAllocFunc #else /* (defined(RWDEBUG)) */ #define RpWorldSectorPS2AllGetMeshHeaderMeshCache RpWorldSectorPS2AllGetMeshHeaderMeshCacheMacro #define RpWorldSectorPS2AllGatherObjMetrics RpWorldSectorPS2AllGatherObjMetricsMacro #define RpWorldSectorPS2AllObjInstanceTest RpWorldSectorPS2AllObjInstanceTestMacro #define RpWorldSectorPS2AllTransformSetup RpWorldSectorPS2AllTransformSetupMacro #define RpWorldSectorPS2AllFrustumTest RpWorldSectorPS2AllFrustumTestMacro #define RpWorldSectorPS2AllMatModulateSetup RpWorldSectorPS2AllMatModulateSetupMacro #define RpWorldSectorPS2AllLightingSetup RpWorldSectorPS2AllLightingSetupMacro #define RpWorldSectorPS2AllResEntryAlloc RpWorldSectorPS2AllResEntryAllocMacro #endif /* (defined(RWDEBUG)) */