2019-05-15 14:52:37 +00:00
|
|
|
#include "common.h"
|
2020-04-17 13:31:11 +00:00
|
|
|
|
2020-04-23 20:25:18 +00:00
|
|
|
#include "RwHelper.h"
|
2019-10-29 23:12:58 +00:00
|
|
|
#include "General.h"
|
2019-05-15 14:52:37 +00:00
|
|
|
#include "NodeName.h"
|
|
|
|
#include "VisibilityPlugins.h"
|
|
|
|
#include "ModelInfo.h"
|
2020-10-28 09:33:27 +00:00
|
|
|
#include "ModelIndices.h"
|
2019-05-15 14:52:37 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
CClumpModelInfo::DeleteRwObject(void)
|
|
|
|
{
|
|
|
|
if(m_clump){
|
|
|
|
RpClumpDestroy(m_clump);
|
|
|
|
m_clump = nil;
|
|
|
|
RemoveTexDictionaryRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-23 20:25:18 +00:00
|
|
|
#ifdef PED_SKIN
|
|
|
|
static RpAtomic*
|
|
|
|
SetHierarchyForSkinAtomic(RpAtomic *atomic, void *data)
|
|
|
|
{
|
|
|
|
RpSkinAtomicSetHAnimHierarchy(atomic, (RpHAnimHierarchy*)data);
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-05-15 14:52:37 +00:00
|
|
|
RwObject*
|
|
|
|
CClumpModelInfo::CreateInstance(void)
|
|
|
|
{
|
2020-04-23 20:25:18 +00:00
|
|
|
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);
|
2020-05-10 15:09:57 +00:00
|
|
|
RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS));
|
2020-04-23 20:25:18 +00:00
|
|
|
// the rest is xbox only:
|
|
|
|
// RpSkinGetNumBones(RpSkinGeometryGetSkin(RpAtomicGetGeometry(IsClumpSkinned(clone))));
|
|
|
|
RpHAnimHierarchyUpdateMatrices(hier);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (RwObject*)clone;
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RwObject*
|
|
|
|
CClumpModelInfo::CreateInstance(RwMatrix *m)
|
|
|
|
{
|
|
|
|
if(m_clump){
|
|
|
|
RpClump *clump = (RpClump*)CreateInstance();
|
|
|
|
*RwFrameGetMatrix(RpClumpGetFrame(clump)) = *m;
|
|
|
|
return (RwObject*)clump;
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
RpAtomic*
|
|
|
|
CClumpModelInfo::SetAtomicRendererCB(RpAtomic *atomic, void *data)
|
|
|
|
{
|
|
|
|
CVisibilityPlugins::SetAtomicRenderCallback(atomic, (RpAtomicCallBackRender)data);
|
|
|
|
return atomic;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CClumpModelInfo::SetClump(RpClump *clump)
|
|
|
|
{
|
|
|
|
m_clump = clump;
|
|
|
|
CVisibilityPlugins::SetClumpModelInfo(m_clump, this);
|
|
|
|
AddTexDictionaryRef();
|
|
|
|
RpClumpForAllAtomics(clump, SetAtomicRendererCB, nil);
|
2020-04-23 20:25:18 +00:00
|
|
|
|
|
|
|
#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;
|
|
|
|
}
|
2020-05-10 15:09:57 +00:00
|
|
|
RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS));
|
2020-10-28 09:33:27 +00:00
|
|
|
}
|
2021-01-08 19:50:59 +00:00
|
|
|
if(strcmp(GetModelName(), "playerh") == 0){
|
2020-10-28 09:33:27 +00:00
|
|
|
// playerh is incompatible with the xbox player skin
|
|
|
|
// so check if player model is skinned and only apply skin to head if it isn't
|
|
|
|
CPedModelInfo *body = (CPedModelInfo*)CModelInfo::GetModelInfo(MI_PLAYER);
|
|
|
|
if(!(body->m_clump && IsClumpSkinned(body->m_clump)))
|
2020-05-14 10:32:51 +00:00
|
|
|
RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
|
2020-10-28 09:33:27 +00:00
|
|
|
}
|
|
|
|
#else
|
2021-01-12 17:55:14 +00:00
|
|
|
if(strcmp(GetModelName(), "playerh") == 0)
|
2020-10-28 09:33:27 +00:00
|
|
|
RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
|
|
|
|
#endif
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CClumpModelInfo::SetFrameIds(RwObjectNameIdAssocation *assocs)
|
|
|
|
{
|
|
|
|
int32 i;
|
|
|
|
RwObjectNameAssociation objname;
|
|
|
|
|
|
|
|
for(i = 0; assocs[i].name; i++)
|
|
|
|
if((assocs[i].flags & CLUMP_FLAG_NO_HIERID) == 0){
|
|
|
|
objname.frame = nil;
|
|
|
|
objname.name = assocs[i].name;
|
|
|
|
RwFrameForAllChildren(RpClumpGetFrame(m_clump), FindFrameFromNameWithoutIdCB, &objname);
|
|
|
|
if(objname.frame)
|
|
|
|
CVisibilityPlugins::SetFrameHierarchyId(objname.frame, assocs[i].hierId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RwFrame*
|
|
|
|
CClumpModelInfo::FindFrameFromIdCB(RwFrame *frame, void *data)
|
|
|
|
{
|
|
|
|
RwObjectIdAssociation *assoc = (RwObjectIdAssociation*)data;
|
|
|
|
|
2020-05-10 15:09:57 +00:00
|
|
|
if(CVisibilityPlugins::GetFrameHierarchyId(frame) == assoc->id){
|
2019-05-15 14:52:37 +00:00
|
|
|
assoc->frame = frame;
|
|
|
|
return nil;
|
|
|
|
}
|
2020-05-10 15:09:57 +00:00
|
|
|
RwFrameForAllChildren(frame, FindFrameFromIdCB, assoc);
|
|
|
|
return assoc->frame ? nil : frame;
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RwFrame*
|
|
|
|
CClumpModelInfo::FindFrameFromNameCB(RwFrame *frame, void *data)
|
|
|
|
{
|
|
|
|
RwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;
|
|
|
|
|
2020-05-10 15:09:57 +00:00
|
|
|
if(!CGeneral::faststricmp(GetFrameNodeName(frame), assoc->name)){
|
2019-05-15 14:52:37 +00:00
|
|
|
assoc->frame = frame;
|
|
|
|
return nil;
|
|
|
|
}
|
2020-05-10 15:09:57 +00:00
|
|
|
RwFrameForAllChildren(frame, FindFrameFromNameCB, assoc);
|
|
|
|
return assoc->frame ? nil : frame;
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RwFrame*
|
|
|
|
CClumpModelInfo::FindFrameFromNameWithoutIdCB(RwFrame *frame, void *data)
|
|
|
|
{
|
|
|
|
RwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;
|
|
|
|
|
2020-05-10 15:09:57 +00:00
|
|
|
if(CVisibilityPlugins::GetFrameHierarchyId(frame) == 0 &&
|
|
|
|
!CGeneral::faststricmp(GetFrameNodeName(frame), assoc->name)){
|
2019-05-15 14:52:37 +00:00
|
|
|
assoc->frame = frame;
|
|
|
|
return nil;
|
|
|
|
}
|
2020-05-10 15:09:57 +00:00
|
|
|
RwFrameForAllChildren(frame, FindFrameFromNameWithoutIdCB, assoc);
|
|
|
|
return assoc->frame ? nil : frame;
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RwFrame*
|
|
|
|
CClumpModelInfo::FillFrameArrayCB(RwFrame *frame, void *data)
|
|
|
|
{
|
|
|
|
int32 id;
|
|
|
|
RwFrame **frames = (RwFrame**)data;
|
|
|
|
id = CVisibilityPlugins::GetFrameHierarchyId(frame);
|
|
|
|
if(id > 0)
|
|
|
|
frames[id] = frame;
|
|
|
|
RwFrameForAllChildren(frame, FillFrameArrayCB, data);
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CClumpModelInfo::FillFrameArray(RpClump *clump, RwFrame **frames)
|
|
|
|
{
|
|
|
|
RwFrameForAllChildren(RpClumpGetFrame(clump), FillFrameArrayCB, frames);
|
|
|
|
}
|
|
|
|
|
|
|
|
RwFrame*
|
|
|
|
CClumpModelInfo::GetFrameFromId(RpClump *clump, int32 id)
|
|
|
|
{
|
|
|
|
RwObjectIdAssociation assoc;
|
|
|
|
assoc.id = id;
|
|
|
|
assoc.frame = nil;
|
|
|
|
RwFrameForAllChildren(RpClumpGetFrame(clump), FindFrameFromIdCB, &assoc);
|
|
|
|
return assoc.frame;
|
|
|
|
}
|