Structures for skeletons
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m57s
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m57s
This commit is contained in:
106
include/JGL/types/Skeleton.h
Normal file
106
include/JGL/types/Skeleton.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <J3ML/LinearAlgebra/Vector3.hpp>
|
||||
#include <J3ML/LinearAlgebra/Matrix4x4.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace JGL {
|
||||
class Bone;
|
||||
class SkeletalVertex;
|
||||
class Skeleton;
|
||||
class KeyFrame;
|
||||
class Animation;
|
||||
}
|
||||
|
||||
class JGL::SkeletalVertex : public Vector3 {
|
||||
private:
|
||||
std::array<int, 4> bone_ids = { 0, 0, 0, 0 };
|
||||
std::array<float, 4> bone_weights = { 0, 0, 0, 0 };
|
||||
public:
|
||||
[[nodiscard]] std::array<int, 4> GetAffectingBoneIDs() const;
|
||||
[[nodiscard]] std::array<float, 4> GetAffectingBoneWeights() const;
|
||||
public:
|
||||
SkeletalVertex() = default;
|
||||
/// These cannpt be longer than 4.
|
||||
SkeletalVertex(const Vector3& rhs, const std::vector<int>& bone_ids, const std::vector<float>& bone_weights);
|
||||
};
|
||||
|
||||
class JGL::Bone {
|
||||
private:
|
||||
int id = 0;
|
||||
// Not every gltf2 model includes names, but I'll still include it.
|
||||
std::string name;
|
||||
Matrix4x4 inverse_bind_matrix = Matrix4x4::Identity;
|
||||
Matrix4x4 offset_matrix = Matrix4x4::Identity;
|
||||
Matrix4x4 final_transform = Matrix4x4::Identity;
|
||||
int parent_id = -1;
|
||||
std::vector<int> children{};
|
||||
public:
|
||||
[[nodiscard]] int GetID() const;
|
||||
[[nodiscard]] std::string GetName() const;
|
||||
[[nodiscard]] Matrix4x4 GetInverseBindMatrix() const;
|
||||
[[nodiscard]] Matrix4x4 GetOffsetMatrix() const;
|
||||
[[nodiscard]] Matrix4x4 GetFinalTransform() const;
|
||||
[[nodiscard]] bool IsRootBone() const;
|
||||
public:
|
||||
[[nodiscard]] int GetParentID() const;
|
||||
[[nodiscard]] std::vector<int> GetChildren() const;
|
||||
public:
|
||||
void SetParent(int parent_id);
|
||||
void AppendChild(int new_child);
|
||||
void SetID(int numeric_id);
|
||||
void SetName(const std::string& string_id);
|
||||
void SetInverseBindMatrix(const Matrix4x4& inverse_bind);
|
||||
void SetOffsetMatrix(const Matrix4x4& offset);
|
||||
void SetFinalTransformMatrix(const Matrix4x4& final);
|
||||
public:
|
||||
~Bone() = default;
|
||||
Bone() = default;
|
||||
explicit Bone(int numeric_id, const std::string& string_id = "", int parent_id = -1, const std::vector<int>& children_ids = {},
|
||||
const Matrix4x4& inverse_bind = Matrix4x4::Identity, const Matrix4x4& offset = Matrix4x4::Identity, const Matrix4x4& final = Matrix4x4::Identity);
|
||||
};
|
||||
|
||||
class JGL::Skeleton {
|
||||
private:
|
||||
Bone root;
|
||||
std::vector<Bone> bones;
|
||||
public:
|
||||
[[nodiscard]] Bone* GetRootBone();
|
||||
[[nodiscard]] Bone* FindBone(int id);
|
||||
[[nodiscard]] Bone* FindBone(const std::string& string_id);
|
||||
public:
|
||||
void AppendBone(const Bone& bone);
|
||||
public:
|
||||
explicit Skeleton(const Bone& root_bone, const std::vector<Bone>& children = {});
|
||||
~Skeleton() = default;
|
||||
Skeleton() = default;
|
||||
};
|
||||
|
||||
class JGL::KeyFrame {
|
||||
private:
|
||||
float time_stamp = 0;
|
||||
Skeleton pose;
|
||||
public:
|
||||
[[nodiscard]] float GetTimeStamp() const;
|
||||
[[nodiscard]] Skeleton GetSkeleton() const;
|
||||
public:
|
||||
KeyFrame(const Skeleton& pose, float time_stamp);
|
||||
};
|
||||
|
||||
class JGL::Animation {
|
||||
private:
|
||||
float length;
|
||||
std::vector<KeyFrame> key_frames;
|
||||
public:
|
||||
[[nodiscard]] float GetDuratrion() const;
|
||||
[[nodiscard]] std::vector<KeyFrame> GetKeyFrames() const;
|
||||
public:
|
||||
void AppendKeyFrame(const KeyFrame& new_key);
|
||||
void SetDuration(float duration);
|
||||
public:
|
||||
explicit Animation(float duration, const std::vector<KeyFrame>& key_frames = {});
|
||||
~Animation() = default;
|
||||
};
|
||||
|
||||
|
@@ -24,15 +24,15 @@ private:
|
||||
public:
|
||||
VRamList(const GLuint* data, const long& length);
|
||||
VRamList(const GLfloat* data, const long& length);
|
||||
VRamList(Vector2* data, const long& length);
|
||||
VRamList(Vector3* data, const long& length);
|
||||
VRamList(Vector4* data, const long& length);
|
||||
VRamList(const Vector2* data, const long& length);
|
||||
VRamList(const Vector3* data, const long& length);
|
||||
VRamList(const Vector4* data, const long& length);
|
||||
|
||||
~VRamList();
|
||||
/** Copying around the VBO data to a new VBO like this is slow.
|
||||
* Pass to function by const reference or pointer always. */
|
||||
VRamList(const VRamList& rhs);
|
||||
|
||||
VRamList() = default;
|
||||
public:
|
||||
[[nodiscard]] GLuint GetHandle() const;
|
||||
/// Returns the number of elements in the list.
|
||||
|
@@ -78,5 +78,9 @@ public:
|
||||
/// @param translate_part The center of the box would be shifted in 3D space by this. Primarily for world space.
|
||||
[[nodiscard]] AABB GetMEAABB(const Matrix3x3& rotation_matrix, const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
|
||||
[[nodiscard]] AABB GetMEAABB(const Matrix4x4& instance_matrix, bool translate = false) const;
|
||||
public:
|
||||
/// Vertices are required, Everything else is optional.
|
||||
VertexArray(const Vector3* vertex_positions, const long& vp_length, const unsigned int* vertex_indices = nullptr, const long& vi_length = 0, const Normal* vertex_normals = nullptr, const long& vn_length = 0,
|
||||
const TextureCoordinate* texture_coordinates = nullptr, const long& vt_length = 0);
|
||||
};
|
||||
|
||||
|
163
src/types/Skeleton.cpp
Normal file
163
src/types/Skeleton.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#include <JGL/types/Skeleton.h>
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <cstring>
|
||||
|
||||
using namespace JGL;
|
||||
|
||||
std::array<int, 4> JGL::SkeletalVertex::GetAffectingBoneIDs() const {
|
||||
return bone_ids;
|
||||
}
|
||||
|
||||
std::array<float, 4> JGL::SkeletalVertex::GetAffectingBoneWeights() const {
|
||||
return bone_weights;
|
||||
}
|
||||
|
||||
JGL::SkeletalVertex::SkeletalVertex(const Vector3& rhs, const std::vector<int>& bone_ids, const std::vector<float>& bone_weights) {
|
||||
x = rhs.x; y = rhs.y; z = rhs.z;
|
||||
|
||||
if (bone_ids.size() > 4 || bone_weights.size() > 4)
|
||||
Logger::Fatal("Initialization of a skeletal vertex that is effected by more than 4 bones.");
|
||||
|
||||
memcpy(this->bone_ids.data(), bone_ids.data(), sizeof(int) * 4);
|
||||
memcpy(this->bone_weights.data(), bone_weights.data(), sizeof(float) * 4);
|
||||
}
|
||||
|
||||
bool JGL::Bone::IsRootBone() const {
|
||||
if (parent_id == -1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int JGL::Bone::GetID() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string JGL::Bone::GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
Matrix4x4 JGL::Bone::GetInverseBindMatrix() const {
|
||||
return inverse_bind_matrix;
|
||||
}
|
||||
|
||||
Matrix4x4 JGL::Bone::GetOffsetMatrix() const {
|
||||
return offset_matrix;
|
||||
}
|
||||
|
||||
Matrix4x4 JGL::Bone::GetFinalTransform() const {
|
||||
return final_transform;
|
||||
}
|
||||
|
||||
std::vector<int> JGL::Bone::GetChildren() const {
|
||||
return children;
|
||||
}
|
||||
|
||||
void Bone::SetParent(int parent_id) {
|
||||
this->parent_id = parent_id;
|
||||
}
|
||||
|
||||
void Bone::AppendChild(int new_child) {
|
||||
children.push_back(new_child);
|
||||
}
|
||||
|
||||
void Bone::SetID(int numeric_id) {
|
||||
id = numeric_id;
|
||||
}
|
||||
|
||||
void Bone::SetName(const std::string& string_id) {
|
||||
name = string_id;
|
||||
}
|
||||
|
||||
void Bone::SetInverseBindMatrix(const Matrix4x4& inverse_bind) {
|
||||
inverse_bind_matrix = inverse_bind;
|
||||
}
|
||||
|
||||
void Bone::SetOffsetMatrix(const Matrix4x4& offset) {
|
||||
offset_matrix = offset;
|
||||
}
|
||||
|
||||
void Bone::SetFinalTransformMatrix(const Matrix4x4& final) {
|
||||
final_transform = final;
|
||||
}
|
||||
|
||||
int Bone::GetParentID() const {
|
||||
return parent_id;
|
||||
}
|
||||
|
||||
Bone::Bone(int numeric_id, const std::string& string_id, int parent_bone, const std::vector<int>& children_ids, const Matrix4x4& inverse_bind, const Matrix4x4& offset, const Matrix4x4& final) {
|
||||
id = numeric_id;
|
||||
name = string_id;
|
||||
parent_id = parent_bone;
|
||||
inverse_bind_matrix = inverse_bind;
|
||||
offset_matrix = offset;
|
||||
final_transform = final;
|
||||
children = children_ids;
|
||||
}
|
||||
|
||||
Bone* Skeleton::GetRootBone() {
|
||||
return &root;
|
||||
}
|
||||
|
||||
Bone* Skeleton::FindBone(int id) {
|
||||
if (root.GetID() == id)
|
||||
return &root;
|
||||
|
||||
for (auto& bone : bones)
|
||||
if (bone.GetID() == id)
|
||||
return &bone;
|
||||
// If we couldn't find it.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bone* Skeleton::FindBone(const std::string& string_id) {
|
||||
if (root.GetName() == string_id)
|
||||
return &root;
|
||||
|
||||
for (auto& bone : bones)
|
||||
if (bone.GetName() == string_id)
|
||||
return &bone;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Skeleton::AppendBone(const Bone& new_bone) {
|
||||
bones.push_back(new_bone);
|
||||
}
|
||||
|
||||
Skeleton::Skeleton(const Bone& root_bone, const std::vector<Bone>& children) {
|
||||
root = root_bone;
|
||||
bones = children;
|
||||
}
|
||||
|
||||
float KeyFrame::GetTimeStamp() const {
|
||||
return time_stamp;
|
||||
}
|
||||
|
||||
Skeleton KeyFrame::GetSkeleton() const {
|
||||
return pose;
|
||||
}
|
||||
|
||||
KeyFrame::KeyFrame(const Skeleton& pose, float time_stamp) {
|
||||
this->pose = pose;
|
||||
this->time_stamp = time_stamp;
|
||||
}
|
||||
|
||||
Animation::Animation(float duration, const std::vector<KeyFrame>& key_frames) {
|
||||
length = duration;
|
||||
this->key_frames = key_frames;
|
||||
}
|
||||
|
||||
float Animation::GetDuratrion() const {
|
||||
return length;
|
||||
}
|
||||
|
||||
std::vector<KeyFrame> Animation::GetKeyFrames() const {
|
||||
return key_frames;
|
||||
}
|
||||
|
||||
void Animation::AppendKeyFrame(const KeyFrame& new_key) {
|
||||
key_frames.push_back(new_key);
|
||||
}
|
||||
|
||||
void Animation::SetDuration(float duration) {
|
||||
length = duration;
|
||||
}
|
@@ -25,10 +25,8 @@ void JGL::VRamList::load(const GLuint* data, const long& size) {
|
||||
}
|
||||
|
||||
void JGL::VRamList::Erase() {
|
||||
if (list_handle == 0) {
|
||||
JGL::Logger::Warning("Erasing an uninitialized VRamList?");
|
||||
if (list_handle == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
GLint current_element_array_buffer = 0;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_element_array_buffer);
|
||||
@@ -194,16 +192,16 @@ JGL::VRamList::VRamList(const GLuint* data, const long& length) {
|
||||
load(data, (long) sizeof(GLuint) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(Vector2* data, const long& length) {
|
||||
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector2) * length);
|
||||
JGL::VRamList::VRamList(const Vector2* data, const long& length) {
|
||||
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector2) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(Vector3* data, const long& length) {
|
||||
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector3) * length);
|
||||
JGL::VRamList::VRamList(const Vector3* data, const long& length) {
|
||||
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector3) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(Vector4* data, const long& length) {
|
||||
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector4) * length);
|
||||
JGL::VRamList::VRamList(const Vector4* data, const long& length) {
|
||||
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector4) * length);
|
||||
}
|
||||
|
||||
void JGL::VRamList::SetData(const GLfloat* data, const long& length) {
|
||||
|
@@ -139,3 +139,28 @@ AABB VertexArray::GetMEAABB(const Matrix3x3& rotation_matrix, const Vector3& sca
|
||||
AABB VertexArray::GetMEAABB(const Matrix4x4& instance_matrix, bool translate) const {
|
||||
return GetMEAABB(instance_matrix.GetRotatePart(), instance_matrix.GetScale(), translate ? instance_matrix.GetTranslatePart() : Vector3::Zero);
|
||||
}
|
||||
|
||||
VertexArray::VertexArray(const Vector3* vertex_positions, const long& vp_length, const unsigned int* vertex_indices, const long& vi_length,
|
||||
const Normal* vertex_normals, const long& vn_length, const TextureCoordinate* texture_coordinates, const long& vt_length) {
|
||||
|
||||
// TODO decimator. This is a total waste of memory as it sits.
|
||||
vertices = VRamList(vertex_positions, vp_length);
|
||||
if (vertex_indices && vi_length) {
|
||||
indices = VRamList(vertex_indices, vi_length);
|
||||
local_indices.resize(vi_length);
|
||||
memcpy(local_indices.data(), vertex_indices, sizeof(unsigned int) * vi_length);
|
||||
}
|
||||
|
||||
if (vertex_normals && vn_length) {
|
||||
normals = VRamList(vertex_normals, vn_length);
|
||||
local_normals.resize(vn_length);
|
||||
memcpy(local_normals.data(), vertex_indices, sizeof(Normal) * vn_length);
|
||||
}
|
||||
|
||||
if (texture_coordinates && vt_length) {
|
||||
this->texture_coordinates = VRamList(texture_coordinates, vt_length);
|
||||
local_normals.resize(vt_length);
|
||||
memcpy(local_texture_coordinates.data(), texture_coordinates, sizeof(TextureCoordinate) * vt_length);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user