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
db8bdab669
commit
d5f5c71d67
33 changed files with 1065 additions and 220 deletions
|
|
@ -307,7 +307,7 @@ bool Wiper_Crossfade::Run(int ticks)
|
|||
|
||||
bool Wiper_Crossfade::RunInterpolated(double ticks)
|
||||
{
|
||||
Clock += ticks;
|
||||
Clock += float(ticks);
|
||||
DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE);
|
||||
return Clock >= 32.;
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ public:
|
|||
const char* GetHash() const { return Hash; }
|
||||
|
||||
int EntryCount() const { return NumLumps; }
|
||||
uint32_t EntryCountU() const { return NumLumps; }
|
||||
int FindEntry(const char* name);
|
||||
|
||||
size_t Length(uint32_t entry)
|
||||
|
|
|
|||
|
|
@ -67,13 +67,13 @@ struct BoneOverrideComponent
|
|||
void Modify(T &value, double tic) const
|
||||
{
|
||||
|
||||
double lerp_amt = interplen > 0.0 ? std::clamp(((tic - switchtic) / interplen), 0.0, 1.0) : 1.0;
|
||||
float lerp_amt = interplen > 0.0f ? std::clamp(float((tic - switchtic) / interplen), 0.0f, 1.0f) : 1.0f;
|
||||
|
||||
if(mode > 0 || (prev_mode > 0 && lerp_amt < 1.0))
|
||||
{
|
||||
T from = ModifyValue(value, prev, prev_mode);
|
||||
T to = ModifyValue(value, cur, mode);
|
||||
value = Lerp(from, to, lerp_amt, 1.0 - lerp_amt);
|
||||
value = Lerp(from, to, lerp_amt, 1.0f - lerp_amt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,9 +126,10 @@ struct BoneOverride
|
|||
|
||||
struct BoneInfo
|
||||
{
|
||||
TArray<TRS> bones_anim_only;
|
||||
TArray<TRS> bones;
|
||||
TArray<TRS> bones_with_override;
|
||||
TArray<VSMatrix> positions;
|
||||
TArray<VSMatrix> positions_with_override;
|
||||
};
|
||||
|
||||
struct ModelAnim
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ class FGameTexture;
|
|||
class IModelVertexBuffer;
|
||||
class FModel;
|
||||
class PClass;
|
||||
class AActor;
|
||||
struct FSpriteModelFrame;
|
||||
struct FLevelLocals;
|
||||
|
||||
FTextureID LoadSkin(const char* path, const char* fn);
|
||||
void FlushModels();
|
||||
|
|
@ -59,6 +61,9 @@ public:
|
|||
unsigned int getFlags(class DActorModelData * defs) const;
|
||||
friend void InitModels();
|
||||
friend void ParseModelDefLump(int Lump);
|
||||
|
||||
VSMatrix ObjectToWorldMatrix(AActor * actor, float x, float y, float z, double ticFrac);
|
||||
VSMatrix ObjectToWorldMatrix(FLevelLocals *Level, DVector3 translation, DRotator rotation, DVector2 scaling, unsigned int flags, double tic);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -92,9 +97,12 @@ public:
|
|||
virtual int FindJoint(FName name) { return -1; }
|
||||
|
||||
virtual int GetJointParent(int joint) { return -1; }
|
||||
virtual double GetJointLength(int joint) { return 0.0; }
|
||||
virtual FName GetJointName(int joint) { return NAME_None; }
|
||||
virtual FVector3 GetJointDir(int joint) { return FVector3(0.0f,0.0f,0.0f); }
|
||||
virtual FQuaternion GetJointRotation(int joint) { return FQuaternion(0.0f,0.0f,0.0f,1.0f); }
|
||||
virtual FVector3 GetJointPosition(int joint) { return FVector3(0.0f,0.0f,0.0f); }
|
||||
virtual TRS GetJointBaseTRS(int joint) { return {}; }
|
||||
virtual TRS GetJointPose(int joint, int frame) { return {}; }
|
||||
virtual int NumFrames() { return -1; }
|
||||
|
||||
virtual void GetJointChildren(int joint, TArray<int> &out) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ struct IQMJoint
|
|||
FVector3 Translate;
|
||||
FQuaternion Quaternion;
|
||||
FVector3 Scale;
|
||||
FVector3 Position;
|
||||
FQuaternion Rotation;
|
||||
FVector3 Scaling;
|
||||
};
|
||||
|
||||
struct IQMPose
|
||||
|
|
@ -164,7 +167,7 @@ private:
|
|||
TArray<VSMatrix> inversebaseframe;
|
||||
TArray<TRS> TRSData;
|
||||
public:
|
||||
int NumJoints() override { return Joints.Size(); }
|
||||
int NumJoints() override { return Joints.SSize(); }
|
||||
int FindJoint(FName name) override
|
||||
{
|
||||
int *j = NamedJoints.CheckKey(name);
|
||||
|
|
@ -174,12 +177,12 @@ public:
|
|||
|
||||
int GetJointParent(int joint) override
|
||||
{
|
||||
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Parent : -1;
|
||||
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Parent : -1;
|
||||
}
|
||||
|
||||
FName GetJointName(int joint) override
|
||||
{
|
||||
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Name : FName(NAME_None);
|
||||
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Name : FName(NAME_None);
|
||||
}
|
||||
|
||||
void GetRootJoints(TArray<int> &out) override
|
||||
|
|
@ -189,20 +192,34 @@ public:
|
|||
|
||||
void GetJointChildren(int joint, TArray<int> &out) override
|
||||
{
|
||||
if(joint >= 0 && joint < Joints.Size())
|
||||
if(joint >= 0 && joint < Joints.SSize())
|
||||
{
|
||||
out = Joints[joint].Children;
|
||||
}
|
||||
}
|
||||
|
||||
double GetJointLength(int joint) override
|
||||
FQuaternion GetJointRotation(int joint) override
|
||||
{
|
||||
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Translate.Length() : 0.0;
|
||||
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Rotation : FQuaternion(0.0f,0.0f,0.0f,1.0f);
|
||||
}
|
||||
|
||||
FVector3 GetJointDir(int joint) override
|
||||
FVector3 GetJointPosition(int joint) override
|
||||
{
|
||||
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Translate.Unit() : FVector3(0.0f,0.0f,0.0f);
|
||||
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Position : FVector3(0.0f,0.0f,0.0f);
|
||||
}
|
||||
|
||||
TRS GetJointBaseTRS(int joint) override
|
||||
{
|
||||
return (joint >= 0 && joint < Joints.SSize()) ? TRS{Joints[joint].Translate, Joints[joint].Quaternion, Joints[joint].Scale} : TRS{};
|
||||
}
|
||||
|
||||
TRS GetJointPose(int joint, int frame) override
|
||||
{
|
||||
return (joint >= 0 && joint < Joints.SSize() && frame >= 0 && ((frame * Joints.SSize()) + joint) < TRSData.SSize()) ? TRSData[(frame * Joints.SSize()) + joint] : TRS{} ;
|
||||
}
|
||||
virtual int NumFrames()
|
||||
{
|
||||
return Joints.SSize() > 0 ? (TRSData.SSize() / Joints.SSize()) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
|
|||
}
|
||||
|
||||
reader.SeekTo(ofs_joints);
|
||||
for (int i = 0; i < Joints.Size(); i++)
|
||||
for (int i = 0; i < Joints.SSize(); i++)
|
||||
{
|
||||
IQMJoint& joint = Joints[i];
|
||||
|
||||
|
|
@ -126,8 +126,6 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
|
|||
joint.Translate.Y = reader.ReadFloat();
|
||||
joint.Translate.Z = reader.ReadFloat();
|
||||
|
||||
int len = joint.Translate.Length();
|
||||
|
||||
joint.Quaternion.X = reader.ReadFloat();
|
||||
joint.Quaternion.Y = reader.ReadFloat();
|
||||
joint.Quaternion.Z = reader.ReadFloat();
|
||||
|
|
@ -139,14 +137,24 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
|
|||
|
||||
if(joint.Parent < 0)
|
||||
{
|
||||
joint.Rotation = joint.Quaternion;
|
||||
joint.Scaling = joint.Scale;
|
||||
joint.Position = joint.Translate.ScaleXYZ(joint.Scaling);
|
||||
RootJoints.Push(i);
|
||||
}
|
||||
else if(joint.Parent >= Joints.Size())
|
||||
else if(joint.Parent >= i)
|
||||
{
|
||||
I_FatalError("Joint child comes before parent in IQM Model");
|
||||
}
|
||||
else if(joint.Parent >= Joints.SSize())
|
||||
{
|
||||
I_FatalError("Joint parent index out of bounds in IQM Model");
|
||||
}
|
||||
else
|
||||
{
|
||||
joint.Rotation = (Joints[joint.Parent].Rotation * joint.Quaternion).Unit();
|
||||
joint.Scaling = joint.Scale.ScaleXYZ(Joints[joint.Parent].Scaling);
|
||||
joint.Position = (Joints[joint.Parent].Rotation * joint.Translate.ScaleXYZ(joint.Scaling)) + Joints[joint.Parent].Position;
|
||||
Joints[joint.Parent].Children.Push(i);
|
||||
}
|
||||
}
|
||||
|
|
@ -618,11 +626,6 @@ const TArray<VSMatrix>* IQMModel::CalculateBones(const ModelAnimFrame &from, con
|
|||
}
|
||||
}
|
||||
|
||||
inline void ModifyBone(const BoneOverride& mod, TRS &bone, double time)
|
||||
{
|
||||
mod.Modify(bone, time);
|
||||
}
|
||||
|
||||
// explicitly don't pass modelBoneOverrides when precalculating animation for interpolation, as it's applied _after_ animation
|
||||
ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray<TRS>* animationData)
|
||||
{
|
||||
|
|
@ -682,15 +685,16 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
|
|||
{
|
||||
const TArray<TRS>& animationFrames = animationData ? *animationData : TRSData;
|
||||
|
||||
TArray<VSMatrix>* outMatrix = out ? &out->positions : &boneData;
|
||||
TArray<VSMatrix>* outMatrix = out ? &out->positions_with_override : &boneData;
|
||||
|
||||
int numbones = Joints.SSize();
|
||||
outMatrix->Resize(numbones);
|
||||
|
||||
if(out)
|
||||
{
|
||||
out->bones_anim_only.Resize(numbones);
|
||||
out->bones.Resize(numbones);
|
||||
out->bones_with_override.Resize(numbones);
|
||||
out->positions.Resize(numbones);
|
||||
}
|
||||
|
||||
if(in && in->size() != Joints.Size()) in = nullptr;
|
||||
|
|
@ -701,11 +705,11 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
|
|||
frame1 = clamp(frame1, 0, (animationFrames.SSize() - 1) / numbones);
|
||||
frame2 = clamp(frame2, 0, (animationFrames.SSize() - 1) / numbones);
|
||||
|
||||
int offset1 = frame1 * numbones;
|
||||
int offset2 = frame2 * numbones;
|
||||
unsigned int offset1 = frame1 * numbones;
|
||||
unsigned int offset2 = frame2 * numbones;
|
||||
|
||||
int offset1_1 = frame1_prev * numbones;
|
||||
int offset2_1 = frame2_prev * numbones;
|
||||
unsigned int offset1_1 = frame1_prev * numbones;
|
||||
unsigned int offset2_1 = frame2_prev * numbones;
|
||||
|
||||
float invt = 1.0f - inter;
|
||||
float invt1 = 1.0f - inter1_prev;
|
||||
|
|
@ -751,7 +755,7 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
|
|||
|
||||
if(out)
|
||||
{
|
||||
out->bones_anim_only[i] = bone;
|
||||
out->bones[i] = bone;
|
||||
|
||||
if(in)
|
||||
{
|
||||
|
|
@ -774,7 +778,6 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
|
|||
VSMatrix& result = (*outMatrix)[i];
|
||||
if (Joints[i].Parent >= 0)
|
||||
{
|
||||
assert(Joints[i].Parent < i);
|
||||
result = (*outMatrix)[Joints[i].Parent];
|
||||
result.multMatrix(swapYZ);
|
||||
result.multMatrix(baseframe[Joints[i].Parent]);
|
||||
|
|
@ -788,6 +791,32 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
|
|||
result.multMatrix(inversebaseframe[i]);
|
||||
}
|
||||
result.multMatrix(swapYZ);
|
||||
|
||||
if(out)
|
||||
{
|
||||
VSMatrix m;
|
||||
m.loadIdentity();
|
||||
m.translate(out->bones[i].translation.X, out->bones[i].translation.Y, out->bones[i].translation.Z);
|
||||
m.multQuaternion(out->bones[i].rotation);
|
||||
m.scale(out->bones[i].scaling.X, out->bones[i].scaling.Y, out->bones[i].scaling.Z);
|
||||
|
||||
VSMatrix& result = out->positions[i];
|
||||
if (Joints[i].Parent >= 0)
|
||||
{
|
||||
result = out->positions[Joints[i].Parent];
|
||||
result.multMatrix(swapYZ);
|
||||
result.multMatrix(baseframe[Joints[i].Parent]);
|
||||
result.multMatrix(m);
|
||||
result.multMatrix(inversebaseframe[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.loadMatrix(swapYZ);
|
||||
result.multMatrix(m);
|
||||
result.multMatrix(inversebaseframe[i]);
|
||||
}
|
||||
result.multMatrix(swapYZ);
|
||||
}
|
||||
}
|
||||
|
||||
return &boneData;
|
||||
|
|
|
|||
|
|
@ -680,14 +680,14 @@ int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction
|
|||
auto vproto = Virtuals[i]->Proto;
|
||||
auto &vflags = Virtuals[i]->ArgFlags;
|
||||
|
||||
int n = flags.size();
|
||||
int n = flags.SSize();
|
||||
|
||||
bool flagsOk = true;
|
||||
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
int argA = i >= vflags.size() ? 0 : vflags[i];
|
||||
int argB = i >= flags.size() ? 0 : flags[i];
|
||||
int argA = i >= vflags.SSize() ? 0 : vflags[i];
|
||||
int argB = i >= flags.SSize() ? 0 : flags[i];
|
||||
|
||||
bool AisRef = argA & (VARF_Out | VARF_Ref);
|
||||
bool BisRef = argB & (VARF_Out | VARF_Ref);
|
||||
|
|
|
|||
|
|
@ -102,14 +102,14 @@ namespace
|
|||
float v_MinimumToFill2(uint32_t inwidth, uint32_t inheight)
|
||||
{
|
||||
// sx = screen x dimension, sy = same for y
|
||||
float sx = (float)inwidth * 1.2, sy = (float)inheight;
|
||||
float sx = (float)inwidth * 1.2f, sy = (float)inheight;
|
||||
static float lastsx = 0., lastsy = 0., result = 0.;
|
||||
if (lastsx != sx || lastsy != sy)
|
||||
{
|
||||
if (sx <= 0. || sy <= 0.)
|
||||
return 1.; // prevent x/0 error
|
||||
// set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible
|
||||
float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2 / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy;
|
||||
float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2f / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy;
|
||||
result = (ssx < ssy) ? ssy : ssx;
|
||||
lastsx = sx;
|
||||
lastsy = sy;
|
||||
|
|
@ -165,7 +165,7 @@ namespace
|
|||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 6 - 320x200
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX2(Width, Height) * 1.2; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2)
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return uint32_t(v_mfillX2(Width, Height) * 1.2); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2)
|
||||
};
|
||||
bool isOutOfBounds(int x)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#endif
|
||||
#include "m_png.h"
|
||||
#include "basics.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
|
@ -944,7 +945,13 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
|
||||
y = height;
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
|
||||
if(buffer.size() > UINT_MAX)
|
||||
{
|
||||
I_Error("save png buffer too large");
|
||||
}
|
||||
|
||||
stream.avail_out = (unsigned int) buffer.size();
|
||||
|
||||
temprow[0][0] = 0;
|
||||
#if USE_FILTER_HEURISTIC
|
||||
|
|
@ -1006,12 +1013,24 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
}
|
||||
while (stream.avail_out == 0)
|
||||
{
|
||||
if (!WriteIDAT (file, buffer.data(), buffer.size()))
|
||||
|
||||
if(buffer.size() > INT_MAX)
|
||||
{
|
||||
I_Error("save png buffer too large");
|
||||
}
|
||||
int sz = (int) buffer.size();
|
||||
if (!WriteIDAT (file, buffer.data(), sz))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
|
||||
if(buffer.size() > UINT_MAX)
|
||||
{
|
||||
I_Error("save png buffer too large");
|
||||
}
|
||||
|
||||
stream.avail_out = (unsigned int) buffer.size();
|
||||
if (stream.avail_in != 0)
|
||||
{
|
||||
err = deflate (&stream, (y == 0) ? Z_FINISH : 0);
|
||||
|
|
@ -1032,12 +1051,23 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
}
|
||||
if (stream.avail_out == 0)
|
||||
{
|
||||
if (!WriteIDAT (file, buffer.data(), buffer.size()))
|
||||
if(buffer.size() > INT_MAX)
|
||||
{
|
||||
I_Error("save png buffer too large");
|
||||
}
|
||||
int sz = (int) buffer.size();
|
||||
if (!WriteIDAT (file, buffer.data(), sz))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
|
||||
if(buffer.size() > UINT_MAX)
|
||||
{
|
||||
I_Error("save png buffer too large");
|
||||
}
|
||||
|
||||
stream.avail_out = (unsigned int) buffer.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1047,7 +1077,15 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
{
|
||||
return false;
|
||||
}
|
||||
return WriteIDAT (file, buffer.data(), buffer.size() - stream.avail_out);
|
||||
|
||||
|
||||
if((buffer.size() - stream.avail_out) > INT_MAX)
|
||||
{
|
||||
I_Error("save png buffer too large");
|
||||
}
|
||||
int sz = (int) (buffer.size() - stream.avail_out);
|
||||
|
||||
return WriteIDAT (file, buffer.data(), sz);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class VSMatrix {
|
|||
static void multMatrix(FLOATTYPE *resMatrix, const FLOATTYPE *aMatrix);
|
||||
|
||||
static void setIdentityMatrix(FLOATTYPE *mat, int size = 4);
|
||||
|
||||
public:
|
||||
/// The storage for matrices
|
||||
FLOATTYPE mMatrix[16];
|
||||
|
||||
|
|
|
|||
|
|
@ -82,25 +82,15 @@ public:
|
|||
}
|
||||
|
||||
// returns the XY fields as a 2D-vector.
|
||||
const Vector2& XY() const
|
||||
Vector2 XY() const
|
||||
{
|
||||
return *reinterpret_cast<const Vector2*>(this);
|
||||
return Vector2(X, Y);
|
||||
}
|
||||
|
||||
Vector2& XY()
|
||||
// returns the XYZ fields as a 3D-vector.
|
||||
Vector3 XYZ() const
|
||||
{
|
||||
return *reinterpret_cast<Vector2*>(this);
|
||||
}
|
||||
|
||||
// returns the XY fields as a 2D-vector.
|
||||
const Vector3& XYZ() const
|
||||
{
|
||||
return *reinterpret_cast<const Vector3*>(this);
|
||||
}
|
||||
|
||||
Vector3& XYZ()
|
||||
{
|
||||
return *reinterpret_cast<Vector3*>(this);
|
||||
return Vector3(X, Y, Z);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -320,7 +310,10 @@ public:
|
|||
auto factor = sinTheta / g_sqrt(lengthSquared);
|
||||
TQuaternion<vec_t> ret;
|
||||
ret.W = cosTheta;
|
||||
ret.XYZ() = factor * axis;
|
||||
auto xyz = vec_t(factor) * axis;
|
||||
ret.X = vec_t(xyz.X);
|
||||
ret.Y = vec_t(xyz.Y);
|
||||
ret.Z = vec_t(xyz.Z);
|
||||
return ret;
|
||||
}
|
||||
static TQuaternion<vec_t> FromAngles(TAngle<vec_t> yaw, TAngle<vec_t> pitch, TAngle<vec_t> roll)
|
||||
|
|
|
|||
|
|
@ -705,12 +705,16 @@ struct TVector3
|
|||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// returns a version with swapped Z/Y
|
||||
constexpr const TVector3 ToXZY() const
|
||||
{
|
||||
return {X, Z, Y};
|
||||
}
|
||||
|
||||
constexpr TVector3 ScaleXYZ (const TVector3 &scaling)
|
||||
{
|
||||
return TVector3(X * scaling.X, Y * scaling.Y, Z * scaling.Z);
|
||||
}
|
||||
};
|
||||
|
||||
template<class vec_t>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue