summaryrefslogtreecommitdiffstats
path: root/src/rw/RwHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rw/RwHelper.cpp')
-rw-r--r--src/rw/RwHelper.cpp241
1 files changed, 206 insertions, 35 deletions
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index f568532a..9633e56c 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -16,6 +16,7 @@ bool gPS2alphaTest = true;
#else
bool gPS2alphaTest = false;
#endif
+bool gBackfaceCulling;
#ifndef FINAL
static bool charsetOpen;
@@ -111,7 +112,7 @@ DefinedState(void)
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEALPHAPRIMITIVEBUFFER, (void*)FALSE);
+ //RwRenderStateSet(rwRENDERSTATEALPHAPRIMITIVEBUFFER, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEBORDERCOLOR, (void*)RWRGBALONG(0, 0, 0, 255));
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEFOGCOLOR,
@@ -131,6 +132,15 @@ DefinedState(void)
#endif
}
+void
+SetCullMode(uint32 mode)
+{
+ if(gBackfaceCulling)
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)mode);
+ else
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
+}
+
RwFrame*
GetFirstFrameCallback(RwFrame *child, void *data)
{
@@ -199,24 +209,11 @@ GetFirstTexture(RwTexDictionary *txd)
return tex;
}
-#ifdef PED_SKIN
-static RpAtomic*
-isSkinnedCb(RpAtomic *atomic, void *data)
-{
- RpAtomic **pAtomic = (RpAtomic**)data;
- if(*pAtomic)
- return nil; // already found one
- if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
- *pAtomic = atomic; // we could just return nil here directly...
- return atomic;
-}
-
-RpAtomic*
+bool
IsClumpSkinned(RpClump *clump)
{
- RpAtomic *atomic = nil;
- RpClumpForAllAtomics(clump, isSkinnedCb, &atomic);
- return atomic;
+ RpAtomic *atomic = GetFirstAtomic(clump);
+ return atomic ? RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)) : nil;
}
static RpAtomic*
@@ -254,17 +251,6 @@ GetAnimHierarchyFromClump(RpClump *clump)
return hier;
}
-RwFrame*
-GetHierarchyFromChildNodesCB(RwFrame *frame, void *data)
-{
- RpHAnimHierarchy **pHier = (RpHAnimHierarchy**)data;
- RpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame);
- if(hier == nil)
- RwFrameForAllChildren(frame, GetHierarchyFromChildNodesCB, &hier);
- *pHier = hier;
- return nil;
-}
-
void
SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable)
{
@@ -280,8 +266,7 @@ SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable)
if(boneTable == nil)
return;
-// atomic = GetFirstAtomic(clump); // mobile, also VC
- atomic = IsClumpSkinned(clump); // xbox, seems safer
+ atomic = GetFirstAtomic(clump); // mobile, also VC
assert(atomic);
skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic));
assert(skin);
@@ -352,9 +337,9 @@ AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data)
hier->interpolator->currentAnim = nil;
}
#else
- if(hier && hier->pCurrentAnim){
- RpHAnimAnimationDestroy(hier->pCurrentAnim);
- hier->pCurrentAnim = nil;
+ if(hier && hier->currentAnim){
+ RpHAnimAnimationDestroy(hier->currentAnim->pCurrentAnim);
+ hier->currentAnim = nil;
}
#endif
}
@@ -387,7 +372,125 @@ RenderSkeleton(RpHAnimHierarchy *hier)
par = stack[--sp];
}
}
-#endif
+
+
+RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset)
+{
+ RwIm2DVertex vx[4];
+
+ /*
+ * Render an opaque white 2D quad at the given coordinates and
+ * spanning a whole texture.
+ */
+
+ RwIm2DVertexSetScreenX(&vx[0], x1);
+ RwIm2DVertexSetScreenY(&vx[0], y1);
+ RwIm2DVertexSetScreenZ(&vx[0], z);
+ RwIm2DVertexSetIntRGBA(&vx[0], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);
+ RwIm2DVertexSetU(&vx[0], uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[0], uvOffset, recipCamZ);
+
+ RwIm2DVertexSetScreenX(&vx[1], x1);
+ RwIm2DVertexSetScreenY(&vx[1], y2);
+ RwIm2DVertexSetScreenZ(&vx[1], z);
+ RwIm2DVertexSetIntRGBA(&vx[1], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);
+ RwIm2DVertexSetU(&vx[1], uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[1], 1.0f + uvOffset, recipCamZ);
+
+ RwIm2DVertexSetScreenX(&vx[2], x2);
+ RwIm2DVertexSetScreenY(&vx[2], y1);
+ RwIm2DVertexSetScreenZ(&vx[2], z);
+ RwIm2DVertexSetIntRGBA(&vx[2], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);
+ RwIm2DVertexSetU(&vx[2], 1.0f + uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[2], uvOffset, recipCamZ);
+
+ RwIm2DVertexSetScreenX(&vx[3], x2);
+ RwIm2DVertexSetScreenY(&vx[3], y2);
+ RwIm2DVertexSetScreenZ(&vx[3], z);
+ RwIm2DVertexSetIntRGBA(&vx[3], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);
+ RwIm2DVertexSetU(&vx[3], 1.0f + uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[3], 1.0f + uvOffset, recipCamZ);
+
+ RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
+
+ return TRUE;
+}
+
+bool b_cbsUseLTM = true;
+
+RpAtomic *cbsCalcMeanBSphereRadiusCB(RpAtomic *atomic, void *data)
+{
+ RwV3d atomicPos;
+
+ if ( b_cbsUseLTM )
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump)));
+ else
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump)));
+
+ RwV3d temp;
+ RwV3dSub(&temp, &atomicPos, &((RwSphere *)data)->center);
+ RwReal radius = RwV3dLength(&temp) + RpAtomicGetBoundingSphere(atomic)->radius;
+
+ if ( ((RwSphere *)data)->radius < radius )
+ ((RwSphere *)data)->radius = radius;
+
+ return atomic;
+}
+
+RpAtomic *cbsCalcMeanBSphereCenterCB(RpAtomic *atomic, void *data)
+{
+ RwV3d atomicPos;
+
+ if ( b_cbsUseLTM )
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump)));
+ else
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump)));
+
+ RwV3dAdd(&((RwSphere *)data)->center, &((RwSphere *)data)->center, &atomicPos);
+
+ return atomic;
+}
+
+RpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM)
+{
+ RwMatrix matrix;
+ RwSphere result = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ b_cbsUseLTM = useLTM;
+
+ if ( clump == nil || sphere == nil )
+ return nil;
+
+ sphere->radius = 0.0f;
+ sphere->center.x = 0.0f;
+ sphere->center.y = 0.0f;
+ sphere->center.z = 0.0f;
+
+ RwInt32 numAtomics = RpClumpGetNumAtomics(clump);
+ if ( numAtomics < 1.0f )
+ return nil;
+
+ RpClumpForAllAtomics(clump, cbsCalcMeanBSphereCenterCB, &result);
+
+ RwV3dScale(&result.center, &result.center, 1.0f/numAtomics);
+
+ RpClumpForAllAtomics(clump, cbsCalcMeanBSphereRadiusCB, &result);
+
+ if ( b_cbsUseLTM )
+ RwMatrixInvert(&matrix, RwFrameGetLTM(RpClumpGetFrame(clump)));
+ else
+ RwMatrixInvert(&matrix, RwFrameGetMatrix(RpClumpGetFrame(clump)));
+
+ RwV3dTransformPoints(&result.center, &result.center, 1, &matrix);
+
+ *sphere = result;
+
+ return clump;
+}
void
CameraSize(RwCamera * camera, RwRect * rect,
@@ -431,6 +534,7 @@ CameraSize(RwCamera * camera, RwRect * rect,
}
}
+ // BUG: game just changes camera raster's sizes, but this is a hack
if (( origSize.w != rect->w ) && ( origSize.h != rect->h ))
{
RwRaster *raster;
@@ -616,6 +720,73 @@ WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); }
WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); }
#endif
+#ifdef LIBRW
+#include <rpmatfx.h>
+#include "VehicleModelInfo.h"
+
+int32
+findPlatform(rw::Atomic *a)
+{
+ rw::Geometry *g = a->geometry;
+ if(g->instData)
+ return g->instData->platform;
+ return 0;
+}
+
+// Game doesn't read atomic extensions so we never get any other than the default pipe,
+// but we need it for uninstancing
+void
+attachPipe(rw::Atomic *atomic)
+{
+ if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
+ atomic->pipeline = rw::skinGlobals.pipelines[rw::platform];
+ else{
+ int fx = rpMATFXEFFECTNULL;
+ RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), CVehicleModelInfo::GetMatFXEffectMaterialCB, &fx);
+ if(fx != rpMATFXEFFECTNULL)
+ RpMatFXAtomicEnableEffects(atomic);
+ }
+}
+
+// Attach pipes for the platform we have native data for so we can uninstance
+void
+switchPipes(rw::Atomic *a, int32 platform)
+{
+ if(a->pipeline && a->pipeline->platform != platform){
+ uint32 plgid = a->pipeline->pluginID;
+ switch(plgid){
+ // assume default pipe won't be attached explicitly
+ case rw::ID_SKIN:
+ a->pipeline = rw::skinGlobals.pipelines[platform];
+ break;
+ case rw::ID_MATFX:
+ a->pipeline = rw::matFXGlobals.pipelines[platform];
+ break;
+ }
+ }
+}
+
+RpAtomic*
+ConvertPlatformAtomic(RpAtomic *atomic, void *data)
+{
+ int32 driver = rw::platform;
+ int32 platform = findPlatform(atomic);
+ if(platform != 0 && platform != driver){
+ attachPipe(atomic); // kludge
+ rw::ObjPipeline *origPipe = atomic->pipeline;
+ rw::platform = platform;
+ switchPipes(atomic, rw::platform);
+ if(atomic->geometry->flags & rw::Geometry::NATIVE)
+ atomic->uninstance();
+ // no ADC in this game
+ //rw::ps2::unconvertADC(atomic->geometry);
+ rw::platform = driver;
+ atomic->pipeline = origPipe;
+ }
+ return atomic;
+}
+#endif
+
#if defined(FIX_BUGS) && defined(GTA_PC)
RwUInt32 saved_alphafunc, saved_alpharef;
@@ -648,4 +819,4 @@ RestoreAlphaTest()
RwD3D8SetRenderState(D3DRS_ALPHAREF, saved_alpharef);
#endif
}
-#endif \ No newline at end of file
+#endif