mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
chore: dump gltf vertex weights
This commit is contained in:
parent
9ab78d5384
commit
c74be5e8ae
@ -1,6 +1,7 @@
|
|||||||
#include "GltfWriter.h"
|
#include "GltfWriter.h"
|
||||||
|
|
||||||
#include "GitVersion.h"
|
#include "GitVersion.h"
|
||||||
|
#include "Math/Vector.h"
|
||||||
#include "XModel/Gltf/GltfConstants.h"
|
#include "XModel/Gltf/GltfConstants.h"
|
||||||
#include "XModel/Gltf/JsonGltf.h"
|
#include "XModel/Gltf/JsonGltf.h"
|
||||||
|
|
||||||
@ -22,9 +23,6 @@ namespace
|
|||||||
|
|
||||||
class GltfWriterImpl final : public gltf::Writer
|
class GltfWriterImpl final : public gltf::Writer
|
||||||
{
|
{
|
||||||
static constexpr auto NODE_INDEX_MESH = 0u;
|
|
||||||
static constexpr auto NODE_FIRST_INDEX_BONES = 1u;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GltfWriterImpl(const Output* output, std::string gameName, std::string zoneName)
|
GltfWriterImpl(const Output* output, std::string gameName, std::string zoneName)
|
||||||
: m_output(output),
|
: m_output(output),
|
||||||
@ -40,8 +38,8 @@ namespace
|
|||||||
|
|
||||||
CreateJsonAsset(gltf.asset);
|
CreateJsonAsset(gltf.asset);
|
||||||
CreateMeshNode(gltf, xmodel);
|
CreateMeshNode(gltf, xmodel);
|
||||||
CreateMaterials(gltf, xmodel);
|
|
||||||
CreateSkeletonNodes(gltf, xmodel);
|
CreateSkeletonNodes(gltf, xmodel);
|
||||||
|
CreateMaterials(gltf, xmodel);
|
||||||
CreateSkin(gltf, xmodel);
|
CreateSkin(gltf, xmodel);
|
||||||
CreateBufferViews(gltf, xmodel);
|
CreateBufferViews(gltf, xmodel);
|
||||||
CreateAccessors(gltf, xmodel);
|
CreateAccessors(gltf, xmodel);
|
||||||
@ -66,7 +64,7 @@ namespace
|
|||||||
asset.generator = GLTF_GENERATOR;
|
asset.generator = GLTF_GENERATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CreateMeshNode(JsonRoot& gltf, const XModelCommon& xmodel)
|
void CreateMeshNode(JsonRoot& gltf, const XModelCommon& xmodel)
|
||||||
{
|
{
|
||||||
JsonNode meshNode;
|
JsonNode meshNode;
|
||||||
|
|
||||||
@ -83,6 +81,7 @@ namespace
|
|||||||
if (!gltf.nodes.has_value())
|
if (!gltf.nodes.has_value())
|
||||||
gltf.nodes.emplace();
|
gltf.nodes.emplace();
|
||||||
|
|
||||||
|
m_mesh_node = gltf.nodes->size();
|
||||||
gltf.nodes->emplace_back(std::move(meshNode));
|
gltf.nodes->emplace_back(std::move(meshNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +92,8 @@ namespace
|
|||||||
|
|
||||||
JsonMesh mesh;
|
JsonMesh mesh;
|
||||||
|
|
||||||
|
const auto hasBoneWeightData = !xmodel.m_vertex_bone_weights.empty();
|
||||||
|
|
||||||
auto objectIndex = 0u;
|
auto objectIndex = 0u;
|
||||||
for (const auto& object : xmodel.m_objects)
|
for (const auto& object : xmodel.m_objects)
|
||||||
{
|
{
|
||||||
@ -105,6 +106,12 @@ namespace
|
|||||||
primitives.attributes.NORMAL = m_normal_accessor;
|
primitives.attributes.NORMAL = m_normal_accessor;
|
||||||
primitives.attributes.TEXCOORD_0 = m_uv_accessor;
|
primitives.attributes.TEXCOORD_0 = m_uv_accessor;
|
||||||
|
|
||||||
|
if (hasBoneWeightData)
|
||||||
|
{
|
||||||
|
primitives.attributes.JOINTS_0 = m_joints_accessor;
|
||||||
|
primitives.attributes.WEIGHTS_0 = m_weights_accessor;
|
||||||
|
}
|
||||||
|
|
||||||
primitives.mode = JsonMeshPrimitivesMode::TRIANGLES;
|
primitives.mode = JsonMeshPrimitivesMode::TRIANGLES;
|
||||||
primitives.indices = m_first_index_accessor + objectIndex;
|
primitives.indices = m_first_index_accessor + objectIndex;
|
||||||
|
|
||||||
@ -136,7 +143,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!modelMaterial.normalMapName.empty())
|
if (!modelMaterial.normalMapName.empty())
|
||||||
material.normalTexture.emplace().index = CreateTexture(gltf, modelMaterial.colorMapName);
|
material.normalTexture.emplace().index = CreateTexture(gltf, modelMaterial.normalMapName);
|
||||||
|
|
||||||
material.doubleSided = true;
|
material.doubleSided = true;
|
||||||
gltf.materials->emplace_back(material);
|
gltf.materials->emplace_back(material);
|
||||||
@ -176,7 +183,7 @@ namespace
|
|||||||
return textureIndex;
|
return textureIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CreateSkeletonNodes(JsonRoot& gltf, const XModelCommon& xmodel)
|
void CreateSkeletonNodes(JsonRoot& gltf, const XModelCommon& xmodel)
|
||||||
{
|
{
|
||||||
if (xmodel.m_bones.empty())
|
if (xmodel.m_bones.empty())
|
||||||
return;
|
return;
|
||||||
@ -185,20 +192,32 @@ namespace
|
|||||||
gltf.nodes.emplace();
|
gltf.nodes.emplace();
|
||||||
|
|
||||||
const auto boneCount = xmodel.m_bones.size();
|
const auto boneCount = xmodel.m_bones.size();
|
||||||
|
m_first_bone_node = gltf.nodes->size();
|
||||||
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
||||||
{
|
{
|
||||||
JsonNode boneNode;
|
JsonNode boneNode;
|
||||||
const auto& bone = xmodel.m_bones[boneIndex];
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
rotation.Normalize();
|
||||||
|
|
||||||
boneNode.name = bone.name;
|
boneNode.name = bone.name;
|
||||||
boneNode.translation = std::to_array(bone.globalOffset);
|
boneNode.translation = std::to_array({translation.x(), translation.y(), translation.z()});
|
||||||
boneNode.rotation = std::to_array({bone.globalRotation.m_x, bone.globalRotation.m_y, bone.globalRotation.m_z, bone.globalRotation.m_w});
|
boneNode.rotation = std::to_array({rotation.m_x, rotation.m_y, rotation.m_z, rotation.m_w});
|
||||||
|
|
||||||
std::vector<unsigned> children;
|
std::vector<unsigned> children;
|
||||||
for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++)
|
for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++)
|
||||||
{
|
{
|
||||||
if (xmodel.m_bones[maybeChildIndex].parentIndex == static_cast<int>(boneIndex))
|
if (xmodel.m_bones[maybeChildIndex].parentIndex == static_cast<int>(boneIndex))
|
||||||
children.emplace_back(maybeChildIndex + NODE_FIRST_INDEX_BONES);
|
children.emplace_back(maybeChildIndex + m_first_bone_node);
|
||||||
}
|
}
|
||||||
if (!children.empty())
|
if (!children.empty())
|
||||||
boneNode.children = std::move(children);
|
boneNode.children = std::move(children);
|
||||||
@ -207,7 +226,7 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CreateSkin(JsonRoot& gltf, const XModelCommon& xmodel)
|
void CreateSkin(JsonRoot& gltf, const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
if (xmodel.m_bones.empty())
|
if (xmodel.m_bones.empty())
|
||||||
return;
|
return;
|
||||||
@ -221,7 +240,7 @@ namespace
|
|||||||
|
|
||||||
skin.joints.reserve(boneCount);
|
skin.joints.reserve(boneCount);
|
||||||
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
||||||
skin.joints.emplace_back(boneIndex + NODE_FIRST_INDEX_BONES);
|
skin.joints.emplace_back(boneIndex + m_first_bone_node);
|
||||||
|
|
||||||
gltf.skins->emplace_back(std::move(skin));
|
gltf.skins->emplace_back(std::move(skin));
|
||||||
}
|
}
|
||||||
@ -231,10 +250,7 @@ namespace
|
|||||||
JsonScene scene;
|
JsonScene scene;
|
||||||
|
|
||||||
// Only add skin if the model has bones
|
// Only add skin if the model has bones
|
||||||
if (xmodel.m_bones.empty())
|
scene.nodes.emplace_back(m_mesh_node);
|
||||||
scene.nodes.emplace_back(NODE_INDEX_MESH);
|
|
||||||
else
|
|
||||||
scene.nodes.emplace_back(m_skeleton_node);
|
|
||||||
|
|
||||||
if (!gltf.scenes.has_value())
|
if (!gltf.scenes.has_value())
|
||||||
gltf.scenes.emplace();
|
gltf.scenes.emplace();
|
||||||
@ -261,6 +277,29 @@ namespace
|
|||||||
m_vertex_buffer_view = gltf.bufferViews->size();
|
m_vertex_buffer_view = gltf.bufferViews->size();
|
||||||
gltf.bufferViews->emplace_back(vertexBufferView);
|
gltf.bufferViews->emplace_back(vertexBufferView);
|
||||||
|
|
||||||
|
if (!xmodel.m_vertex_bone_weights.empty())
|
||||||
|
{
|
||||||
|
JsonBufferView jointsBufferView;
|
||||||
|
jointsBufferView.buffer = 0u;
|
||||||
|
jointsBufferView.byteOffset = bufferOffset;
|
||||||
|
jointsBufferView.byteLength = sizeof(uint8_t) * xmodel.m_vertices.size() * 4u;
|
||||||
|
jointsBufferView.target = JsonBufferViewTarget::ARRAY_BUFFER;
|
||||||
|
bufferOffset += jointsBufferView.byteLength;
|
||||||
|
|
||||||
|
m_joints_buffer_view = gltf.bufferViews->size();
|
||||||
|
gltf.bufferViews->emplace_back(jointsBufferView);
|
||||||
|
|
||||||
|
JsonBufferView weightsBufferView;
|
||||||
|
weightsBufferView.buffer = 0u;
|
||||||
|
weightsBufferView.byteOffset = bufferOffset;
|
||||||
|
weightsBufferView.byteLength = sizeof(float) * xmodel.m_vertices.size() * 4u;
|
||||||
|
weightsBufferView.target = JsonBufferViewTarget::ARRAY_BUFFER;
|
||||||
|
bufferOffset += weightsBufferView.byteLength;
|
||||||
|
|
||||||
|
m_weights_buffer_view = gltf.bufferViews->size();
|
||||||
|
gltf.bufferViews->emplace_back(weightsBufferView);
|
||||||
|
}
|
||||||
|
|
||||||
m_first_index_buffer_view = gltf.bufferViews->size();
|
m_first_index_buffer_view = gltf.bufferViews->size();
|
||||||
for (const auto& object : xmodel.m_objects)
|
for (const auto& object : xmodel.m_objects)
|
||||||
{
|
{
|
||||||
@ -307,6 +346,25 @@ namespace
|
|||||||
m_uv_accessor = gltf.accessors->size();
|
m_uv_accessor = gltf.accessors->size();
|
||||||
gltf.accessors->emplace_back(uvAccessor);
|
gltf.accessors->emplace_back(uvAccessor);
|
||||||
|
|
||||||
|
if (!xmodel.m_vertex_bone_weights.empty())
|
||||||
|
{
|
||||||
|
JsonAccessor jointsAccessor;
|
||||||
|
jointsAccessor.bufferView = m_joints_buffer_view;
|
||||||
|
jointsAccessor.componentType = JsonAccessorComponentType::UNSIGNED_BYTE;
|
||||||
|
jointsAccessor.count = xmodel.m_vertices.size();
|
||||||
|
jointsAccessor.type = JsonAccessorType::VEC4;
|
||||||
|
m_joints_accessor = gltf.accessors->size();
|
||||||
|
gltf.accessors->emplace_back(jointsAccessor);
|
||||||
|
|
||||||
|
JsonAccessor weightsAccessor;
|
||||||
|
weightsAccessor.bufferView = m_weights_buffer_view;
|
||||||
|
weightsAccessor.componentType = JsonAccessorComponentType::FLOAT;
|
||||||
|
weightsAccessor.count = xmodel.m_vertices.size();
|
||||||
|
weightsAccessor.type = JsonAccessorType::VEC4;
|
||||||
|
m_weights_accessor = gltf.accessors->size();
|
||||||
|
gltf.accessors->emplace_back(weightsAccessor);
|
||||||
|
}
|
||||||
|
|
||||||
m_first_index_accessor = gltf.accessors->size();
|
m_first_index_accessor = gltf.accessors->size();
|
||||||
for (auto i = 0u; i < xmodel.m_objects.size(); i++)
|
for (auto i = 0u; i < xmodel.m_objects.size(); i++)
|
||||||
{
|
{
|
||||||
@ -377,6 +435,37 @@ namespace
|
|||||||
gltf.accessors.value()[m_position_accessor].max = std::vector({maxPosition[0], maxPosition[1], maxPosition[2]});
|
gltf.accessors.value()[m_position_accessor].max = std::vector({maxPosition[0], maxPosition[1], maxPosition[2]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!xmodel.m_vertex_bone_weights.empty())
|
||||||
|
{
|
||||||
|
assert(xmodel.m_vertex_bone_weights.size() == xmodel.m_vertices.size());
|
||||||
|
|
||||||
|
auto* joints = reinterpret_cast<uint8_t*>(&bufferData[currentBufferOffset]);
|
||||||
|
auto* weights = reinterpret_cast<float*>(&bufferData[currentBufferOffset + sizeof(uint8_t) * 4u * xmodel.m_vertex_bone_weights.size()]);
|
||||||
|
for (const auto& commonVertexWeights : xmodel.m_vertex_bone_weights)
|
||||||
|
{
|
||||||
|
assert(commonVertexWeights.weights != nullptr);
|
||||||
|
assert(commonVertexWeights.weightCount <= 4u);
|
||||||
|
|
||||||
|
const auto commonVertexWeightCount = std::min(commonVertexWeights.weightCount, 4u);
|
||||||
|
for (auto i = 0u; i < commonVertexWeightCount; i++)
|
||||||
|
{
|
||||||
|
joints[i] = static_cast<unsigned char>(commonVertexWeights.weights[i].boneIndex);
|
||||||
|
weights[i] = commonVertexWeights.weights[i].weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = commonVertexWeightCount; i < 4u; i++)
|
||||||
|
{
|
||||||
|
joints[i] = 0u;
|
||||||
|
weights[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
joints += 4u;
|
||||||
|
weights += 4u;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentBufferOffset += (sizeof(uint8_t) + sizeof(float)) * 4u * xmodel.m_vertex_bone_weights.size();
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& object : xmodel.m_objects)
|
for (const auto& object : xmodel.m_objects)
|
||||||
{
|
{
|
||||||
for (const auto& face : object.m_faces)
|
for (const auto& face : object.m_faces)
|
||||||
@ -399,6 +488,11 @@ namespace
|
|||||||
|
|
||||||
result += xmodel.m_vertices.size() * sizeof(GltfVertex);
|
result += xmodel.m_vertices.size() * sizeof(GltfVertex);
|
||||||
|
|
||||||
|
if (!xmodel.m_vertex_bone_weights.empty())
|
||||||
|
{
|
||||||
|
result += xmodel.m_vertices.size() * 4u * (sizeof(uint8_t) + sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& object : xmodel.m_objects)
|
for (const auto& object : xmodel.m_objects)
|
||||||
{
|
{
|
||||||
result += object.m_faces.size() * sizeof(unsigned short) * 3u;
|
result += object.m_faces.size() * sizeof(unsigned short) * 3u;
|
||||||
@ -421,11 +515,16 @@ namespace
|
|||||||
gltf.buffers->emplace_back(std::move(jsonBuffer));
|
gltf.buffers->emplace_back(std::move(jsonBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned m_skeleton_node = 0u;
|
unsigned m_mesh_node = 0u;
|
||||||
|
unsigned m_first_bone_node = 0u;
|
||||||
unsigned m_position_accessor = 0u;
|
unsigned m_position_accessor = 0u;
|
||||||
unsigned m_normal_accessor = 0u;
|
unsigned m_normal_accessor = 0u;
|
||||||
unsigned m_uv_accessor = 0u;
|
unsigned m_uv_accessor = 0u;
|
||||||
|
unsigned m_joints_accessor = 0u;
|
||||||
|
unsigned m_weights_accessor = 0u;
|
||||||
unsigned m_vertex_buffer_view = 0u;
|
unsigned m_vertex_buffer_view = 0u;
|
||||||
|
unsigned m_joints_buffer_view = 0u;
|
||||||
|
unsigned m_weights_buffer_view = 0u;
|
||||||
unsigned m_first_index_buffer_view = 0u;
|
unsigned m_first_index_buffer_view = 0u;
|
||||||
unsigned m_first_index_accessor = 0u;
|
unsigned m_first_index_accessor = 0u;
|
||||||
|
|
||||||
|
@ -51,6 +51,96 @@ public:
|
|||||||
|
|
||||||
return Matrix<T>(m00, m01, m02, 0, m10, m11, m12, 0, m20, m21, m22, 0, 0, 0, 0, T(1.0));
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
T lengthSquared()
|
||||||
|
{
|
||||||
|
return Quaternion::dot(*this, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T length()
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Quaternion<float> Quaternion32;
|
typedef Quaternion<float> Quaternion32;
|
||||||
|
@ -24,6 +24,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~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)
|
_NODISCARD T& operator()(const size_t index)
|
||||||
{
|
{
|
||||||
assert(index < 2);
|
assert(index < 2);
|
||||||
@ -55,6 +61,32 @@ public:
|
|||||||
{
|
{
|
||||||
return m_value[1];
|
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<float> Vector2f;
|
||||||
@ -80,6 +112,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~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)
|
_NODISCARD T& operator()(const size_t index)
|
||||||
{
|
{
|
||||||
assert(index < 3);
|
assert(index < 3);
|
||||||
@ -151,6 +189,34 @@ public:
|
|||||||
{
|
{
|
||||||
return m_value[2];
|
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<float> Vector3f;
|
||||||
@ -176,6 +242,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~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)
|
_NODISCARD T& operator()(const size_t index)
|
||||||
{
|
{
|
||||||
assert(index < 4);
|
assert(index < 4);
|
||||||
@ -267,6 +339,36 @@ public:
|
|||||||
{
|
{
|
||||||
return m_value[3];
|
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<float> Vector4f;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user