From f03b4eec4c37eab75a5bd639279cfcc615105b01 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 23 Apr 2020 22:25:18 +0200 Subject: implemented skinned peds, no cutscene hands yet --- src/rw/RwHelper.cpp | 179 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 171 insertions(+), 8 deletions(-) (limited to 'src/rw/RwHelper.cpp') diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index acf811ad..5aa4475f 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -3,16 +3,15 @@ #include "Timecycle.h" #include "skeleton.h" -#if defined(RWLIBS) && !defined(FINAL) +#include "Debug.h" +#ifndef FINAL #include "rtcharse.h" -#pragma comment( lib, "rtcharse.lib" ) - RtCharset *debugCharset; #endif void CreateDebugFont() { -#if defined(RWLIBS) && !defined(FINAL) +#ifndef FINAL RwRGBA color = { 255, 255, 128, 255 }; RwRGBA colorbg = { 0, 0, 0, 0 }; RtCharsetOpen(); @@ -22,7 +21,7 @@ void CreateDebugFont() void DestroyDebugFont() { -#if defined(RWLIBS) && !defined(FINAL) +#ifndef FINAL RtCharsetDestroy(debugCharset); RtCharsetClose(); #endif @@ -30,14 +29,14 @@ void DestroyDebugFont() void ObrsPrintfString(const char *str, short x, short y) { -#if defined(RWLIBS) && !defined(FINAL) - RtCharsetPrintBuffered(debugCharset, str, x, y, true); +#ifndef FINAL + RtCharsetPrintBuffered(debugCharset, str, x*8, y*16, true); #endif } void FlushObrsPrintfs() { -#if defined(RWLIBS) && !defined(FINAL) +#ifndef FINAL RtCharsetBufferFlush(); #endif } @@ -168,6 +167,170 @@ 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(atomic->geometry)) + *pAtomic = atomic; // we could just return nil here directly... + return atomic; +} + +RpAtomic* +IsClumpSkinned(RpClump *clump) +{ + RpAtomic *atomic = nil; + RpClumpForAllAtomics(clump, isSkinnedCb, &atomic); + return atomic; +} + +static RpAtomic* +GetAnimHierarchyCallback(RpAtomic *atomic, void *data) +{ + *(RpHAnimHierarchy**)data = RpSkinAtomicGetHAnimHierarchy(atomic); + return nil; +} + +RpHAnimHierarchy* +GetAnimHierarchyFromSkinClump(RpClump *clump) +{ + RpHAnimHierarchy *hier = nil; + RpClumpForAllAtomics(clump, GetAnimHierarchyCallback, &hier); + return hier; +} + +static RwFrame* +GetAnimHierarchyFromClumpCB(RwFrame *frame, void *data) +{ + RpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame); + if(hier){ + *(RpHAnimHierarchy**)data = hier; + return nil; + } + RwFrameForAllChildren(frame, GetAnimHierarchyFromClumpCB, data); + return frame; +} + +RpHAnimHierarchy* +GetAnimHierarchyFromClump(RpClump *clump) +{ + RpHAnimHierarchy *hier = nil; + RwFrameForAllChildren(RpClumpGetFrame(clump), GetAnimHierarchyFromClumpCB, &hier); + 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) +{ + int i, parent; + RpAtomic *atomic; + RpSkin *skin; + RpHAnimHierarchy *hier; + int numBones; + RwMatrix m, invmat; + int stack[32]; + int sp; + + if(boneTable == nil) + return; + +// atomic = GetFirstAtomic(clump); // mobile, also VC + atomic = IsClumpSkinned(clump); // xbox, seems safer + assert(atomic); + skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)); + assert(skin); + hier = GetAnimHierarchyFromSkinClump(clump); + assert(hier); + boneTable[0].x = 0.0f; + boneTable[0].y = 0.0f; + boneTable[0].z = 0.0f; + numBones = RpSkinGetNumBones(skin); + parent = 0; + sp = 0; +#ifdef FIX_BUGS + stack[0] = 0; // i think this is ok +#endif + for(i = 1; i < numBones; i++){ + RwMatrixCopy(&m, &RpSkinGetSkinToBoneMatrices(skin)[i]); + RwMatrixInvert(&invmat, &m); + const RwMatrix *x = RpSkinGetSkinToBoneMatrices(skin); + RwV3dTransformPoints(&boneTable[i], &invmat.pos, 1, &x[parent]); + if(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX) + stack[++sp] = parent; + if(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX) + parent = stack[sp--]; + else + parent = i; + assert(parent >= 0 && parent < numBones); + } +} + +RpHAnimAnimation* +HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier) +{ + int i; +#ifdef FIX_BUGS + int numNodes = hier->numNodes*2; // you're supposed to have at least two KFs per node +#else + int numNodes = hier->numNodes; +#endif + RpHAnimAnimation *anim = RpHAnimAnimationCreate(rpHANIMSTDKEYFRAMETYPEID, numNodes, 0, 0.0f); + if(anim == nil) + return nil; + RpHAnimStdKeyFrame *frame = (RpHAnimStdKeyFrame*)HANIMFRAMES(anim); + for(i = 0; i < numNodes; i++){ + frame->q.real = 1.0f; + frame->q.imag.x = frame->q.imag.y = frame->q.imag.z = 0.0f; + frame->t.x = frame->t.y = frame->t.z = 0.0f; + frame->time = 0.0f; + frame->prevFrame = nil; + frame++; + } + return anim; +} + +void +RenderSkeleton(RpHAnimHierarchy *hier) +{ + int i; + int sp; + int stack[32]; + int par; + CVector p1, p2; + int numNodes = hier->numNodes; + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + p1 = mats[0].pos; + + par = 0; + sp = 0; + stack[sp++] = par; + for(i = 1; i < numNodes; i++){ + p1 = mats[par].pos; + p2 = mats[i].pos; + CDebug::AddLine(p1, p2, 0xFFFFFFFF, 0xFFFFFFFF); + if(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX) + stack[sp++] = par; + par = i; + if(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX) + par = stack[--sp]; + } +} +#endif + void CameraSize(RwCamera * camera, RwRect * rect, RwReal viewWindow, RwReal aspectRatio) -- cgit v1.2.3