diff options
Diffstat (limited to 'src/modelinfo')
-rw-r--r-- | src/modelinfo/ClumpModelInfo.cpp | 72 | ||||
-rw-r--r-- | src/modelinfo/PedModelInfo.cpp | 164 | ||||
-rw-r--r-- | src/modelinfo/PedModelInfo.h | 17 |
3 files changed, 243 insertions, 10 deletions
diff --git a/src/modelinfo/ClumpModelInfo.cpp b/src/modelinfo/ClumpModelInfo.cpp index 464bda61..44faf3c5 100644 --- a/src/modelinfo/ClumpModelInfo.cpp +++ b/src/modelinfo/ClumpModelInfo.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "RwHelper.h" #include "General.h" #include "NodeName.h" #include "VisibilityPlugins.h" @@ -15,12 +16,40 @@ CClumpModelInfo::DeleteRwObject(void) } } +#ifdef PED_SKIN +static RpAtomic* +SetHierarchyForSkinAtomic(RpAtomic *atomic, void *data) +{ + RpSkinAtomicSetHAnimHierarchy(atomic, (RpHAnimHierarchy*)data); + return nil; +} +#endif + RwObject* CClumpModelInfo::CreateInstance(void) { - if(m_clump) - return (RwObject*)RpClumpClone(m_clump); - return nil; + if(m_clump == nil) + return nil; + RpClump *clone = RpClumpClone(m_clump); +#ifdef PED_SKIN + if(IsClumpSkinned(clone)){ + RpHAnimHierarchy *hier; + RpHAnimAnimation *anim; + + hier = GetAnimHierarchyFromClump(clone); + assert(hier); + // This seems dangerous as only the first atomic will get a hierarchy + // can we guarantee this if hands and head are also in the clump? + RpClumpForAllAtomics(clone, SetHierarchyForSkinAtomic, hier); + anim = HAnimAnimationCreateForHierarchy(hier); + RpHAnimHierarchySetCurrentAnim(hier, anim); +// RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS)); + // the rest is xbox only: + // RpSkinGetNumBones(RpSkinGeometryGetSkin(RpAtomicGetGeometry(IsClumpSkinned(clone)))); + RpHAnimHierarchyUpdateMatrices(hier); + } +#endif + return (RwObject*)clone; } RwObject* @@ -48,8 +77,45 @@ CClumpModelInfo::SetClump(RpClump *clump) CVisibilityPlugins::SetClumpModelInfo(m_clump, this); AddTexDictionaryRef(); RpClumpForAllAtomics(clump, SetAtomicRendererCB, nil); + + // TODO: also set for player? if(strncmp(GetName(), "playerh", 8) == 0) RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); + +#ifdef PED_SKIN + if(IsClumpSkinned(clump)){ + int i; + RpHAnimHierarchy *hier; + RpAtomic *skinAtomic; + RpSkin *skin; + + // mobile: +// hier = nil; +// RwFrameForAllChildren(RpClumpGetFrame(clump), GetHierarchyFromChildNodesCB, &hier); +// assert(hier); +// RpClumpForAllAtomics(clump, SetHierarchyForSkinAtomic, hier); +// skinAtomic = GetFirstAtomic(clump); + + // xbox: + hier = GetAnimHierarchyFromClump(clump); + assert(hier); + RpSkinAtomicSetHAnimHierarchy(IsClumpSkinned(clump), hier); + skinAtomic = IsClumpSkinned(clump); + + assert(skinAtomic); + skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(skinAtomic)); + // ignore const + for(i = 0; i < RpGeometryGetNumVertices(RpAtomicGetGeometry(skinAtomic)); i++){ + RwMatrixWeights *weights = (RwMatrixWeights*)&RpSkinGetVertexBoneWeights(skin)[i]; + float sum = weights->w0 + weights->w1 + weights->w2 + weights->w3; + weights->w0 /= sum; + weights->w1 /= sum; + weights->w2 /= sum; + weights->w3 /= sum; + } +// RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS)); + } +#endif } void diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 5c801a2b..47080e23 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -1,6 +1,9 @@ #include "common.h" +#include "RwHelper.h" #include "General.h" +#include "Bones.h" +#include "SurfaceTable.h" #include "Ped.h" #include "NodeName.h" #include "VisibilityPlugins.h" @@ -9,13 +12,31 @@ void CPedModelInfo::DeleteRwObject(void) { - CClumpModelInfo::DeleteRwObject(); if(m_hitColModel) delete m_hitColModel; m_hitColModel = nil; +#ifdef PED_SKIN + RwFrame *frame; + if(m_head){ + frame = RpAtomicGetFrame(m_head); + RpAtomicDestroy(m_head); + RwFrameDestroy(frame); + } + if(m_lhand){ + frame = RpAtomicGetFrame(m_lhand); + RpAtomicDestroy(m_lhand); + RwFrameDestroy(frame); + } + if(m_rhand){ + frame = RpAtomicGetFrame(m_rhand); + RpAtomicDestroy(m_rhand); + RwFrameDestroy(frame); + } +#endif + CClumpModelInfo::DeleteRwObject(); // PC calls this first } -RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[12] = { +RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = { { "Smid", PED_MID, 0, }, // that is strange... { "Shead", PED_HEAD, 0, }, { "Supperarml", PED_UPPERARML, 0, }, @@ -30,15 +51,70 @@ RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[12] = { { nil, 0, 0, }, }; +#ifdef PED_SKIN +struct LimbCBarg +{ + CPedModelInfo *mi; + RpClump *clump; + int32 frameIDs[3]; +}; + +RpAtomic* +CPedModelInfo::findLimbsCb(RpAtomic *atomic, void *data) +{ + LimbCBarg *limbs = (LimbCBarg*)data; + RwFrame *frame = RpAtomicGetFrame(atomic); + const char *name = GetFrameNodeName(frame); + if(CGeneral::faststricmp(name, "Shead01") == 0){ + limbs->frameIDs[0] = RpHAnimFrameGetID(frame); + limbs->mi->m_head = atomic; + RpClumpRemoveAtomic(limbs->clump, atomic); + RwFrameRemoveChild(frame); + }else if(CGeneral::faststricmp(name, "SLhand01") == 0){ + limbs->frameIDs[1] = RpHAnimFrameGetID(frame); + limbs->mi->m_lhand = atomic; + RpClumpRemoveAtomic(limbs->clump, atomic); + RwFrameRemoveChild(frame); + }else if(CGeneral::faststricmp(name, "SRhand01") == 0){ + limbs->frameIDs[2] = RpHAnimFrameGetID(frame); + limbs->mi->m_rhand = atomic; + RpClumpRemoveAtomic(limbs->clump, atomic); + RwFrameRemoveChild(frame); + } + return atomic; +} +#endif + void CPedModelInfo::SetClump(RpClump *clump) { +#ifdef PED_SKIN + + // CB has to be set here before atomics are detached from clump + if(strncmp(GetName(), "player", 7) == 0) + RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); + if(IsClumpSkinned(clump)){ + LimbCBarg limbs = { this, clump, { 0, 0, 0 } }; + RpClumpForAllAtomics(clump, findLimbsCb, &limbs); + } + CClumpModelInfo::SetClump(clump); + SetFrameIds(m_pPedIds); + if(m_hitColModel == nil && !IsClumpSkinned(clump)) + CreateHitColModel(); + // And again because CClumpModelInfo resets it + if(strncmp(GetName(), "player", 7) == 0) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); + else if(IsClumpSkinned(clump)) + // skinned peds have no low detail version, so they don't have the right render Cb + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB); +#else CClumpModelInfo::SetClump(clump); SetFrameIds(m_pPedIds); if(m_hitColModel == nil) CreateHitColModel(); if(strncmp(GetName(), "player", 7) == 0) RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); +#endif } RpAtomic* @@ -157,7 +233,7 @@ CPedModelInfo::CreateHitColModel(void) } if(nodeFrame){ float radius = m_pColNodeInfos[i].radius; - if(m_pColNodeInfos[i].pieceType == 6) + if(m_pColNodeInfos[i].pieceType == PEDPIECE_HEAD) RwFrameForAllObjects(nodeFrame, FindHeadRadiusCB, &radius); RwMatrixTransform(mat, RwFrameGetMatrix(nodeFrame), rwCOMBINEREPLACE); const char *name = GetFrameNodeName(nodeFrame); @@ -172,7 +248,7 @@ CPedModelInfo::CreateHitColModel(void) center.x = mat->pos.x + m_pColNodeInfos[i].x; center.y = mat->pos.y + 0.0f; center.z = mat->pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(radius, center, 17, m_pColNodeInfos[i].pieceType); + spheres[i].Set(radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); } } RwMatrixDestroy(mat); @@ -186,7 +262,7 @@ CPedModelInfo::CreateHitColModel(void) max.x = max.y = 0.5f; max.z = 1.2f; colmodel->boundingBox.Set(min, max, 0, 0); - colmodel->level = 0; + colmodel->level = LEVEL_NONE; m_hitColModel = colmodel; } @@ -229,3 +305,81 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame) return colmodel; } + +#ifdef PED_SKIN +void +CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) +{ + CVector center; + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump); + CColModel *colmodel = new CColModel; + CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere)); + RwFrame *root = RpClumpGetFrame(m_clump); + RwMatrix *invmat = RwMatrixCreate(); + RwMatrix *mat = RwMatrixCreate(); + RwMatrixInvert(invmat, RwFrameGetMatrix(RpClumpGetFrame(clump))); + + for(int i = 0; i < NUMPEDINFONODES; i++){ + *mat = *invmat; + int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode); // this is wrong, wtf R* ??? + int idx = RpHAnimIDGetIndex(hier, id); + + // This doesn't really work as the positions are not initialized yet + RwMatrixTransform(mat, &RpHAnimHierarchyGetMatrixArray(hier)[idx], rwCOMBINEPRECONCAT); + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + RwV3dTransformPoints(&pos, &pos, 1, mat); + + center.x = pos.x + m_pColNodeInfos[i].x; + center.y = pos.y + 0.0f; + center.z = pos.z + m_pColNodeInfos[i].z; + spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); + } + RwMatrixDestroy(invmat); + RwMatrixDestroy(mat); + colmodel->spheres = spheres; + colmodel->numSpheres = NUMPEDINFONODES; + center.x = center.y = center.z = 0.0f; + colmodel->boundingSphere.Set(2.0f, center, 0, 0); + CVector min, max; + min.x = min.y = -0.5f; + min.z = -1.2f; + max.x = max.y = 0.5f; + max.z = 1.2f; + colmodel->boundingBox.Set(min, max, 0, 0); + colmodel->level = LEVEL_NONE; + m_hitColModel = colmodel; +} + +CColModel* +CPedModelInfo::AnimatePedColModelSkinned(RpClump *clump) +{ + if(m_hitColModel == nil){ + CreateHitColModelSkinned(clump); + return m_hitColModel; + } + RwMatrix *invmat, *mat; + CColSphere *spheres = m_hitColModel->spheres; + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump); + invmat = RwMatrixCreate(); + mat = RwMatrixCreate(); + RwMatrixInvert(invmat, RwFrameGetMatrix(RpClumpGetFrame(clump))); + + for(int i = 0; i < NUMPEDINFONODES; i++){ + *mat = *invmat; + int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode); + int idx = RpHAnimIDGetIndex(hier, id); + + RwMatrixTransform(mat, &RpHAnimHierarchyGetMatrixArray(hier)[idx], rwCOMBINEPRECONCAT); + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + RwV3dTransformPoints(&pos, &pos, 1, mat); + + spheres[i].center.x = pos.x + m_pColNodeInfos[i].x; + spheres[i].center.y = pos.y + 0.0f; + spheres[i].center.z = pos.z + m_pColNodeInfos[i].z; + } + RwMatrixDestroy(invmat); + RwMatrixDestroy(mat); + return m_hitColModel; +} + +#endif diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h index 0336fa9b..a2bfd122 100644 --- a/src/modelinfo/PedModelInfo.h +++ b/src/modelinfo/PedModelInfo.h @@ -28,11 +28,13 @@ public: ePedStats m_pedStatType; uint32 m_carsCanDrive; CColModel *m_hitColModel; +#ifdef PED_SKIN RpAtomic *m_head; RpAtomic *m_lhand; RpAtomic *m_rhand; +#endif - static RwObjectNameIdAssocation m_pPedIds[12]; + static RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX]; CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { } void DeleteRwObject(void); @@ -40,7 +42,18 @@ public: void SetLowDetailClump(RpClump*); void CreateHitColModel(void); + void CreateHitColModelSkinned(RpClump *clump); CColModel *GetHitColModel(void) { return m_hitColModel; } static CColModel *AnimatePedColModel(CColModel* colmodel, RwFrame* frame); + CColModel *AnimatePedColModelSkinned(RpClump *clump); + +#ifdef PED_SKIN + static RpAtomic *findLimbsCb(RpAtomic *atomic, void *data); + RpAtomic *getHead(void) { return m_head; } + RpAtomic *getLeftHand(void) { return m_lhand; } + RpAtomic *getRightHand(void) { return m_rhand; } +#endif }; -static_assert(sizeof(CPedModelInfo) == 0x54, "CPedModelInfo: error"); +#ifndef PED_SKIN +static_assert(sizeof(CPedModelInfo) == 0x48, "CPedModelInfo: error"); +#endif
\ No newline at end of file |