Bone Getters Part 2/3, plus fixed warnings for MSVC
* add getters for frame poses * fix missing joint in GetJointPose * clean up models_iqm.cpp * clean up usage of I_GetTimeFrac, split out matrix calculation into its own function * clean up SetModelBoneRotationInternal * clean up a few float <-> double and unsigned <-> signed warnings * fix more warnings * further clean up warnings * split mode ObjectToWorldMatrix stuff * initial work on bone getters, matrix hell (the matrix/vec3 multiplications are probably wrong af, just gotta add more stuff 'till i can test it) * clean up matrix math * GetBone/TransformByBone * fix GetBoneFramePose * fix ObjectToWorldMatrix * fix missing array resize * raw matrix getters (for use with gutamatics/etc) * reverse matrix mult order * replace GetBoneLength/GetBoneDir with GetBoneBaseTRS * fix GetBonePosition, remove GetBoneWorldMatrix as it's useless * GetBonePosition * deduplicate code * rename GetBonePosition to GetBoneBasePosition to avoid confusion * GetBoneBaseRotation * GetBonePosition helper function * forgot include_offsets
This commit is contained in:
parent
9eaf472071
commit
9e2b1f9c4c
37 changed files with 1109 additions and 261 deletions
|
|
@ -59,32 +59,42 @@ EXTERN_CVAR (Bool, r_drawvoxels)
|
|||
extern TDeletingArray<FVoxel *> Voxels;
|
||||
extern TDeletingArray<FVoxelDef *> VoxelDefs;
|
||||
|
||||
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, FTranslationID translation, AActor* actor);
|
||||
|
||||
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, int curTics, double tic, FTranslationID translation, AActor* actor);
|
||||
|
||||
void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac)
|
||||
{
|
||||
// Setup transformation.
|
||||
|
||||
int smf_flags = smf->getFlags(actor->modelData);
|
||||
|
||||
FTranslationID translation = NO_TRANSLATION;
|
||||
if (!(smf_flags & MDL_IGNORETRANSLATION))
|
||||
translation = actor->Translation;
|
||||
|
||||
// y scale for a sprite means height, i.e. z in the world!
|
||||
VSMatrix objectToWorldMatrix = smf->ObjectToWorldMatrix(actor, x, y, z, ticFrac);
|
||||
|
||||
float scaleFactorX = actor->Scale.X * smf->xscale;
|
||||
float scaleFactorY = actor->Scale.X * smf->yscale;
|
||||
float scaleFactorZ = actor->Scale.Y * smf->zscale;
|
||||
float pitch = 0;
|
||||
float roll = 0;
|
||||
double rotateOffset = 0;
|
||||
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
|
||||
|
||||
renderer->BeginDrawModel(actor->RenderStyle, smf_flags, objectToWorldMatrix, orientation < 0);
|
||||
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, ticFrac, translation, actor);
|
||||
renderer->EndDrawModel(actor->RenderStyle, smf_flags);
|
||||
}
|
||||
|
||||
VSMatrix FSpriteModelFrame::ObjectToWorldMatrix(AActor * actor, float x, float y, float z, double ticFrac)
|
||||
{
|
||||
int smf_flags = getFlags(actor->modelData);
|
||||
|
||||
// Setup transformation.
|
||||
DRotator angles;
|
||||
|
||||
if (actor->renderflags & RF_INTERPOLATEANGLES) // [Nash] use interpolated angles
|
||||
angles = actor->InterpolatedAngles(ticFrac);
|
||||
else
|
||||
angles = actor->Angles;
|
||||
|
||||
float angle = angles.Yaw.Degrees();
|
||||
float pitch = 0;
|
||||
float roll = 0;
|
||||
|
||||
// [BB] Workaround for the missing pitch information.
|
||||
if ((smf_flags & MDL_PITCHFROMMOMENTUM))
|
||||
|
|
@ -107,20 +117,6 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
|
|||
}
|
||||
}
|
||||
|
||||
if (smf_flags & MDL_ROTATING)
|
||||
{
|
||||
if (smf->rotationSpeed > 0.0000000001 || smf->rotationSpeed < -0.0000000001)
|
||||
{
|
||||
double turns = (I_GetTime() + I_GetTimeFrac()) / (200.0 / smf->rotationSpeed);
|
||||
turns -= floor(turns);
|
||||
rotateOffset = turns * 360.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotateOffset = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
|
||||
// If both flags MDL_USEACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the velocity vector pitch.
|
||||
if (smf_flags & MDL_USEACTORPITCH)
|
||||
|
|
@ -131,75 +127,116 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
|
|||
}
|
||||
if (smf_flags & MDL_USEACTORROLL) roll += angles.Roll.Degrees();
|
||||
|
||||
// [Nash] take SpriteRotation into account
|
||||
angle += actor->SpriteRotation.Degrees();
|
||||
|
||||
double tic = actor->Level->totaltime;
|
||||
|
||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen())
|
||||
{
|
||||
tic += ticFrac;
|
||||
}
|
||||
|
||||
return ObjectToWorldMatrix(actor->Level, DVector3(x, y, z), DRotator(DAngle::fromDeg(pitch), DAngle::fromDeg(angle), DAngle::fromDeg(roll)), actor->Scale, smf_flags, tic);
|
||||
}
|
||||
|
||||
VSMatrix FSpriteModelFrame::ObjectToWorldMatrix(FLevelLocals *Level, DVector3 translation, DRotator rotation, DVector2 scaling, unsigned int flags, double tic)
|
||||
{
|
||||
double rotateOffset = 0;
|
||||
|
||||
if (flags & MDL_ROTATING)
|
||||
{
|
||||
if (rotationSpeed > 0.0000000001 || rotationSpeed < -0.0000000001)
|
||||
{
|
||||
double turns = (tic) / (200.0 / rotationSpeed);
|
||||
turns -= floor(turns);
|
||||
rotateOffset = turns * 360.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotateOffset = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// y scale for a sprite means height, i.e. z in the world!
|
||||
float scaleFactorX = scaling.X * xscale;
|
||||
float scaleFactorY = scaling.X * yscale;
|
||||
float scaleFactorZ = scaling.Y * zscale;
|
||||
|
||||
VSMatrix objectToWorldMatrix;
|
||||
objectToWorldMatrix.loadIdentity();
|
||||
|
||||
// Model space => World space
|
||||
objectToWorldMatrix.translate(x, z, y);
|
||||
|
||||
// [Nash] take SpriteRotation into account
|
||||
angle += actor->SpriteRotation.Degrees();
|
||||
objectToWorldMatrix.translate(translation.X, translation.Z, translation.Y);
|
||||
|
||||
// consider the pixel stretching. For non-voxels this must be factored out here
|
||||
float stretch = 1.f;
|
||||
|
||||
// [MK] distortions might happen depending on when the pixel stretch is compensated for
|
||||
// so we make the "undistorted" behavior opt-in
|
||||
if ((smf_flags & MDL_CORRECTPIXELSTRETCH) && smf->modelIDs.Size() > 0)
|
||||
if ((flags & MDL_CORRECTPIXELSTRETCH) && modelIDs.Size() > 0)
|
||||
{
|
||||
stretch = (smf->modelIDs[0] >= 0 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch;
|
||||
stretch = (modelIDs[0] >= 0 ? Models[modelIDs[0]]->getAspectFactor(Level->info->pixelstretch) : 1.f) / Level->info->pixelstretch;
|
||||
objectToWorldMatrix.scale(1, stretch, 1);
|
||||
}
|
||||
|
||||
// Applying model transformations:
|
||||
// 1) Applying actor angle, pitch and roll to the model
|
||||
if (smf_flags & MDL_USEROTATIONCENTER)
|
||||
if (flags & MDL_USEROTATIONCENTER)
|
||||
{
|
||||
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterZ/stretch, smf->rotationCenterY);
|
||||
}
|
||||
objectToWorldMatrix.rotate(-angle, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(pitch, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-roll, 1, 0, 0);
|
||||
if (smf_flags & MDL_USEROTATIONCENTER)
|
||||
{
|
||||
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ/stretch, -smf->rotationCenterY);
|
||||
}
|
||||
objectToWorldMatrix.translate(rotationCenterX, rotationCenterY/stretch, rotationCenterZ);
|
||||
|
||||
// 2) Applying Doomsday like rotation of the weapon pickup models
|
||||
// The rotation angle is based on the elapsed time.
|
||||
objectToWorldMatrix.rotate(-rotation.Yaw.Degrees(), 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(rotation.Pitch.Degrees(), 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-rotation.Roll.Degrees(), 1, 0, 0);
|
||||
|
||||
if (smf_flags & MDL_ROTATING)
|
||||
// 2) Applying Doomsday like rotation of the weapon pickup models
|
||||
// The rotation angle is based on the elapsed time.
|
||||
if(flags & MDL_ROTATING)
|
||||
{
|
||||
objectToWorldMatrix.rotate(rotateOffset, xrotate, yrotate, zrotate);
|
||||
}
|
||||
|
||||
objectToWorldMatrix.translate(-rotationCenterX, -rotationCenterY/stretch, -rotationCenterZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY/stretch, smf->rotationCenterZ);
|
||||
objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate);
|
||||
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterY/stretch, -smf->rotationCenterZ);
|
||||
objectToWorldMatrix.rotate(-rotation.Yaw.Degrees(), 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(rotation.Pitch.Degrees(), 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-rotation.Roll.Degrees(), 1, 0, 0);
|
||||
|
||||
|
||||
// 2) Applying Doomsday like rotation of the weapon pickup models
|
||||
// The rotation angle is based on the elapsed time.
|
||||
if(flags & MDL_ROTATING)
|
||||
{
|
||||
objectToWorldMatrix.translate(rotationCenterX, rotationCenterY/stretch, rotationCenterZ);
|
||||
objectToWorldMatrix.rotate(rotateOffset, xrotate, yrotate, zrotate);
|
||||
objectToWorldMatrix.translate(-rotationCenterX, -rotationCenterY/stretch, -rotationCenterZ);
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Scaling model.
|
||||
objectToWorldMatrix.scale(scaleFactorX, scaleFactorZ, scaleFactorY);
|
||||
|
||||
// 4) Aplying model offsets (model offsets do not depend on model scalings).
|
||||
objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / (smf->zscale*stretch), smf->yoffset / smf->yscale);
|
||||
objectToWorldMatrix.translate(xoffset / xscale, zoffset / (zscale*stretch), yoffset / yscale);
|
||||
|
||||
// 5) Applying model rotations.
|
||||
objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
|
||||
objectToWorldMatrix.rotate(-angleoffset, 0, 1, 0);
|
||||
objectToWorldMatrix.rotate(pitchoffset, 0, 0, 1);
|
||||
objectToWorldMatrix.rotate(-rolloffset, 1, 0, 0);
|
||||
|
||||
if (!(smf_flags & MDL_CORRECTPIXELSTRETCH) && smf->modelIDs.Size() > 0)
|
||||
if (!(flags & MDL_CORRECTPIXELSTRETCH) && modelIDs.Size() > 0)
|
||||
{
|
||||
stretch = (smf->modelIDs[0] >= 0 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch;
|
||||
stretch = (modelIDs[0] >= 0 ? Models[modelIDs[0]]->getAspectFactor(Level->info->pixelstretch) : 1.f) / Level->info->pixelstretch;
|
||||
objectToWorldMatrix.scale(1, stretch, 1);
|
||||
}
|
||||
|
||||
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
|
||||
|
||||
renderer->BeginDrawModel(actor->RenderStyle, smf_flags, objectToWorldMatrix, orientation < 0);
|
||||
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, translation, actor);
|
||||
renderer->EndDrawModel(actor->RenderStyle, smf_flags);
|
||||
return objectToWorldMatrix;
|
||||
}
|
||||
|
||||
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf)
|
||||
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf, double ticFrac)
|
||||
{
|
||||
AActor * playermo = players[consoleplayer].camera;
|
||||
|
||||
|
|
@ -256,7 +293,7 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
|
|||
auto trans = psp->GetTranslation();
|
||||
if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation;
|
||||
|
||||
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), trans, psp->Caller);
|
||||
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), ticFrac, trans, psp->Caller);
|
||||
renderer->EndDrawHUDModel(playermo->RenderStyle, smf_flags);
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +350,7 @@ void calcFrames(const ModelAnim &curAnim, double tic, ModelAnimFrameInterp &to,
|
|||
}
|
||||
}
|
||||
|
||||
CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* data, AActor* actor, bool is_decoupled, double tic)
|
||||
CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* data, AActor* actor, bool is_decoupled, double tic, double ticFrac)
|
||||
{
|
||||
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
|
||||
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
|
||||
|
|
@ -348,8 +385,9 @@ CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *
|
|||
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
|
||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !Level->isFrozen())
|
||||
{
|
||||
ticFraction = I_GetTimeFrac();
|
||||
ticFraction = ticFrac;
|
||||
}
|
||||
|
||||
inter = static_cast<double>(curState->Tics - curTics + ticFraction) / static_cast<double>(curState->Tics);
|
||||
|
||||
// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
|
||||
|
|
@ -413,11 +451,11 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
|
|||
if (data)
|
||||
{
|
||||
//modelID
|
||||
if (data->models.Size() > i && data->models[i].modelID >= 0)
|
||||
if (data->models.SSize() > i && data->models[i].modelID >= 0)
|
||||
{
|
||||
out.modelid = data->models[i].modelID;
|
||||
}
|
||||
else if(data->models.Size() > i && data->models[i].modelID == -2)
|
||||
else if(data->models.SSize() > i && data->models[i].modelID == -2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -427,7 +465,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
|
|||
}
|
||||
|
||||
//animationID
|
||||
if (data->animationIDs.Size() > i && data->animationIDs[i] >= 0)
|
||||
if (data->animationIDs.SSize() > i && data->animationIDs[i] >= 0)
|
||||
{
|
||||
out.animationid = data->animationIDs[i];
|
||||
}
|
||||
|
|
@ -438,7 +476,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
|
|||
if(!is_decoupled)
|
||||
{
|
||||
//modelFrame
|
||||
if (data->modelFrameGenerators.Size() > i
|
||||
if (data->modelFrameGenerators.SSize() > i
|
||||
&& (unsigned)data->modelFrameGenerators[i] < info.modelsamount
|
||||
&& smf->modelframes[data->modelFrameGenerators[i]] >= 0
|
||||
) {
|
||||
|
|
@ -464,7 +502,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
|
|||
}
|
||||
|
||||
//skinID
|
||||
if (data->skinIDs.Size() > i && data->skinIDs[i].isValid())
|
||||
if (data->skinIDs.SSize() > i && data->skinIDs[i].isValid())
|
||||
{
|
||||
out.skinid = data->skinIDs[i];
|
||||
}
|
||||
|
|
@ -474,7 +512,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
|
|||
}
|
||||
|
||||
//surfaceSkinIDs
|
||||
if(data->models.Size() > i && data->models[i].surfaceSkinIDs.Size() > 0)
|
||||
if(data->models.SSize() > i && data->models[i].surfaceSkinIDs.SSize() > 0)
|
||||
{
|
||||
unsigned sz1 = smf->surfaceskinIDs.Size();
|
||||
unsigned sz2 = data->models[i].surfaceSkinIDs.Size();
|
||||
|
|
@ -534,7 +572,7 @@ const TArray<VSMatrix> * ProcessModelFrame(FModel * animation, bool nextFrame, i
|
|||
frameinfo.decoupled_frame,
|
||||
frameinfo.inter,
|
||||
animationData,
|
||||
modelData->modelBoneOverrides.Size() > i
|
||||
modelData->modelBoneOverrides.SSize() > i
|
||||
? &modelData->modelBoneOverrides[i]
|
||||
: nullptr,
|
||||
out,
|
||||
|
|
@ -552,7 +590,7 @@ const TArray<VSMatrix> * ProcessModelFrame(FModel * animation, bool nextFrame, i
|
|||
},
|
||||
-1.0f,
|
||||
animationData,
|
||||
(modelData && modelData->modelBoneOverrides.Size() > i)
|
||||
(modelData && modelData->modelBoneOverrides.SSize() > i)
|
||||
? &modelData->modelBoneOverrides[i]
|
||||
: nullptr,
|
||||
out,
|
||||
|
|
@ -570,7 +608,7 @@ static inline void RenderModelFrame(FModelRenderer *renderer, int i, const FSpri
|
|||
|
||||
auto ssidp = drawinfo.surfaceskinids.Size() > 0
|
||||
? drawinfo.surfaceskinids.Data()
|
||||
: (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr);
|
||||
: (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.SSize()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr);
|
||||
|
||||
bool nextFrame = frameinfo.smfNext && drawinfo.modelframe != drawinfo.modelframenext;
|
||||
|
||||
|
|
@ -589,19 +627,19 @@ static inline void RenderModelFrame(FModelRenderer *renderer, int i, const FSpri
|
|||
mdl->RenderFrame(renderer, tex, drawinfo.modelframe, nextFrame ? drawinfo.modelframenext : drawinfo.modelframe, nextFrame ? frameinfo.inter : -1.f, translation, ssidp, boneStartingPosition);
|
||||
}
|
||||
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, int curTics, double ticFrac, FTranslationID translation, AActor* actor)
|
||||
{
|
||||
double tic = actor->Level->totaltime;
|
||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen())
|
||||
{
|
||||
tic += I_GetTimeFrac();
|
||||
tic += ticFrac;
|
||||
}
|
||||
|
||||
bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS);
|
||||
|
||||
DActorModelData* modelData = actor ? actor->modelData.ForceGet() : nullptr;
|
||||
|
||||
CalcModelFrameInfo frameinfo = CalcModelFrame(Level, smf, curState, curTics, modelData, actor, is_decoupled, tic);
|
||||
CalcModelFrameInfo frameinfo = CalcModelFrame(Level, smf, curState, curTics, modelData, actor, is_decoupled, tic, ticFrac);
|
||||
ModelDrawInfo drawinfo;
|
||||
|
||||
int boneStartingPosition = -1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue