mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Merge pull request #192 from Laupetin/fix/gltf-bone-rotations
fix: gltf bone rotations
This commit is contained in:
commit
30394e6a4c
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -13,3 +13,6 @@
|
||||
[submodule "thirdparty/json"]
|
||||
path = thirdparty/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
[submodule "thirdparty/eigen"]
|
||||
path = thirdparty/eigen
|
||||
url = https://gitlab.com/libeigen/eigen.git
|
||||
|
@ -84,6 +84,7 @@ workspace "OpenAssetTools"
|
||||
-- ThirdParty
|
||||
-- ========================
|
||||
include "thirdparty/catch2.lua"
|
||||
include "thirdparty/eigen.lua"
|
||||
include "thirdparty/libtomcrypt.lua"
|
||||
include "thirdparty/libtommath.lua"
|
||||
include "thirdparty/json.lua"
|
||||
@ -95,6 +96,7 @@ include "thirdparty/zlib.lua"
|
||||
-- ThirdParty group: All projects that are external dependencies
|
||||
group "ThirdParty"
|
||||
catch2:project()
|
||||
eigen:project()
|
||||
libtommath:project()
|
||||
libtomcrypt:project()
|
||||
json:project()
|
||||
|
@ -1,11 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Math/Quaternion.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct XModelQuaternion
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
struct XModelBone
|
||||
{
|
||||
std::string name;
|
||||
@ -13,8 +20,8 @@ struct XModelBone
|
||||
float scale[3];
|
||||
float globalOffset[3];
|
||||
float localOffset[3];
|
||||
Quaternion32 globalRotation;
|
||||
Quaternion32 localRotation;
|
||||
XModelQuaternion globalRotation;
|
||||
XModelQuaternion localRotation;
|
||||
};
|
||||
|
||||
struct XModelBoneWeight
|
||||
|
@ -56,4 +56,5 @@ function ObjLoading:project()
|
||||
minizip:include(includes)
|
||||
zlib:include(includes)
|
||||
json:include(includes)
|
||||
eigen:include(includes)
|
||||
end
|
||||
|
@ -80,16 +80,16 @@ float AbstractGdtEntryReader::ReadFloatProperty(const std::string& propertyName,
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector2f AbstractGdtEntryReader::ReadVec2Property(const std::string& propertyName, const Vector2f defaultValue) const
|
||||
GdtVec2 AbstractGdtEntryReader::ReadVec2Property(const std::string& propertyName, const GdtVec2 defaultValue) const
|
||||
{
|
||||
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||
if (foundProperty == m_entry.m_properties.end())
|
||||
return defaultValue;
|
||||
|
||||
std::istringstream iss(foundProperty->second);
|
||||
Vector2f result;
|
||||
GdtVec2 result;
|
||||
|
||||
iss >> result(0) >> result(1);
|
||||
iss >> result.x >> result.y;
|
||||
|
||||
if (iss.fail())
|
||||
{
|
||||
@ -101,16 +101,16 @@ Vector2f AbstractGdtEntryReader::ReadVec2Property(const std::string& propertyNam
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f AbstractGdtEntryReader::ReadVec3Property(const std::string& propertyName, const Vector3f defaultValue) const
|
||||
GdtVec3 AbstractGdtEntryReader::ReadVec3Property(const std::string& propertyName, const GdtVec3 defaultValue) const
|
||||
{
|
||||
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||
if (foundProperty == m_entry.m_properties.end())
|
||||
return defaultValue;
|
||||
|
||||
std::istringstream iss(foundProperty->second);
|
||||
Vector3f result;
|
||||
GdtVec3 result;
|
||||
|
||||
iss >> result(0) >> result(1) >> result(2);
|
||||
iss >> result.x >> result.y >> result.z;
|
||||
|
||||
if (iss.fail())
|
||||
{
|
||||
@ -122,16 +122,16 @@ Vector3f AbstractGdtEntryReader::ReadVec3Property(const std::string& propertyNam
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector4f AbstractGdtEntryReader::ReadVec4Property(const std::string& propertyName, const Vector4f defaultValue) const
|
||||
GdtVec4 AbstractGdtEntryReader::ReadVec4Property(const std::string& propertyName, const GdtVec4 defaultValue) const
|
||||
{
|
||||
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||
if (foundProperty == m_entry.m_properties.end())
|
||||
return defaultValue;
|
||||
|
||||
std::istringstream iss(foundProperty->second);
|
||||
Vector4f result;
|
||||
GdtVec4 result;
|
||||
|
||||
iss >> result(0) >> result(1) >> result(2) >> result(3);
|
||||
iss >> result.x >> result.y >> result.z >> result.w;
|
||||
|
||||
if (iss.fail())
|
||||
{
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Math/Vector.h"
|
||||
#include "Obj/Gdt/GdtEntry.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
@ -16,6 +15,27 @@ private:
|
||||
std::string m_message;
|
||||
};
|
||||
|
||||
struct GdtVec2
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
struct GdtVec3
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct GdtVec4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
class AbstractGdtEntryReader
|
||||
{
|
||||
protected:
|
||||
@ -25,9 +45,9 @@ protected:
|
||||
_NODISCARD bool ReadBoolProperty(const std::string& propertyName, bool defaultValue = false) const;
|
||||
_NODISCARD int ReadIntegerProperty(const std::string& propertyName, int defaultValue = 0) const;
|
||||
_NODISCARD float ReadFloatProperty(const std::string& propertyName, float defaultValue = 0.0f) const;
|
||||
_NODISCARD Vector2f ReadVec2Property(const std::string& propertyName, Vector2f defaultValue = {}) const;
|
||||
_NODISCARD Vector3f ReadVec3Property(const std::string& propertyName, Vector3f defaultValue = {}) const;
|
||||
_NODISCARD Vector4f ReadVec4Property(const std::string& propertyName, Vector4f defaultValue = {}) const;
|
||||
_NODISCARD GdtVec2 ReadVec2Property(const std::string& propertyName, GdtVec2 defaultValue = {}) const;
|
||||
_NODISCARD GdtVec3 ReadVec3Property(const std::string& propertyName, GdtVec3 defaultValue = {}) const;
|
||||
_NODISCARD GdtVec4 ReadVec4Property(const std::string& propertyName, GdtVec4 defaultValue = {}) const;
|
||||
|
||||
const GdtEntry& m_entry;
|
||||
};
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "Game/IW4/MaterialConstantsIW4.h"
|
||||
#include "Game/IW4/ObjConstantsIW4.h"
|
||||
#include "Game/IW4/TechsetConstantsIW4.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "ObjLoading.h"
|
||||
#include "Pool/GlobalAssetPool.h"
|
||||
#include "StateMap/StateMapFromTechniqueExtractor.h"
|
||||
@ -198,14 +197,14 @@ namespace IW4
|
||||
|
||||
const auto distortionScaleX = ReadFloatProperty("distortionScaleX");
|
||||
const auto distortionScaleY = ReadFloatProperty("distortionScaleY");
|
||||
AddConstant("distortionScale", Vector4f(distortionScaleX, distortionScaleY, 0, 0));
|
||||
AddConstant("distortionScale", {distortionScaleX, distortionScaleY, 0, 0});
|
||||
|
||||
if (uvAnim)
|
||||
{
|
||||
const auto uvScrollX = ReadFloatProperty("uvScrollX");
|
||||
const auto uvScrollY = ReadFloatProperty("uvScrollY");
|
||||
const auto uvScrollRotate = ReadFloatProperty("uvScrollRotate");
|
||||
AddConstant("uvAnimParms", Vector4f(uvScrollX, uvScrollY, uvScrollRotate, 0));
|
||||
AddConstant("uvAnimParms", {uvScrollX, uvScrollY, uvScrollRotate, 0});
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,11 +503,11 @@ namespace IW4
|
||||
const auto zFeatherDepth = ReadFloatProperty("zFeatherDepth");
|
||||
if (std::fpclassify(zFeatherDepth) == FP_ZERO)
|
||||
throw GdtReadingException("zFeatherDepth may not be zero");
|
||||
AddConstant("featherParms", Vector4f(1.0f / zFeatherDepth, zFeatherDepth, 0, 0));
|
||||
AddConstant("featherParms", {1.0f / zFeatherDepth, zFeatherDepth, 0, 0});
|
||||
}
|
||||
|
||||
if (std::fpclassify(eyeOffsetDepth) != FP_ZERO)
|
||||
AddConstant("eyeOffsetParms", Vector4f(eyeOffsetDepth, 0, 0, 0));
|
||||
AddConstant("eyeOffsetParms", {eyeOffsetDepth, 0, 0, 0});
|
||||
|
||||
const auto colorTint = ReadVec4Property("colorTint", {1.0f, 1.0f, 1.0f, 1.0f});
|
||||
AddConstant("colorTint", colorTint);
|
||||
@ -1009,13 +1008,13 @@ namespace IW4
|
||||
m_textures.push_back(textureDef);
|
||||
}
|
||||
|
||||
void AddConstant(const std::string& constantName, Vector4f literalData)
|
||||
void AddConstant(const std::string& constantName, const GdtVec4& literalData)
|
||||
{
|
||||
MaterialConstantDef constantDef{};
|
||||
constantDef.literal[0] = literalData(0);
|
||||
constantDef.literal[1] = literalData(1);
|
||||
constantDef.literal[2] = literalData(2);
|
||||
constantDef.literal[3] = literalData(3);
|
||||
constantDef.literal[0] = literalData.x;
|
||||
constantDef.literal[1] = literalData.y;
|
||||
constantDef.literal[2] = literalData.z;
|
||||
constantDef.literal[3] = literalData.w;
|
||||
strncpy(constantDef.name, constantName.c_str(), std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||
constantDef.nameHash = Common::R_HashString(constantName.c_str());
|
||||
|
||||
|
@ -55,6 +55,7 @@ function ObjWriting:project()
|
||||
Utils:include(includes)
|
||||
minilzo:include(includes)
|
||||
minizip:include(includes)
|
||||
eigen:include(includes)
|
||||
json:include(includes)
|
||||
libtomcrypt:include(includes)
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include "Game/IW3/CommonIW3.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
@ -125,25 +124,31 @@ namespace
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = {
|
||||
model->baseMat[boneNum].quat[0],
|
||||
model->baseMat[boneNum].quat[1],
|
||||
model->baseMat[boneNum].quat[2],
|
||||
model->baseMat[boneNum].quat[3],
|
||||
};
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
bone.localOffset[0] = 0;
|
||||
bone.localOffset[1] = 0;
|
||||
bone.localOffset[2] = 0;
|
||||
bone.localRotation = Quaternion32(0, 0, 0, 1);
|
||||
bone.localRotation = {0, 0, 0, 1};
|
||||
}
|
||||
else
|
||||
{
|
||||
bone.localOffset[0] = model->trans[boneNum - model->numRootBones][0];
|
||||
bone.localOffset[1] = model->trans[boneNum - model->numRootBones][1];
|
||||
bone.localOffset[2] = model->trans[boneNum - model->numRootBones][2];
|
||||
bone.localRotation = Quaternion32(QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
bone.localRotation = {
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]),
|
||||
};
|
||||
}
|
||||
|
||||
out.m_bones.emplace_back(std::move(bone));
|
||||
@ -267,6 +272,11 @@ namespace
|
||||
weightCollection.weights.resize(totalWeightCount);
|
||||
}
|
||||
|
||||
float BoneWeight16(const uint16_t value)
|
||||
{
|
||||
return static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||
}
|
||||
|
||||
void AddXModelVertexBoneWeights(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
@ -318,7 +328,7 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -335,9 +345,9 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -355,11 +365,11 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneIndex3 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 5] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight3 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight3 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
|
@ -3,9 +3,9 @@
|
||||
#include "Game/IW4/MaterialConstantsIW4.h"
|
||||
#include "Game/IW4/ObjConstantsIW4.h"
|
||||
#include "Game/IW4/TechsetConstantsIW4.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
#include <Eigen>
|
||||
#include <iomanip>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sstream>
|
||||
@ -450,7 +450,7 @@ namespace IW4
|
||||
class ConstantsInfo
|
||||
{
|
||||
public:
|
||||
Vector4f m_color_tint = Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Eigen::Vector4f m_color_tint = Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
float m_env_map_min = 0.2f;
|
||||
float m_env_map_max = 1.0f;
|
||||
float m_env_map_exponent = 2.5f;
|
||||
@ -460,13 +460,13 @@ namespace IW4
|
||||
float m_falloff_end_angle = 65.0f;
|
||||
float m_dist_falloff_begin_distance = 200.0f;
|
||||
float m_dist_falloff_end_distance = 10.0f;
|
||||
Vector4f m_falloff_begin_color = Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Vector4f m_falloff_end_color = Vector4f(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
Vector2f m_detail_scale = Vector2f(8.0f, 8.0f);
|
||||
Vector2f m_distortion_scale = Vector2f(0.5f, 0.5f);
|
||||
Vector4f m_color_obj_min = Vector4f(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
Vector4f m_color_obj_max = Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Vector4f m_water_color = Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Eigen::Vector4f m_falloff_begin_color = Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Eigen::Vector4f m_falloff_end_color = Eigen::Vector4f(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
Eigen::Vector2f m_detail_scale = Eigen::Vector2f(8.0f, 8.0f);
|
||||
Eigen::Vector2f m_distortion_scale = Eigen::Vector2f(0.5f, 0.5f);
|
||||
Eigen::Vector4f m_color_obj_min = Eigen::Vector4f(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
Eigen::Vector4f m_color_obj_max = Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Eigen::Vector4f m_water_color = Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// Speed in which the wave animation is played
|
||||
float m_flag_speed = 1.0f;
|
||||
@ -497,7 +497,7 @@ namespace IW4
|
||||
m_entry.m_properties.emplace(std::make_pair(key, std::move(value)));
|
||||
}
|
||||
|
||||
void SetValue(const std::string& key, const Vector4f& v)
|
||||
void SetValue(const std::string& key, const Eigen::Vector4f& v)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << v.x() << " " << v.y() << " " << v.z() << " " << v.w();
|
||||
@ -1183,7 +1183,7 @@ namespace IW4
|
||||
|
||||
if (constant.nameHash == Common::R_HashString("colorTint"))
|
||||
{
|
||||
m_constants_info.m_color_tint = Vector4f(constant.literal);
|
||||
m_constants_info.m_color_tint = Eigen::Vector4f(constant.literal);
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("envMapParms"))
|
||||
{
|
||||
@ -1198,11 +1198,11 @@ namespace IW4
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("falloffBeginColor"))
|
||||
{
|
||||
m_constants_info.m_falloff_begin_color = Vector4f(constant.literal);
|
||||
m_constants_info.m_falloff_begin_color = Eigen::Vector4f(constant.literal);
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("falloffEndColor"))
|
||||
{
|
||||
m_constants_info.m_falloff_end_color = Vector4f(constant.literal);
|
||||
m_constants_info.m_falloff_end_color = Eigen::Vector4f(constant.literal);
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("eyeOffsetParms"))
|
||||
{
|
||||
@ -1227,14 +1227,15 @@ namespace IW4
|
||||
{
|
||||
const auto detailScaleFactorX = static_cast<float>(colorMapTexture->width) / static_cast<float>(detailMapTexture->width);
|
||||
const auto detailScaleFactorY = static_cast<float>(colorMapTexture->height) / static_cast<float>(detailMapTexture->height);
|
||||
m_constants_info.m_detail_scale = Vector2f(constant.literal[0] / detailScaleFactorX, constant.literal[1] / detailScaleFactorY);
|
||||
m_constants_info.m_detail_scale =
|
||||
Eigen::Vector2f(constant.literal[0] / detailScaleFactorX, constant.literal[1] / detailScaleFactorY);
|
||||
}
|
||||
else
|
||||
m_constants_info.m_detail_scale = Vector2f(constant.literal[0], constant.literal[1]);
|
||||
m_constants_info.m_detail_scale = Eigen::Vector2f(constant.literal[0], constant.literal[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_constants_info.m_detail_scale = Vector2f(constant.literal[0], constant.literal[1]);
|
||||
m_constants_info.m_detail_scale = Eigen::Vector2f(constant.literal[0], constant.literal[1]);
|
||||
}
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("flagParms"))
|
||||
@ -1252,7 +1253,7 @@ namespace IW4
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("distortionScale"))
|
||||
{
|
||||
m_constants_info.m_distortion_scale = Vector2f(constant.literal[0], constant.literal[1]);
|
||||
m_constants_info.m_distortion_scale = Eigen::Vector2f(constant.literal[0], constant.literal[1]);
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("uvAnimParms"))
|
||||
{
|
||||
@ -1262,15 +1263,15 @@ namespace IW4
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("colorObjMin"))
|
||||
{
|
||||
m_constants_info.m_color_obj_min = Vector4f(constant.literal);
|
||||
m_constants_info.m_color_obj_min = Eigen::Vector4f(constant.literal);
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("colorObjMax"))
|
||||
{
|
||||
m_constants_info.m_color_obj_max = Vector4f(constant.literal);
|
||||
m_constants_info.m_color_obj_max = Eigen::Vector4f(constant.literal);
|
||||
}
|
||||
else if (constant.nameHash == Common::R_HashString("waterColor"))
|
||||
{
|
||||
m_constants_info.m_water_color = Vector4f(constant.literal);
|
||||
m_constants_info.m_water_color = Eigen::Vector4f(constant.literal);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include "Game/IW4/CommonIW4.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
@ -120,25 +119,31 @@ namespace
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = {
|
||||
model->baseMat[boneNum].quat[0],
|
||||
model->baseMat[boneNum].quat[1],
|
||||
model->baseMat[boneNum].quat[2],
|
||||
model->baseMat[boneNum].quat[3],
|
||||
};
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
bone.localOffset[0] = 0;
|
||||
bone.localOffset[1] = 0;
|
||||
bone.localOffset[2] = 0;
|
||||
bone.localRotation = Quaternion32(0, 0, 0, 1);
|
||||
bone.localRotation = {0, 0, 0, 1};
|
||||
}
|
||||
else
|
||||
{
|
||||
bone.localOffset[0] = model->trans[boneNum - model->numRootBones][0];
|
||||
bone.localOffset[1] = model->trans[boneNum - model->numRootBones][1];
|
||||
bone.localOffset[2] = model->trans[boneNum - model->numRootBones][2];
|
||||
bone.localRotation = Quaternion32(QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
bone.localRotation = {
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]),
|
||||
};
|
||||
}
|
||||
|
||||
out.m_bones.emplace_back(std::move(bone));
|
||||
@ -253,6 +258,11 @@ namespace
|
||||
weightCollection.weights.resize(totalWeightCount);
|
||||
}
|
||||
|
||||
float BoneWeight16(const uint16_t value)
|
||||
{
|
||||
return static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||
}
|
||||
|
||||
void AddXModelVertexBoneWeights(XModelCommon& out, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
auto& weightCollection = out.m_bone_weight_data;
|
||||
@ -301,7 +311,7 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -318,9 +328,9 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -338,11 +348,11 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneIndex3 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 5] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight3 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight3 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include "Game/IW5/CommonIW5.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
@ -120,25 +119,31 @@ namespace
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = {
|
||||
model->baseMat[boneNum].quat[0],
|
||||
model->baseMat[boneNum].quat[1],
|
||||
model->baseMat[boneNum].quat[2],
|
||||
model->baseMat[boneNum].quat[3],
|
||||
};
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
bone.localOffset[0] = 0;
|
||||
bone.localOffset[1] = 0;
|
||||
bone.localOffset[2] = 0;
|
||||
bone.localRotation = Quaternion32(0, 0, 0, 1);
|
||||
bone.localRotation = {0, 0, 0, 1};
|
||||
}
|
||||
else
|
||||
{
|
||||
bone.localOffset[0] = model->trans[boneNum - model->numRootBones][0];
|
||||
bone.localOffset[1] = model->trans[boneNum - model->numRootBones][1];
|
||||
bone.localOffset[2] = model->trans[boneNum - model->numRootBones][2];
|
||||
bone.localRotation = Quaternion32(QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
bone.localRotation = {
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]),
|
||||
};
|
||||
}
|
||||
|
||||
out.m_bones.emplace_back(std::move(bone));
|
||||
@ -253,6 +258,11 @@ namespace
|
||||
weightCollection.weights.resize(totalWeightCount);
|
||||
}
|
||||
|
||||
float BoneWeight16(const uint16_t value)
|
||||
{
|
||||
return static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||
}
|
||||
|
||||
void AddXModelVertexBoneWeights(XModelCommon& out, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
auto& weightCollection = out.m_bone_weight_data;
|
||||
@ -301,7 +311,7 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -318,9 +328,9 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -338,11 +348,11 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneIndex3 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 5] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight3 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight3 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include "Game/T5/CommonT5.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
@ -125,25 +123,31 @@ namespace
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = {
|
||||
model->baseMat[boneNum].quat[0],
|
||||
model->baseMat[boneNum].quat[1],
|
||||
model->baseMat[boneNum].quat[2],
|
||||
model->baseMat[boneNum].quat[3],
|
||||
};
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
bone.localOffset[0] = 0;
|
||||
bone.localOffset[1] = 0;
|
||||
bone.localOffset[2] = 0;
|
||||
bone.localRotation = Quaternion32(0, 0, 0, 1);
|
||||
bone.localRotation = {0, 0, 0, 1};
|
||||
}
|
||||
else
|
||||
{
|
||||
bone.localOffset[0] = model->trans[boneNum - model->numRootBones][0];
|
||||
bone.localOffset[1] = model->trans[boneNum - model->numRootBones][1];
|
||||
bone.localOffset[2] = model->trans[boneNum - model->numRootBones][2];
|
||||
bone.localRotation = Quaternion32(QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
bone.localRotation = {
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]),
|
||||
};
|
||||
}
|
||||
|
||||
out.m_bones.emplace_back(std::move(bone));
|
||||
@ -267,6 +271,11 @@ namespace
|
||||
weightCollection.weights.resize(totalWeightCount);
|
||||
}
|
||||
|
||||
float BoneWeight16(const uint16_t value)
|
||||
{
|
||||
return static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||
}
|
||||
|
||||
void AddXModelVertexBoneWeights(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
@ -318,7 +327,7 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -335,9 +344,9 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -355,11 +364,11 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneIndex3 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 5] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight3 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight3 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include "Game/T6/CommonT6.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
@ -137,25 +135,31 @@ namespace
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans.x;
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans.y;
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans.z;
|
||||
bone.globalRotation =
|
||||
Quaternion32(model->baseMat[boneNum].quat.x, model->baseMat[boneNum].quat.y, model->baseMat[boneNum].quat.z, model->baseMat[boneNum].quat.w);
|
||||
bone.globalRotation = {
|
||||
model->baseMat[boneNum].quat.x,
|
||||
model->baseMat[boneNum].quat.y,
|
||||
model->baseMat[boneNum].quat.z,
|
||||
model->baseMat[boneNum].quat.w,
|
||||
};
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
bone.localOffset[0] = 0;
|
||||
bone.localOffset[1] = 0;
|
||||
bone.localOffset[2] = 0;
|
||||
bone.localRotation = Quaternion32(0, 0, 0, 1);
|
||||
bone.localRotation = {0, 0, 0, 1};
|
||||
}
|
||||
else
|
||||
{
|
||||
bone.localOffset[0] = model->trans[boneNum - model->numRootBones][0];
|
||||
bone.localOffset[1] = model->trans[boneNum - model->numRootBones][1];
|
||||
bone.localOffset[2] = model->trans[boneNum - model->numRootBones][2];
|
||||
bone.localRotation = Quaternion32(QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
bone.localRotation = {
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]),
|
||||
};
|
||||
}
|
||||
|
||||
out.m_bones.emplace_back(std::move(bone));
|
||||
@ -285,6 +289,11 @@ namespace
|
||||
weightCollection.weights.resize(totalWeightCount);
|
||||
}
|
||||
|
||||
float BoneWeight16(const uint16_t value)
|
||||
{
|
||||
return static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||
}
|
||||
|
||||
void AddXModelVertexBoneWeights(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
@ -339,7 +348,7 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -356,9 +365,9 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
@ -376,11 +385,11 @@ namespace
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
const auto boneIndex1 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneIndex2 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneIndex3 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 5] / sizeof(DObjSkelMat));
|
||||
const auto boneWeight3 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight3 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "XModelExportWriter.h"
|
||||
|
||||
#include "Math/Quaternion.h"
|
||||
|
||||
#include <Eigen>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
@ -61,10 +60,10 @@ protected:
|
||||
m_stream << std::format("OFFSET {:.6f}, {:.6f}, {:.6f}\n", bone.globalOffset[0], bone.globalOffset[1], bone.globalOffset[2]);
|
||||
m_stream << std::format("SCALE {:.6f}, {:.6f}, {:.6f}\n", bone.scale[0], bone.scale[1], bone.scale[2]);
|
||||
|
||||
const Matrix32 mat = bone.globalRotation.ToMatrix();
|
||||
m_stream << std::format("X {:.6f}, {:.6f}, {:.6f}\n", mat.m_data[0][0], mat.m_data[1][0], mat.m_data[2][0]);
|
||||
m_stream << std::format("Y {:.6f}, {:.6f}, {:.6f}\n", mat.m_data[0][1], mat.m_data[1][1], mat.m_data[2][1]);
|
||||
m_stream << std::format("Z {:.6f}, {:.6f}, {:.6f}\n", mat.m_data[0][2], mat.m_data[1][2], mat.m_data[2][2]);
|
||||
const auto mat = Eigen::Quaternionf(bone.globalRotation.w, bone.globalRotation.x, bone.globalRotation.y, bone.globalRotation.z).matrix();
|
||||
m_stream << std::format("X {:.6f}, {:.6f}, {:.6f}\n", mat(0, 0), mat(1, 0), mat(2, 0));
|
||||
m_stream << std::format("Y {:.6f}, {:.6f}, {:.6f}\n", mat(0, 1), mat(1, 1), mat(2, 1));
|
||||
m_stream << std::format("Z {:.6f}, {:.6f}, {:.6f}\n", mat(0, 2), mat(1, 2), mat(2, 2));
|
||||
m_stream << '\n';
|
||||
boneNum++;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include "GltfWriter.h"
|
||||
|
||||
#include "GitVersion.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "XModel/Gltf/GltfConstants.h"
|
||||
#include "XModel/Gltf/JsonGltf.h"
|
||||
|
||||
#include <Eigen>
|
||||
#include <format>
|
||||
|
||||
using namespace gltf;
|
||||
@ -222,20 +222,26 @@ namespace
|
||||
JsonNode boneNode;
|
||||
const auto& bone = xmodel.m_bones[boneIndex];
|
||||
|
||||
Vector3f translation(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]);
|
||||
Quaternion32 rotation(bone.globalRotation.m_x, bone.globalRotation.m_z, -bone.globalRotation.m_y, bone.globalRotation.m_w);
|
||||
Eigen::Vector3f translation(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]);
|
||||
Eigen::Quaternionf rotation(bone.globalRotation.w, bone.globalRotation.x, bone.globalRotation.z, -bone.globalRotation.y);
|
||||
if (bone.parentIndex >= 0)
|
||||
{
|
||||
const auto& parentBone = xmodel.m_bones[bone.parentIndex];
|
||||
translation -= Vector3f(parentBone.globalOffset[0], parentBone.globalOffset[2], -parentBone.globalOffset[1]);
|
||||
rotation /= Quaternion32(
|
||||
parentBone.globalRotation.m_x, parentBone.globalRotation.m_z, -parentBone.globalRotation.m_y, parentBone.globalRotation.m_w);
|
||||
const auto inverseParentRotation =
|
||||
Eigen::Quaternionf(parentBone.globalRotation.w, parentBone.globalRotation.x, parentBone.globalRotation.z, -parentBone.globalRotation.y)
|
||||
.normalized()
|
||||
.inverse()
|
||||
.normalized();
|
||||
|
||||
translation -= Eigen::Vector3f(parentBone.globalOffset[0], parentBone.globalOffset[2], -parentBone.globalOffset[1]);
|
||||
translation = inverseParentRotation * translation;
|
||||
rotation = inverseParentRotation * rotation;
|
||||
}
|
||||
rotation.Normalize();
|
||||
rotation.normalize();
|
||||
|
||||
boneNode.name = bone.name;
|
||||
boneNode.translation = std::to_array({translation.x(), translation.y(), translation.z()});
|
||||
boneNode.rotation = std::to_array({rotation.m_x, rotation.m_y, rotation.m_z, rotation.m_w});
|
||||
boneNode.rotation = std::to_array({rotation.x(), rotation.y(), rotation.z(), rotation.w()});
|
||||
|
||||
std::vector<unsigned> children;
|
||||
for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++)
|
||||
@ -267,6 +273,7 @@ namespace
|
||||
skin.joints.emplace_back(boneIndex + m_first_bone_node);
|
||||
|
||||
skin.inverseBindMatrices = m_inverse_bind_matrices_accessor;
|
||||
skin.skeleton = m_first_bone_node;
|
||||
|
||||
gltf.skins->emplace_back(std::move(skin));
|
||||
}
|
||||
@ -511,29 +518,28 @@ namespace
|
||||
auto* inverseBindMatrixData = reinterpret_cast<float*>(&bufferData[currentBufferOffset]);
|
||||
for (const auto& bone : xmodel.m_bones)
|
||||
{
|
||||
Matrix32 inverseBindMatrix;
|
||||
inverseBindMatrix.m_data[0][3] = -bone.globalOffset[0];
|
||||
inverseBindMatrix.m_data[1][3] = -bone.globalOffset[2];
|
||||
inverseBindMatrix.m_data[2][3] = bone.globalOffset[1];
|
||||
const auto translation = Eigen::Translation3f(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]);
|
||||
const auto rotation = Eigen::Quaternionf(bone.globalRotation.w, bone.globalRotation.x, bone.globalRotation.z, -bone.globalRotation.y);
|
||||
|
||||
// In-memory = row major
|
||||
// gltf = column major
|
||||
inverseBindMatrixData[0] = inverseBindMatrix.m_data[0][0];
|
||||
inverseBindMatrixData[1] = inverseBindMatrix.m_data[1][0];
|
||||
inverseBindMatrixData[2] = inverseBindMatrix.m_data[2][0];
|
||||
inverseBindMatrixData[3] = inverseBindMatrix.m_data[3][0];
|
||||
inverseBindMatrixData[4] = inverseBindMatrix.m_data[0][1];
|
||||
inverseBindMatrixData[5] = inverseBindMatrix.m_data[1][1];
|
||||
inverseBindMatrixData[6] = inverseBindMatrix.m_data[2][1];
|
||||
inverseBindMatrixData[7] = inverseBindMatrix.m_data[3][1];
|
||||
inverseBindMatrixData[8] = inverseBindMatrix.m_data[0][2];
|
||||
inverseBindMatrixData[9] = inverseBindMatrix.m_data[1][2];
|
||||
inverseBindMatrixData[10] = inverseBindMatrix.m_data[2][2];
|
||||
inverseBindMatrixData[11] = inverseBindMatrix.m_data[3][2];
|
||||
inverseBindMatrixData[12] = inverseBindMatrix.m_data[0][3];
|
||||
inverseBindMatrixData[13] = inverseBindMatrix.m_data[1][3];
|
||||
inverseBindMatrixData[14] = inverseBindMatrix.m_data[2][3];
|
||||
inverseBindMatrixData[15] = inverseBindMatrix.m_data[3][3];
|
||||
const auto inverseBindMatrix = (translation * rotation).matrix().inverse();
|
||||
|
||||
// GLTF matrix is column major
|
||||
inverseBindMatrixData[0] = inverseBindMatrix(0, 0);
|
||||
inverseBindMatrixData[1] = inverseBindMatrix(1, 0);
|
||||
inverseBindMatrixData[2] = inverseBindMatrix(2, 0);
|
||||
inverseBindMatrixData[3] = inverseBindMatrix(3, 0);
|
||||
inverseBindMatrixData[4] = inverseBindMatrix(0, 1);
|
||||
inverseBindMatrixData[5] = inverseBindMatrix(1, 1);
|
||||
inverseBindMatrixData[6] = inverseBindMatrix(2, 1);
|
||||
inverseBindMatrixData[7] = inverseBindMatrix(3, 1);
|
||||
inverseBindMatrixData[8] = inverseBindMatrix(0, 2);
|
||||
inverseBindMatrixData[9] = inverseBindMatrix(1, 2);
|
||||
inverseBindMatrixData[10] = inverseBindMatrix(2, 2);
|
||||
inverseBindMatrixData[11] = inverseBindMatrix(3, 2);
|
||||
inverseBindMatrixData[12] = inverseBindMatrix(0, 3);
|
||||
inverseBindMatrixData[13] = inverseBindMatrix(1, 3);
|
||||
inverseBindMatrixData[14] = inverseBindMatrix(2, 3);
|
||||
inverseBindMatrixData[15] = inverseBindMatrix(3, 3);
|
||||
|
||||
inverseBindMatrixData += 16u;
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
template<typename T> class Matrix
|
||||
{
|
||||
public:
|
||||
T m_data[4][4];
|
||||
|
||||
Matrix()
|
||||
: m_data{
|
||||
{T(1.0), 0, 0, 0 },
|
||||
{0, T(1.0), 0, 0 },
|
||||
{0, 0, T(1.0), 0 },
|
||||
{0, 0, 0, T(1.0)},
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
Matrix(T d00, T d01, T d02, T d03, T d10, T d11, T d12, T d13, T d20, T d21, T d22, T d23, T d30, T d31, T d32, T d33)
|
||||
: m_data{
|
||||
{d00, d01, d02, d03},
|
||||
{d10, d11, d12, d13},
|
||||
{d20, d21, d22, d23},
|
||||
{d30, d31, d32, d33},
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
static Matrix<T> Identity()
|
||||
{
|
||||
return Matrix();
|
||||
}
|
||||
};
|
||||
|
||||
typedef Matrix<float> Matrix32;
|
||||
typedef Matrix<double> Matrix64;
|
@ -1,186 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
template<typename T> class Quaternion
|
||||
{
|
||||
public:
|
||||
T m_x;
|
||||
T m_y;
|
||||
T m_z;
|
||||
T m_w;
|
||||
|
||||
Quaternion()
|
||||
{
|
||||
m_x = T(0);
|
||||
m_y = T(0);
|
||||
m_z = T(0);
|
||||
m_w = T(1);
|
||||
}
|
||||
|
||||
Quaternion(T x, T y, T z, T w)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_z = z;
|
||||
m_w = w;
|
||||
}
|
||||
|
||||
_NODISCARD Matrix<T> ToMatrix() const
|
||||
{
|
||||
const T xx = m_x * m_x;
|
||||
const T xy = m_x * m_y;
|
||||
const T xz = m_x * m_z;
|
||||
const T xw = m_x * m_w;
|
||||
const T yy = m_y * m_y;
|
||||
const T yz = m_y * m_z;
|
||||
const T yw = m_y * m_w;
|
||||
const T zz = m_z * m_z;
|
||||
const T zw = m_z * m_w;
|
||||
|
||||
const T m00 = 1 - 2 * yy - 2 * zz;
|
||||
const T m01 = 2 * xy - 2 * zw;
|
||||
const T m02 = 2 * xz + 2 * yw;
|
||||
const T m10 = 2 * xy + 2 * zw;
|
||||
const T m11 = 1 - 2 * xx - 2 * zz;
|
||||
const T m12 = 2 * yz - 2 * xw;
|
||||
const T m20 = 2 * xz - 2 * yw;
|
||||
const T m21 = 2 * yz + 2 * xw;
|
||||
const T m22 = 1 - 2 * xx - 2 * yy;
|
||||
|
||||
return Matrix<T>(m00, m01, m02, 0, m10, m11, m12, 0, m20, m21, m22, 0, 0, 0, 0, T(1.0));
|
||||
}
|
||||
|
||||
static T dot(const Quaternion& q1, const Quaternion& q2)
|
||||
{
|
||||
return static_cast<T>((q1.m_x * q2.m_x) + (q1.m_y * q2.m_y) + (q1.m_z * q2.m_z) + (q1.m_w * q2.m_w));
|
||||
}
|
||||
|
||||
static Quaternion& conj(Quaternion& result)
|
||||
{
|
||||
result.m_x = -result.m_x;
|
||||
result.m_y = -result.m_y;
|
||||
result.m_z = -result.m_z;
|
||||
return result;
|
||||
}
|
||||
|
||||
static Quaternion& invert(Quaternion& result)
|
||||
{
|
||||
// from game programming gems p198
|
||||
// do result = conj( q ) / norm( q )
|
||||
Quaternion::conj(result);
|
||||
|
||||
// return if norm() is near 0 (divide by 0 would result in NaN)
|
||||
T l = result.lengthSquared();
|
||||
if (l < static_cast<T>(0.0001))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
T l_inv = static_cast<T>(1.0) / l;
|
||||
result.m_x *= l_inv;
|
||||
result.m_y *= l_inv;
|
||||
result.m_z *= l_inv;
|
||||
result.m_w *= l_inv;
|
||||
return result;
|
||||
}
|
||||
|
||||
T lengthSquared() const
|
||||
{
|
||||
return Quaternion::dot(*this, *this);
|
||||
}
|
||||
|
||||
T length() const
|
||||
{
|
||||
return sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
const auto l = length();
|
||||
|
||||
// return if no magnitude (already as normalized as possible)
|
||||
if (l < static_cast<T>(0.0001))
|
||||
return;
|
||||
|
||||
T inverseLength = static_cast<T>(1.0) / l;
|
||||
m_x *= inverseLength;
|
||||
m_y *= inverseLength;
|
||||
m_z *= inverseLength;
|
||||
m_w *= inverseLength;
|
||||
}
|
||||
|
||||
friend Quaternion operator+(const Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
return Quaternion(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y, lhs.m_z + rhs.m_z, lhs.m_w + rhs.m_w);
|
||||
}
|
||||
|
||||
friend Quaternion operator-(const Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
return Quaternion(lhs.m_x - rhs.m_x, lhs.m_y - rhs.m_y, lhs.m_z - rhs.m_z, lhs.m_w - rhs.m_w);
|
||||
}
|
||||
|
||||
friend Quaternion& operator+=(Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
lhs.m_x += rhs.m_x;
|
||||
lhs.m_y += rhs.m_y;
|
||||
lhs.m_z += rhs.m_z;
|
||||
lhs.m_w += rhs.m_w;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend Quaternion& operator-=(Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
lhs.m_x -= rhs.m_x;
|
||||
lhs.m_y -= rhs.m_y;
|
||||
lhs.m_z -= rhs.m_z;
|
||||
lhs.m_w -= rhs.m_w;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
const T x2 = lhs.m_w * rhs.m_x + lhs.m_x * rhs.m_w + lhs.m_y * rhs.m_z - lhs.m_z * rhs.m_y;
|
||||
const T y2 = lhs.m_w * rhs.m_y + lhs.m_y * rhs.m_w + lhs.m_z * rhs.m_x - lhs.m_x * rhs.m_z;
|
||||
const T z2 = lhs.m_w * rhs.m_z + lhs.m_z * rhs.m_w + lhs.m_x * rhs.m_y - lhs.m_y * rhs.m_x;
|
||||
const T w2 = lhs.m_w * rhs.m_w - lhs.m_x * rhs.m_x - lhs.m_y * rhs.m_y - lhs.m_z * rhs.m_z;
|
||||
|
||||
return Quaternion(x2, y2, z2, w2);
|
||||
}
|
||||
|
||||
friend Quaternion operator/(const Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
Quaternion rhsInv = rhs;
|
||||
Quaternion::invert(rhsInv);
|
||||
return lhs * rhsInv;
|
||||
}
|
||||
|
||||
friend Quaternion& operator*=(Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
const T x2 = lhs.m_w * rhs.m_x + lhs.m_x * rhs.m_w + lhs.m_y * rhs.m_z - lhs.m_z * rhs.m_y;
|
||||
const T y2 = lhs.m_w * rhs.m_y + lhs.m_y * rhs.m_w + lhs.m_z * rhs.m_x - lhs.m_x * rhs.m_z;
|
||||
const T z2 = lhs.m_w * rhs.m_z + lhs.m_z * rhs.m_w + lhs.m_x * rhs.m_y - lhs.m_y * rhs.m_x;
|
||||
const T w2 = lhs.m_w * rhs.m_w - lhs.m_x * rhs.m_x - lhs.m_y * rhs.m_y - lhs.m_z * rhs.m_z;
|
||||
|
||||
lhs.m_x = x2;
|
||||
lhs.m_y = y2;
|
||||
lhs.m_z = z2;
|
||||
lhs.m_w = w2;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend Quaternion& operator/=(Quaternion& lhs, const Quaternion& rhs)
|
||||
{
|
||||
Quaternion rhsInv = rhs;
|
||||
Quaternion::invert(rhsInv);
|
||||
lhs *= rhsInv;
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Quaternion<float> Quaternion32;
|
||||
typedef Quaternion<double> Quaternion64;
|
@ -1,375 +0,0 @@
|
||||
#pragma once
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
template<typename T> class Vector2
|
||||
{
|
||||
T m_value[2];
|
||||
|
||||
public:
|
||||
Vector2()
|
||||
: m_value{T(0), T(0)}
|
||||
{
|
||||
}
|
||||
|
||||
Vector2(T x, T y)
|
||||
: m_value{x, y}
|
||||
{
|
||||
}
|
||||
|
||||
explicit Vector2(const T* value)
|
||||
: m_value{value[0], value[1]}
|
||||
{
|
||||
}
|
||||
|
||||
~Vector2() = default;
|
||||
Vector2(const Vector2& other) = default;
|
||||
Vector2(Vector2&& other) noexcept = default;
|
||||
Vector2& operator=(const Vector2& other) = default;
|
||||
Vector2& operator=(Vector2&& other) noexcept = default;
|
||||
|
||||
_NODISCARD T& operator()(const size_t index)
|
||||
{
|
||||
assert(index < 2);
|
||||
return m_value[index];
|
||||
}
|
||||
|
||||
_NODISCARD const T& operator()(const size_t index) const
|
||||
{
|
||||
assert(index < 2);
|
||||
return m_value[index];
|
||||
}
|
||||
|
||||
_NODISCARD T& x()
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD T& y()
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD const T& x() const
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD const T& y() const
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
friend Vector2 operator+(const Vector2& lhs, const Vector2& rhs)
|
||||
{
|
||||
return Vector2(lhs.m_value[0] + rhs.m_value[0], lhs.m_value[1] + rhs.m_value[1]);
|
||||
}
|
||||
|
||||
friend Vector2 operator-(const Vector2& lhs, const Vector2& rhs)
|
||||
{
|
||||
return Vector2(lhs.m_value[0] - rhs.m_value[0], lhs.m_value[1] - rhs.m_value[1]);
|
||||
}
|
||||
|
||||
friend Vector2& operator+=(Vector2& lhs, const Vector2& rhs)
|
||||
{
|
||||
lhs.m_value[0] += rhs.m_value[0];
|
||||
lhs.m_value[1] += rhs.m_value[1];
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend Vector2& operator-=(Vector2& lhs, const Vector2& rhs)
|
||||
{
|
||||
lhs.m_value[0] -= rhs.m_value[0];
|
||||
lhs.m_value[1] -= rhs.m_value[1];
|
||||
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Vector2<float> Vector2f;
|
||||
typedef Vector2<double> Vector2d;
|
||||
|
||||
template<typename T> class Vector3
|
||||
{
|
||||
T m_value[3];
|
||||
|
||||
public:
|
||||
Vector3()
|
||||
: m_value{T(0), T(0), T(0)}
|
||||
{
|
||||
}
|
||||
|
||||
Vector3(T x, T y, T z)
|
||||
: m_value{x, y, z}
|
||||
{
|
||||
}
|
||||
|
||||
explicit Vector3(const T* value)
|
||||
: m_value{value[0], value[1], value[2]}
|
||||
{
|
||||
}
|
||||
|
||||
~Vector3() = default;
|
||||
Vector3(const Vector3& other) = default;
|
||||
Vector3(Vector3&& other) noexcept = default;
|
||||
Vector3& operator=(const Vector3& other) = default;
|
||||
Vector3& operator=(Vector3&& other) noexcept = default;
|
||||
|
||||
_NODISCARD T& operator()(const size_t index)
|
||||
{
|
||||
assert(index < 3);
|
||||
return m_value[index];
|
||||
}
|
||||
|
||||
_NODISCARD const T& operator()(const size_t index) const
|
||||
{
|
||||
assert(index < 3);
|
||||
return m_value[index];
|
||||
}
|
||||
|
||||
_NODISCARD T& x()
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD T& y()
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD T& z()
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD const T& x() const
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD const T& y() const
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD const T& z() const
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD T& r()
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD T& g()
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD T& b()
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD const T& r() const
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD const T& g() const
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD const T& b() const
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
friend Vector3 operator+(const Vector3& lhs, const Vector3& rhs)
|
||||
{
|
||||
return Vector3(lhs.m_value[0] + rhs.m_value[0], lhs.m_value[1] + rhs.m_value[1], lhs.m_value[2] + rhs.m_value[2]);
|
||||
}
|
||||
|
||||
friend Vector3 operator-(const Vector3& lhs, const Vector3& rhs)
|
||||
{
|
||||
return Vector3(lhs.m_value[0] - rhs.m_value[0], lhs.m_value[1] - rhs.m_value[1], lhs.m_value[2] - rhs.m_value[2]);
|
||||
}
|
||||
|
||||
friend Vector3& operator+=(Vector3& lhs, const Vector3& rhs)
|
||||
{
|
||||
lhs.m_value[0] += rhs.m_value[0];
|
||||
lhs.m_value[1] += rhs.m_value[1];
|
||||
lhs.m_value[2] += rhs.m_value[2];
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend Vector3& operator-=(Vector3& lhs, const Vector3& rhs)
|
||||
{
|
||||
lhs.m_value[0] -= rhs.m_value[0];
|
||||
lhs.m_value[1] -= rhs.m_value[1];
|
||||
lhs.m_value[2] -= rhs.m_value[2];
|
||||
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Vector3<float> Vector3f;
|
||||
typedef Vector3<double> Vector3d;
|
||||
|
||||
template<typename T> class Vector4
|
||||
{
|
||||
T m_value[4];
|
||||
|
||||
public:
|
||||
Vector4()
|
||||
: m_value{T(0), T(0), T(0), T(0)}
|
||||
{
|
||||
}
|
||||
|
||||
Vector4(T x, T y, T z, T w)
|
||||
: m_value{x, y, z, w}
|
||||
{
|
||||
}
|
||||
|
||||
explicit Vector4(const T* value)
|
||||
: m_value{value[0], value[1], value[2], value[3]}
|
||||
{
|
||||
}
|
||||
|
||||
~Vector4() = default;
|
||||
Vector4(const Vector4& other) = default;
|
||||
Vector4(Vector4&& other) noexcept = default;
|
||||
Vector4& operator=(const Vector4& other) = default;
|
||||
Vector4& operator=(Vector4&& other) noexcept = default;
|
||||
|
||||
_NODISCARD T& operator()(const size_t index)
|
||||
{
|
||||
assert(index < 4);
|
||||
return m_value[index];
|
||||
}
|
||||
|
||||
_NODISCARD const T& operator()(const size_t index) const
|
||||
{
|
||||
assert(index < 4);
|
||||
return m_value[index];
|
||||
}
|
||||
|
||||
_NODISCARD T& x()
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD T& y()
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD T& z()
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD T& w()
|
||||
{
|
||||
return m_value[3];
|
||||
}
|
||||
|
||||
_NODISCARD const T& x() const
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD const T& y() const
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD const T& z() const
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD const T& w() const
|
||||
{
|
||||
return m_value[3];
|
||||
}
|
||||
|
||||
_NODISCARD T& r()
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD T& g()
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD T& b()
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD T& a()
|
||||
{
|
||||
return m_value[3];
|
||||
}
|
||||
|
||||
_NODISCARD const T& r() const
|
||||
{
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
_NODISCARD const T& g() const
|
||||
{
|
||||
return m_value[1];
|
||||
}
|
||||
|
||||
_NODISCARD const T& b() const
|
||||
{
|
||||
return m_value[2];
|
||||
}
|
||||
|
||||
_NODISCARD const T& a() const
|
||||
{
|
||||
return m_value[3];
|
||||
}
|
||||
|
||||
friend Vector4 operator+(const Vector4& lhs, const Vector4& rhs)
|
||||
{
|
||||
return Vector4(lhs.m_value[0] + rhs.m_value[0], lhs.m_value[1] + rhs.m_value[1], lhs.m_value[2] + rhs.m_value[2], lhs.m_value[3] + rhs.m_value[3]);
|
||||
}
|
||||
|
||||
friend Vector4 operator-(const Vector4& lhs, const Vector4& rhs)
|
||||
{
|
||||
return Vector4(lhs.m_value[0] - rhs.m_value[0], lhs.m_value[1] - rhs.m_value[1], lhs.m_value[2] - rhs.m_value[2], lhs.m_value[3] - rhs.m_value[3]);
|
||||
}
|
||||
|
||||
friend Vector4& operator+=(Vector4& lhs, const Vector4& rhs)
|
||||
{
|
||||
lhs.m_value[0] += rhs.m_value[0];
|
||||
lhs.m_value[1] += rhs.m_value[1];
|
||||
lhs.m_value[2] += rhs.m_value[2];
|
||||
lhs.m_value[3] += rhs.m_value[3];
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend Vector4& operator-=(Vector4& lhs, const Vector4& rhs)
|
||||
{
|
||||
lhs.m_value[0] -= rhs.m_value[0];
|
||||
lhs.m_value[1] -= rhs.m_value[1];
|
||||
lhs.m_value[2] -= rhs.m_value[2];
|
||||
lhs.m_value[3] -= rhs.m_value[3];
|
||||
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Vector4<float> Vector4f;
|
||||
typedef Vector4<double> Vector4d;
|
1
thirdparty/eigen
vendored
Submodule
1
thirdparty/eigen
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit afb17288cbb5bac779a850e3ec6ba106b7f42c1c
|
23
thirdparty/eigen.lua
vendored
Normal file
23
thirdparty/eigen.lua
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
eigen = {}
|
||||
|
||||
function eigen:include(includes)
|
||||
if includes:handle(self:name()) then
|
||||
includedirs {
|
||||
path.join(ThirdPartyFolder(), "eigen", "Eigen")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function eigen:link()
|
||||
end
|
||||
|
||||
function eigen:use()
|
||||
|
||||
end
|
||||
|
||||
function eigen:name()
|
||||
return "eigen"
|
||||
end
|
||||
|
||||
function eigen:project()
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user