mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
Some of the to-dos
- Implemented Animation parameters for A_ChangeModel - Made a modeldef flag to treat additional model indices as just attachments, meaning they will use armature data from index 0 - Fixed an issue with A_ChangeModel where generated indices lower than smf frame amounts could not actually generate anything
This commit is contained in:
parent
e9e919b54c
commit
5670e6f54c
19 changed files with 119 additions and 59 deletions
|
@ -70,11 +70,12 @@ public:
|
||||||
|
|
||||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0;
|
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0;
|
||||||
virtual int FindFrame(const char * name, bool nodefault = false) = 0;
|
virtual int FindFrame(const char * name, bool nodefault = false) = 0;
|
||||||
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) = 0;
|
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) = 0;
|
||||||
virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0;
|
virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0;
|
||||||
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0;
|
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0;
|
||||||
virtual float getAspectFactor(float vscale) { return 1.f; }
|
virtual float getAspectFactor(float vscale) { return 1.f; }
|
||||||
virtual const TArray<VSMatrix>* AttachAnimationData() { return nullptr; };
|
virtual const TArray<VSMatrix>* AttachAnimationData() { return nullptr; };
|
||||||
|
virtual const TArray<VSMatrix> CalculateBones(int frame1, int frame2, double inter, const TArray<VSMatrix>& animationData) { return {}; };
|
||||||
|
|
||||||
void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; }
|
void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; }
|
||||||
IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; }
|
IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; }
|
||||||
|
|
|
@ -109,10 +109,11 @@ public:
|
||||||
|
|
||||||
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
|
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
|
||||||
int FindFrame(const char* name, bool nodefault) override;
|
int FindFrame(const char* name, bool nodefault) override;
|
||||||
void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) override;
|
void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) override;
|
||||||
void BuildVertexBuffer(FModelRenderer* renderer) override;
|
void BuildVertexBuffer(FModelRenderer* renderer) override;
|
||||||
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
|
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
|
||||||
const TArray<VSMatrix>* AttachAnimationData() override;
|
const TArray<VSMatrix>* AttachAnimationData() override;
|
||||||
|
const TArray<VSMatrix> CalculateBones(int frame1, int frame2, double inter, const TArray<VSMatrix>& animationData) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadGeometry();
|
void LoadGeometry();
|
||||||
|
|
|
@ -59,7 +59,7 @@ public:
|
||||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
||||||
void Initialize();
|
void Initialize();
|
||||||
virtual int FindFrame(const char* name, bool nodefault) override;
|
virtual int FindFrame(const char* name, bool nodefault) override;
|
||||||
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) override;
|
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) override;
|
||||||
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
||||||
FTextureID GetPaletteTexture() const { return mPalette; }
|
FTextureID GetPaletteTexture() const { return mPalette; }
|
||||||
void BuildVertexBuffer(FModelRenderer *renderer) override;
|
void BuildVertexBuffer(FModelRenderer *renderer) override;
|
||||||
|
|
|
@ -113,7 +113,7 @@ public:
|
||||||
|
|
||||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
||||||
virtual int FindFrame(const char* name, bool nodefault) override;
|
virtual int FindFrame(const char* name, bool nodefault) override;
|
||||||
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) override;
|
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) override;
|
||||||
virtual void LoadGeometry();
|
virtual void LoadGeometry();
|
||||||
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
|
|
||||||
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
||||||
virtual int FindFrame(const char* name, bool nodefault) override;
|
virtual int FindFrame(const char* name, bool nodefault) override;
|
||||||
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) override;
|
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) override;
|
||||||
void LoadGeometry();
|
void LoadGeometry();
|
||||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||||
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
||||||
|
|
|
@ -98,7 +98,7 @@ public:
|
||||||
~FOBJModel();
|
~FOBJModel();
|
||||||
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
|
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
|
||||||
int FindFrame(const char* name, bool nodefault) override;
|
int FindFrame(const char* name, bool nodefault) override;
|
||||||
void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) override;
|
void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) override;
|
||||||
void BuildVertexBuffer(FModelRenderer* renderer) override;
|
void BuildVertexBuffer(FModelRenderer* renderer) override;
|
||||||
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
|
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
|
|
||||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
||||||
int FindFrame(const char* name, bool nodefault) override;
|
int FindFrame(const char* name, bool nodefault) override;
|
||||||
void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData) override;
|
void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData) override;
|
||||||
void BuildVertexBuffer(FModelRenderer *renderer) override;
|
void BuildVertexBuffer(FModelRenderer *renderer) override;
|
||||||
void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override;
|
||||||
void LoadGeometry();
|
void LoadGeometry();
|
||||||
|
|
|
@ -490,46 +490,9 @@ int IQMModel::FindFrame(const char* name, bool nodefault)
|
||||||
return FErr_NotFound;
|
return FErr_NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData)
|
void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData)
|
||||||
{
|
{
|
||||||
const TArray<VSMatrix>& animationFrames = &animationData ? animationData : FrameTransforms;
|
renderer->SetupFrame(this, 0, 0, NumVertices, boneData);
|
||||||
|
|
||||||
int numbones = Joints.Size();
|
|
||||||
|
|
||||||
frame1 = clamp(frame1, 0, ((int)animationFrames.Size() - 1)/numbones);
|
|
||||||
frame2 = clamp(frame2, 0, ((int)animationFrames.Size() - 1)/numbones);
|
|
||||||
|
|
||||||
int offset1 = frame1 * numbones;
|
|
||||||
int offset2 = frame2 * numbones;
|
|
||||||
float t = (float)inter;
|
|
||||||
float invt = 1.0f - t;
|
|
||||||
|
|
||||||
TArray<VSMatrix> bones(numbones, true);
|
|
||||||
for (int i = 0; i < numbones; i++)
|
|
||||||
{
|
|
||||||
const float* from = animationFrames[offset1 + i].get();
|
|
||||||
const float* to = animationFrames[offset2 + i].get();
|
|
||||||
|
|
||||||
// Interpolate bone between the two frames
|
|
||||||
float bone[16];
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
bone[i] = from[i] * invt + to[i] * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply parent bone
|
|
||||||
if (Joints[i].Parent >= 0)
|
|
||||||
{
|
|
||||||
bones[i] = bones[Joints[i].Parent];
|
|
||||||
bones[i].multMatrix(bone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bones[i].loadMatrix(bone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer->SetupFrame(this, 0, 0, NumVertices, bones);
|
|
||||||
|
|
||||||
FGameTexture* lastSkin = nullptr;
|
FGameTexture* lastSkin = nullptr;
|
||||||
for (int i = 0; i < Meshes.Size(); i++)
|
for (int i = 0; i < Meshes.Size(); i++)
|
||||||
|
@ -597,3 +560,45 @@ const TArray<VSMatrix>* IQMModel::AttachAnimationData()
|
||||||
{
|
{
|
||||||
return &FrameTransforms;
|
return &FrameTransforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double inter, const TArray<VSMatrix>& animationData)
|
||||||
|
{
|
||||||
|
const TArray<VSMatrix>& animationFrames = &animationData ? animationData : FrameTransforms;
|
||||||
|
|
||||||
|
int numbones = Joints.Size();
|
||||||
|
|
||||||
|
frame1 = clamp(frame1, 0, ((int)animationFrames.Size() - 1) / numbones);
|
||||||
|
frame2 = clamp(frame2, 0, ((int)animationFrames.Size() - 1) / numbones);
|
||||||
|
|
||||||
|
int offset1 = frame1 * numbones;
|
||||||
|
int offset2 = frame2 * numbones;
|
||||||
|
float t = (float)inter;
|
||||||
|
float invt = 1.0f - t;
|
||||||
|
|
||||||
|
TArray<VSMatrix> bones(numbones, true);
|
||||||
|
for (int i = 0; i < numbones; i++)
|
||||||
|
{
|
||||||
|
const float* from = animationFrames[offset1 + i].get();
|
||||||
|
const float* to = animationFrames[offset2 + i].get();
|
||||||
|
|
||||||
|
// Interpolate bone between the two frames
|
||||||
|
float bone[16];
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
bone[i] = from[i] * invt + to[i] * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply parent bone
|
||||||
|
if (Joints[i].Parent >= 0)
|
||||||
|
{
|
||||||
|
bones[i] = bones[Joints[i].Parent];
|
||||||
|
bones[i].multMatrix(bone);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bones[i].loadMatrix(bone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bones;
|
||||||
|
}
|
|
@ -363,7 +363,7 @@ int FDMDModel::FindFrame(const char* name, bool nodefault)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID*, const TArray<VSMatrix>& animationData)
|
void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID*, const TArray<VSMatrix>& boneData)
|
||||||
{
|
{
|
||||||
if (frameno >= info.numFrames || frameno2 >= info.numFrames) return;
|
if (frameno >= info.numFrames || frameno2 >= info.numFrames) return;
|
||||||
|
|
||||||
|
|
|
@ -343,7 +343,7 @@ int FMD3Model::FindFrame(const char* name, bool nodefault)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData)
|
void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData)
|
||||||
{
|
{
|
||||||
if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return;
|
if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return;
|
||||||
|
|
||||||
|
|
|
@ -628,7 +628,7 @@ int FOBJModel::FindFrame(const char* name, bool nodefault)
|
||||||
* @param inter The amount to interpolate the two frames.
|
* @param inter The amount to interpolate the two frames.
|
||||||
* @param translation The translation for the skin
|
* @param translation The translation for the skin
|
||||||
*/
|
*/
|
||||||
void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData)
|
void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData)
|
||||||
{
|
{
|
||||||
// Prevent the model from rendering if the frame number is < 0
|
// Prevent the model from rendering if the frame number is < 0
|
||||||
if (frameno < 0 || frameno2 < 0) return;
|
if (frameno < 0 || frameno2 < 0) return;
|
||||||
|
|
|
@ -229,7 +229,7 @@ int FUE1Model::FindFrame(const char* name, bool nodefault)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& animationData)
|
void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray<VSMatrix>& boneData)
|
||||||
{
|
{
|
||||||
// the moment of magic
|
// the moment of magic
|
||||||
if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return;
|
if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return;
|
||||||
|
|
|
@ -400,7 +400,7 @@ float FVoxelModel::getAspectFactor(float stretch)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID*, const TArray<VSMatrix>& animationData)
|
void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID*, const TArray<VSMatrix>& boneData)
|
||||||
{
|
{
|
||||||
renderer->SetMaterial(skin, true, translation);
|
renderer->SetMaterial(skin, true, translation);
|
||||||
renderer->SetupFrame(this, 0, 0, 0, {});
|
renderer->SetupFrame(this, 0, 0, 0, {});
|
||||||
|
|
|
@ -682,6 +682,7 @@ public:
|
||||||
TArray<int> modelIDs;
|
TArray<int> modelIDs;
|
||||||
TArray<FTextureID> skinIDs;
|
TArray<FTextureID> skinIDs;
|
||||||
TArray<FTextureID> surfaceSkinIDs;
|
TArray<FTextureID> surfaceSkinIDs;
|
||||||
|
TArray<int> animationIDs;
|
||||||
TArray<int> modelFrameGenerators;
|
TArray<int> modelFrameGenerators;
|
||||||
|
|
||||||
DActorModelData() = default;
|
DActorModelData() = default;
|
||||||
|
|
|
@ -5047,6 +5047,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
PARAM_NAME(skin);
|
PARAM_NAME(skin);
|
||||||
PARAM_INT(flags);
|
PARAM_INT(flags);
|
||||||
PARAM_INT(generatorindex);
|
PARAM_INT(generatorindex);
|
||||||
|
PARAM_INT(animationindex);
|
||||||
|
PARAM_STRING_VAL(animationpath);
|
||||||
|
PARAM_NAME(animation);
|
||||||
|
|
||||||
if (self == nullptr)
|
if (self == nullptr)
|
||||||
ACTION_RETURN_BOOL(false);
|
ACTION_RETURN_BOOL(false);
|
||||||
|
@ -5060,11 +5063,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
Printf("Attempt to pass invalid skin index %d in %s, index must be non-negative.", skinindex, self->GetCharacterName());
|
Printf("Attempt to pass invalid skin index %d in %s, index must be non-negative.", skinindex, self->GetCharacterName());
|
||||||
ACTION_RETURN_BOOL(false);
|
ACTION_RETURN_BOOL(false);
|
||||||
}
|
}
|
||||||
|
else if (animationindex < 0)
|
||||||
|
{
|
||||||
|
Printf("Attempt to pass invalid animation index %d in %s, index must be non-negative.", animationindex, self->GetCharacterName());
|
||||||
|
ACTION_RETURN_BOOL(false);
|
||||||
|
}
|
||||||
|
|
||||||
AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : stateowner;
|
AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : stateowner;
|
||||||
|
|
||||||
if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/';
|
if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/';
|
||||||
if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/';
|
if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/';
|
||||||
|
if (animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/';
|
||||||
|
|
||||||
if (mobj->modelData == nullptr)
|
if (mobj->modelData == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -5073,6 +5082,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
ptr->modelIDs = *new TArray<int>();
|
ptr->modelIDs = *new TArray<int>();
|
||||||
ptr->skinIDs = *new TArray<FTextureID>();
|
ptr->skinIDs = *new TArray<FTextureID>();
|
||||||
ptr->surfaceSkinIDs = *new TArray<FTextureID>();
|
ptr->surfaceSkinIDs = *new TArray<FTextureID>();
|
||||||
|
ptr->animationIDs = *new TArray<int>();
|
||||||
ptr->modelFrameGenerators = *new TArray<int>();
|
ptr->modelFrameGenerators = *new TArray<int>();
|
||||||
ptr->modelDef = NAME_None;
|
ptr->modelDef = NAME_None;
|
||||||
mobj->modelData = ptr;
|
mobj->modelData = ptr;
|
||||||
|
@ -5083,15 +5093,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
int maxModels = mobj->modelData->modelIDs.Size();
|
int maxModels = mobj->modelData->modelIDs.Size();
|
||||||
int maxSkins = mobj->modelData->skinIDs.Size();
|
int maxSkins = mobj->modelData->skinIDs.Size();
|
||||||
int maxSurfaceSkins = mobj->modelData->surfaceSkinIDs.Size();
|
int maxSurfaceSkins = mobj->modelData->surfaceSkinIDs.Size();
|
||||||
|
int maxAnimations = mobj->modelData->animationIDs.Size();
|
||||||
int maxGenerators = mobj->modelData->modelFrameGenerators.Size();
|
int maxGenerators = mobj->modelData->modelFrameGenerators.Size();
|
||||||
|
|
||||||
int skinPosition = skinindex + modelindex * MD3_MAX_SURFACES;
|
int skinPosition = skinindex + modelindex * MD3_MAX_SURFACES;
|
||||||
|
|
||||||
int queryModel = !(flags & CMDL_HIDEMODEL) ? model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1 : -2;
|
int queryModel = !(flags & CMDL_HIDEMODEL) ? model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1 : -2;
|
||||||
|
int queryAnimation = animation != NAME_None ? FindModel(animationpath.GetChars(), animation.GetChars()) : -1;
|
||||||
|
|
||||||
//[SM] - Let's clear out any potential entries at the specified indices
|
//[SM] - Let's clear out any potential entries at the specified indices
|
||||||
mobj->modelData->modelDef = modeldef;
|
mobj->modelData->modelDef = modeldef;
|
||||||
if(maxModels > modelindex) mobj->modelData->modelIDs.Pop(mobj->modelData->modelIDs[modelindex]);
|
if(maxModels > modelindex) mobj->modelData->modelIDs.Pop(mobj->modelData->modelIDs[modelindex]);
|
||||||
|
if(maxAnimations > animationindex) mobj->modelData->animationIDs.Pop(mobj->modelData->animationIDs[animationindex]);
|
||||||
if(maxGenerators > modelindex) mobj->modelData->modelFrameGenerators.Pop(mobj->modelData->modelFrameGenerators[modelindex]);
|
if(maxGenerators > modelindex) mobj->modelData->modelFrameGenerators.Pop(mobj->modelData->modelFrameGenerators[modelindex]);
|
||||||
|
|
||||||
if (flags & CMDL_USESURFACESKIN)
|
if (flags & CMDL_USESURFACESKIN)
|
||||||
|
@ -5108,6 +5121,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
//[SM] - We need to fill up any holes this new index will make so that it doesn't leave behind any undefined behavior
|
//[SM] - We need to fill up any holes this new index will make so that it doesn't leave behind any undefined behavior
|
||||||
while ((int)mobj->modelData->modelIDs.Size() < modelindex) mobj->modelData->modelIDs.Push(-1);
|
while ((int)mobj->modelData->modelIDs.Size() < modelindex) mobj->modelData->modelIDs.Push(-1);
|
||||||
while ((int)mobj->modelData->modelFrameGenerators.Size() < modelindex) mobj->modelData->modelFrameGenerators.Push(-1);
|
while ((int)mobj->modelData->modelFrameGenerators.Size() < modelindex) mobj->modelData->modelFrameGenerators.Push(-1);
|
||||||
|
while ((int)mobj->modelData->animationIDs.Size() < modelindex) mobj->modelData->animationIDs.Push(-1);
|
||||||
if (flags & CMDL_USESURFACESKIN)
|
if (flags & CMDL_USESURFACESKIN)
|
||||||
while ((int)mobj->modelData->surfaceSkinIDs.Size() < skinPosition) mobj->modelData->surfaceSkinIDs.Push(FNullTextureID());
|
while ((int)mobj->modelData->surfaceSkinIDs.Size() < skinPosition) mobj->modelData->surfaceSkinIDs.Push(FNullTextureID());
|
||||||
else
|
else
|
||||||
|
@ -5115,6 +5129,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
|
|
||||||
mobj->modelData->modelIDs.Insert(modelindex, queryModel);
|
mobj->modelData->modelIDs.Insert(modelindex, queryModel);
|
||||||
mobj->modelData->modelFrameGenerators.Insert(modelindex, generatorindex);
|
mobj->modelData->modelFrameGenerators.Insert(modelindex, generatorindex);
|
||||||
|
mobj->modelData->animationIDs.Insert(animationindex, queryAnimation);
|
||||||
if (flags & CMDL_USESURFACESKIN)
|
if (flags & CMDL_USESURFACESKIN)
|
||||||
mobj->modelData->surfaceSkinIDs.Insert(skinPosition, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID());
|
mobj->modelData->surfaceSkinIDs.Insert(skinPosition, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID());
|
||||||
else
|
else
|
||||||
|
@ -5131,6 +5146,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
|
|
||||||
if(allowPush) savedModelFiles.Push(fullName);
|
if(allowPush) savedModelFiles.Push(fullName);
|
||||||
}
|
}
|
||||||
|
//Same for animations
|
||||||
|
if (queryAnimation >= 0)
|
||||||
|
{
|
||||||
|
FString fullName;
|
||||||
|
fullName.Format("%s%s", animationpath.GetChars(), animation.GetChars());
|
||||||
|
bool allowPush = true;
|
||||||
|
for (unsigned i = 0; i < savedModelFiles.Size(); i++) if (!savedModelFiles[i].CompareNoCase(fullName)) allowPush = false;
|
||||||
|
for (unsigned i = 0; i < Models.Size() - 1; i++) if (!Models[i]->mFileName.CompareNoCase(fullName)) allowPush = false;
|
||||||
|
|
||||||
|
if (allowPush) savedModelFiles.Push(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
//[SM] - if an indice of modelIDs or skinIDs comes up blank and it's the last one, just delete it. For using very large amounts of indices, common sense says to just not run this repeatedly.
|
//[SM] - if an indice of modelIDs or skinIDs comes up blank and it's the last one, just delete it. For using very large amounts of indices, common sense says to just not run this repeatedly.
|
||||||
while (mobj->modelData->modelIDs.Size() > 0 && mobj->modelData->modelIDs.Last() == -1)
|
while (mobj->modelData->modelIDs.Size() > 0 && mobj->modelData->modelIDs.Last() == -1)
|
||||||
|
@ -5141,14 +5167,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs.Last());
|
mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs.Last());
|
||||||
while (mobj->modelData->surfaceSkinIDs.Size() > 0 && mobj->modelData->surfaceSkinIDs.Last() == FNullTextureID())
|
while (mobj->modelData->surfaceSkinIDs.Size() > 0 && mobj->modelData->surfaceSkinIDs.Last() == FNullTextureID())
|
||||||
mobj->modelData->surfaceSkinIDs.Pop(mobj->modelData->surfaceSkinIDs.Last());
|
mobj->modelData->surfaceSkinIDs.Pop(mobj->modelData->surfaceSkinIDs.Last());
|
||||||
|
while (mobj->modelData->animationIDs.Size() > 0 && mobj->modelData->animationIDs.Last() == -1)
|
||||||
|
mobj->modelData->animationIDs.Pop(mobj->modelData->animationIDs.Last());
|
||||||
|
|
||||||
if (mobj->modelData->modelIDs.Size() == 0 && mobj->modelData->modelFrameGenerators.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && mobj->modelData->surfaceSkinIDs.Size() == 0 && modeldef == NAME_None)
|
if (mobj->modelData->modelIDs.Size() == 0 && mobj->modelData->modelFrameGenerators.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && mobj->modelData->surfaceSkinIDs.Size() == 0 && mobj->modelData->animationIDs.Size() == 0 && modeldef == NAME_None)
|
||||||
{
|
{
|
||||||
mobj->hasmodel = mobj->modelData->hasModel;
|
mobj->hasmodel = mobj->modelData->hasModel;
|
||||||
mobj->modelData->modelIDs.Reset();
|
mobj->modelData->modelIDs.Reset();
|
||||||
mobj->modelData->modelFrameGenerators.Reset();
|
mobj->modelData->modelFrameGenerators.Reset();
|
||||||
mobj->modelData->skinIDs.Reset();
|
mobj->modelData->skinIDs.Reset();
|
||||||
mobj->modelData->surfaceSkinIDs.Reset();
|
mobj->modelData->surfaceSkinIDs.Reset();
|
||||||
|
mobj->modelData->animationIDs.Reset();
|
||||||
mobj->modelData->Destroy();
|
mobj->modelData->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1370,6 +1370,7 @@ void DActorModelData::Serialize(FSerializer& arc)
|
||||||
("modelIDs", modelIDs)
|
("modelIDs", modelIDs)
|
||||||
("skinIDs", skinIDs)
|
("skinIDs", skinIDs)
|
||||||
("surfaceSkinIDs", surfaceSkinIDs)
|
("surfaceSkinIDs", surfaceSkinIDs)
|
||||||
|
("animationIDs", animationIDs)
|
||||||
("modelFrameGenerators", modelFrameGenerators)
|
("modelFrameGenerators", modelFrameGenerators)
|
||||||
("hasModel", hasModel);
|
("hasModel", hasModel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,9 +286,12 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
||||||
|
|
||||||
TArray<FTextureID> surfaceskinids;
|
TArray<FTextureID> surfaceskinids;
|
||||||
|
|
||||||
|
TArray<VSMatrix> boneData = TArray<VSMatrix>();
|
||||||
|
|
||||||
for (int i = 0; i < modelsamount; i++)
|
for (int i = 0; i < modelsamount; i++)
|
||||||
{
|
{
|
||||||
int modelid = -1;
|
int modelid = -1;
|
||||||
|
int animationid = -1;
|
||||||
int modelframe = -1;
|
int modelframe = -1;
|
||||||
int modelframenext = -1;
|
int modelframenext = -1;
|
||||||
FTextureID skinid; skinid.SetInvalid();
|
FTextureID skinid; skinid.SetInvalid();
|
||||||
|
@ -299,10 +302,13 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
||||||
if (i < (int)actor->modelData->modelIDs.Size())
|
if (i < (int)actor->modelData->modelIDs.Size())
|
||||||
modelid = actor->modelData->modelIDs[i];
|
modelid = actor->modelData->modelIDs[i];
|
||||||
|
|
||||||
|
if (i < (int)actor->modelData->animationIDs.Size())
|
||||||
|
animationid = actor->modelData->animationIDs[i];
|
||||||
|
|
||||||
if (i < (int)actor->modelData->modelFrameGenerators.Size())
|
if (i < (int)actor->modelData->modelFrameGenerators.Size())
|
||||||
{
|
{
|
||||||
//[SM] - We will use this little snippet to allow a modder to specify a model index to clone. It's also pointless to clone something that clones something else in this case. And causes me headaches.
|
//[SM] - We will use this little snippet to allow a modder to specify a model index to clone. It's also pointless to clone something that clones something else in this case. And causes me headaches.
|
||||||
if (actor->modelData->modelFrameGenerators[i] >= 0 && smf->modelframes.Size() < (unsigned)i && smf->modelframes[i] != -1)
|
if (actor->modelData->modelFrameGenerators[i] >= 0 && actor->modelData->modelFrameGenerators[i] <= modelsamount && smf->modelframes[actor->modelData->modelFrameGenerators[i]] != -1)
|
||||||
{
|
{
|
||||||
modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]];
|
modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||||
if (smfNext) modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]];
|
if (smfNext) modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||||
|
@ -329,6 +335,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
||||||
if (i < smf->modelsAmount)
|
if (i < smf->modelsAmount)
|
||||||
{
|
{
|
||||||
if (modelid == -1) modelid = smf->modelIDs[i];
|
if (modelid == -1) modelid = smf->modelIDs[i];
|
||||||
|
if (animationid == -1) animationid = smf->animationIDs[i];
|
||||||
if (modelframe == -1) modelframe = smf->modelframes[i];
|
if (modelframe == -1) modelframe = smf->modelframes[i];
|
||||||
if (modelframenext == -1 && smfNext) modelframenext = smfNext->modelframes[i];
|
if (modelframenext == -1 && smfNext) modelframenext = smfNext->modelframes[i];
|
||||||
if (!skinid.isValid()) skinid = smf->skinIDs[i];
|
if (!skinid.isValid()) skinid = smf->skinIDs[i];
|
||||||
|
@ -345,16 +352,26 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
||||||
|
|
||||||
const TArray<VSMatrix>* animationData = nullptr;
|
const TArray<VSMatrix>* animationData = nullptr;
|
||||||
|
|
||||||
if (smf->animationIDs[i] >= 0)
|
bool attachments = smf->flags & MDL_MODELSAREATTACHMENTS;
|
||||||
|
bool nextFrame = smfNext && modelframe != modelframenext;
|
||||||
|
bool hasExternAnimation = false;
|
||||||
|
|
||||||
|
if (animationid >= 0)
|
||||||
{
|
{
|
||||||
FModel* animation = Models[smf->animationIDs[i]];
|
FModel* animation = Models[animationid];
|
||||||
animationData = animation->AttachAnimationData();
|
animationData = animation->AttachAnimationData();
|
||||||
|
if(!attachments || boneData.Size() == 0)
|
||||||
|
boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData);
|
||||||
|
|
||||||
|
hasExternAnimation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!hasExternAnimation) boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData);
|
||||||
|
|
||||||
if (smfNext && modelframe != modelframenext)
|
if (smfNext && modelframe != modelframenext)
|
||||||
mdl->RenderFrame(renderer, tex, modelframe, modelframenext, inter, translation, ssidp, *animationData);
|
mdl->RenderFrame(renderer, tex, modelframe, modelframenext, inter, translation, ssidp, boneData);
|
||||||
else
|
else
|
||||||
mdl->RenderFrame(renderer, tex, modelframe, modelframe, 0.f, translation, ssidp, *animationData);
|
mdl->RenderFrame(renderer, tex, modelframe, modelframe, 0.f, translation, ssidp, boneData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,6 +646,10 @@ static void ParseModelDefLump(int Lump)
|
||||||
{
|
{
|
||||||
smf.flags |= MDL_SCALEWEAPONFOV;
|
smf.flags |= MDL_SCALEWEAPONFOV;
|
||||||
}
|
}
|
||||||
|
else if (sc.Compare("modelsareattachments"))
|
||||||
|
{
|
||||||
|
smf.flags |= MDL_MODELSAREATTACHMENTS;
|
||||||
|
}
|
||||||
else if (sc.Compare("rotating"))
|
else if (sc.Compare("rotating"))
|
||||||
{
|
{
|
||||||
smf.flags |= MDL_ROTATING;
|
smf.flags |= MDL_ROTATING;
|
||||||
|
|
|
@ -57,6 +57,7 @@ enum
|
||||||
MDL_USEROTATIONCENTER = 512,
|
MDL_USEROTATIONCENTER = 512,
|
||||||
MDL_NOPERPIXELLIGHTING = 1024, // forces a model to not use per-pixel lighting. useful for voxel-converted-to-model objects.
|
MDL_NOPERPIXELLIGHTING = 1024, // forces a model to not use per-pixel lighting. useful for voxel-converted-to-model objects.
|
||||||
MDL_SCALEWEAPONFOV = 2048, // scale weapon view model with higher user FOVs
|
MDL_SCALEWEAPONFOV = 2048, // scale weapon view model with higher user FOVs
|
||||||
|
MDL_MODELSAREATTACHMENTS = 4096, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0
|
||||||
};
|
};
|
||||||
|
|
||||||
FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
|
FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ class Actor : Thinker native
|
||||||
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.);
|
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.);
|
||||||
deprecated("2.3", "Use 'b<FlagName> = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value);
|
deprecated("2.3", "Use 'b<FlagName> = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value);
|
||||||
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
||||||
action native void A_ChangeModel(name modeldef, int modelindex = 0, string modelpath = "", name model = "", int skinindex = 0, string skinpath = "", name skin = "", int flags = 0, int generatorindex = -1);
|
action native void A_ChangeModel(name modeldef, int modelindex = 0, string modelpath = "", name model = "", int skinindex = 0, string skinpath = "", name skin = "", int flags = 0, int generatorindex = -1, int animationindex = 0, string animationpath = "", name animation = "");
|
||||||
|
|
||||||
void A_SetFriendly (bool set)
|
void A_SetFriendly (bool set)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue