mirror of
https://github.com/halpz/re3.git
synced 2025-04-25 12:05:47 +00:00
220 lines
6.2 KiB
C++
220 lines
6.2 KiB
C++
#include "common.h"
|
|
|
|
#include "main.h"
|
|
#include "RwHelper.h"
|
|
#include "General.h"
|
|
#include "Bones.h"
|
|
#include "SurfaceTable.h"
|
|
#include "Ped.h"
|
|
#include "NodeName.h"
|
|
#include "VisibilityPlugins.h"
|
|
#include "ModelInfo.h"
|
|
#include "custompipes.h"
|
|
#include "Streaming.h"
|
|
#include "Leeds.h"
|
|
#include "TempColModels.h"
|
|
|
|
base::cRelocatableChunkClassInfo CPedModelInfo::msClassInfo("CPedModelInfo", VTABLE_ADDR(&msClassInstance), sizeof(msClassInstance));
|
|
CPedModelInfo CPedModelInfo::msClassInstance;
|
|
|
|
void
|
|
CPedModelInfo::DeleteRwObject(void)
|
|
{
|
|
CStreaming::UnregisterPointer(&m_hitColModel, 2);
|
|
CClumpModelInfo::DeleteRwObject();
|
|
if(!gUseChunkFiles && m_hitColModel)
|
|
delete m_hitColModel;
|
|
m_hitColModel = nil;
|
|
}
|
|
|
|
// leftover...
|
|
RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = {
|
|
{ "Smid", PED_MID, 0, }, // that is strange...
|
|
{ "Shead", PED_HEAD, 0, },
|
|
{ "Supperarml", PED_UPPERARML, 0, },
|
|
{ "Supperarmr", PED_UPPERARMR, 0, },
|
|
{ "SLhand", PED_HANDL, 0, },
|
|
{ "SRhand", PED_HANDR, 0, },
|
|
{ "Supperlegl", PED_UPPERLEGL, 0, },
|
|
{ "Supperlegr", PED_UPPERLEGR, 0, },
|
|
{ "Sfootl", PED_FOOTL, 0, },
|
|
{ "Sfootr", PED_FOOTR, 0, },
|
|
{ "Slowerlegr", PED_LOWERLEGR, 0, },
|
|
{ nil, 0, 0, },
|
|
};
|
|
|
|
void
|
|
CPedModelInfo::SetClump(RpClump *clump)
|
|
{
|
|
#ifdef EXTENDED_PIPELINES
|
|
CustomPipes::AttachRimPipe(clump);
|
|
#endif
|
|
if(!IsClumpSkinned(clump))
|
|
return;
|
|
CClumpModelInfo::SetClump(clump);
|
|
SetFrameIds(m_pPedIds); // not needed in VC actually
|
|
if(m_hitColModel == nil)
|
|
CreateHitColModelSkinned(clump);
|
|
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB);
|
|
//if(strcmp(GetModelName(), "player") == 0)
|
|
// RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
|
|
}
|
|
|
|
struct ColNodeInfo
|
|
{
|
|
Const char *name;
|
|
int pedNode;
|
|
int pieceType;
|
|
float x, z;
|
|
float radius;
|
|
};
|
|
|
|
#define NUMPEDINFONODES 10
|
|
ColNodeInfo m_pColNodeInfos[NUMPEDINFONODES] = {
|
|
{ nil, PED_HEAD, PEDPIECE_HEAD, 0.0f, 0.05f, 0.15f },
|
|
{ nil, PED_MID, PEDPIECE_TORSO, 0.0f, 0.15f, 0.2f },
|
|
{ nil, PED_MID, PEDPIECE_TORSO, 0.0f, -0.05f, 0.25f },
|
|
{ nil, PED_MID, PEDPIECE_MID, 0.0f, -0.25f, 0.25f },
|
|
{ nil, PED_UPPERARML, PEDPIECE_LEFTARM, 0.03f, -0.05f, 0.16f },
|
|
{ nil, PED_UPPERARMR, PEDPIECE_RIGHTARM, -0.03f, -0.05f, 0.16f },
|
|
{ nil, PED_LOWERLEGL, PEDPIECE_LEFTLEG, 0.0f, 0.15f, 0.2f },
|
|
{ nil, PED_LOWERLEGR, PEDPIECE_RIGHTLEG, 0.0f, 0.15f, 0.2f },
|
|
{ nil, PED_FOOTL, PEDPIECE_LEFTLEG, 0.0f, 0.15f, 0.15f },
|
|
{ nil, PED_FOOTR, PEDPIECE_RIGHTLEG, 0.0f, 0.15f, 0.15f },
|
|
};
|
|
|
|
bool
|
|
CPedModelInfo::CreateHitColModelSkinned(RpClump *clump)
|
|
{
|
|
CColModel *colmodel = new CColModel;
|
|
CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere));
|
|
|
|
for(int i = 0; i < NUMPEDINFONODES; i++){
|
|
spheres[i].center.x = 0.0f;
|
|
spheres[i].center.y = 0.0f;
|
|
spheres[i].center.z = 0.0f;
|
|
spheres[i].radius = m_pColNodeInfos[i].radius;
|
|
spheres[i].surface = SURFACE_PED;
|
|
spheres[i].piece = m_pColNodeInfos[i].pieceType;
|
|
}
|
|
colmodel->spheres = spheres;
|
|
colmodel->numSpheres = NUMPEDINFONODES;
|
|
colmodel->boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
|
|
colmodel->boundingBox.Set(CVector(-0.5f, -0.5f, -1.2f), CVector(0.5f, 0.5f, 1.2f));
|
|
colmodel->level = LEVEL_GENERIC;
|
|
m_hitColModel = colmodel;
|
|
return true;
|
|
}
|
|
|
|
CColModel*
|
|
CPedModelInfo::AnimatePedColModelSkinned(RpClump *clump)
|
|
{
|
|
if(m_hitColModel == nil){
|
|
CreateHitColModelSkinned(clump);
|
|
#ifndef FIX_BUGS
|
|
return m_hitColModel;
|
|
#endif
|
|
// we should really animate this now
|
|
}
|
|
RwMatrix invmat, mat;
|
|
CColSphere *spheres = m_hitColModel->spheres;
|
|
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);
|
|
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 }; // actually CVector
|
|
RwV3dTransformPoints(&pos, &pos, 1, &mat);
|
|
|
|
spheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z);
|
|
}
|
|
return m_hitColModel;
|
|
}
|
|
|
|
CColModel*
|
|
CPedModelInfo::AnimatePedColModelSkinnedWorld(RpClump *clump)
|
|
{
|
|
if(m_hitColModel == nil)
|
|
CreateHitColModelSkinned(clump);
|
|
CColSphere *spheres = m_hitColModel->spheres;
|
|
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);
|
|
RwMatrix *mat;
|
|
|
|
for(int i = 0; i < NUMPEDINFONODES; i++){
|
|
int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode);
|
|
int idx = RpHAnimIDGetIndex(hier, id);
|
|
|
|
mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
|
|
RwV3d pos = { 0.0f, 0.0f, 0.0f }; // actually CVector
|
|
RwV3dTransformPoints(&pos, &pos, 1, mat);
|
|
|
|
spheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z);
|
|
}
|
|
return m_hitColModel;
|
|
}
|
|
|
|
|
|
struct PedChunk
|
|
{
|
|
CColModel *colmodel;
|
|
RpClump *clump;
|
|
};
|
|
|
|
void
|
|
CPedModelInfo::LoadModel(void *data, const void *chunk)
|
|
{
|
|
PedChunk *chk = (PedChunk*)data;
|
|
m_hitColModel = chk->colmodel;
|
|
CStreaming::RegisterPointer(&m_hitColModel, 2, true);
|
|
CClumpModelInfo::LoadModel(chk->clump, chunk);
|
|
}
|
|
|
|
void
|
|
CPedModelInfo::Write(base::cRelocatableChunkWriter &writer)
|
|
{
|
|
SetColModel(&gpTempColModels->ms_colModelPed1);
|
|
CClumpModelInfo::Write(writer);
|
|
if(m_hitColModel){
|
|
writer.AddPatch(&m_hitColModel);
|
|
m_hitColModel->Write(writer, true);
|
|
}
|
|
}
|
|
|
|
void*
|
|
CPedModelInfo::WriteModel(base::cRelocatableChunkWriter &writer)
|
|
{
|
|
PedChunk *chunk = new PedChunk; // LEAK
|
|
chunk->colmodel = nil;
|
|
chunk->clump = nil;
|
|
writer.AllocateRaw(chunk, sizeof(*chunk), sizeof(void*), false, true);
|
|
|
|
chunk->clump = (RpClump*)CClumpModelInfo::WriteModel(writer);
|
|
if(chunk->clump)
|
|
writer.AddPatch(&chunk->clump);
|
|
|
|
chunk->colmodel = m_hitColModel;
|
|
if(chunk->colmodel){
|
|
writer.AddPatch(&chunk->colmodel);
|
|
chunk->colmodel->Write(writer, true);
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
void
|
|
CPedModelInfo::RcWriteThis(base::cRelocatableChunkWriter &writer)
|
|
{
|
|
writer.AllocateRaw(this, sizeof(*this), sizeof(void*), false, true);
|
|
writer.Class(VTABLE_ADDR(this), msClassInfo);
|
|
}
|
|
|
|
void
|
|
CPedModelInfo::RcWriteEmpty(base::cRelocatableChunkWriter &writer)
|
|
{
|
|
writer.AllocateRaw(this, sizeof(*this), sizeof(void*), false, true);
|
|
writer.Class(VTABLE_ADDR(this), msClassInfo);
|
|
}
|