update for J3ML 3.0

This commit is contained in:
2024-08-21 13:36:31 -04:00
parent cedad4f3ea
commit 5c23ff7701
10 changed files with 49 additions and 793 deletions

View File

@@ -19,6 +19,8 @@ set(CMAKE_CXX_STANDARD 20)
file(GLOB_RECURSE HEADERS "include/*.h") file(GLOB_RECURSE HEADERS "include/*.h")
file(GLOB_RECURSE SOURCES "src/*.cpp") file(GLOB_RECURSE SOURCES "src/*.cpp")
include_directories("include" ${J3ML_SOURCE_DIR}/include)
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "In-Source builds are not allowed") message(FATAL_ERROR "In-Source builds are not allowed")
endif() endif()
@@ -31,12 +33,9 @@ if (WIN32)
add_library(Collage STATIC ${SOURCES} ${HEADERS}) add_library(Collage STATIC ${SOURCES} ${HEADERS})
endif() endif()
target_include_directories(Collage PUBLIC ${PROJECT_SOURCE_DIR}/include ${J3ML_SOURCE_DIR}/include)
add_executable(CollageTest main.cpp) add_executable(CollageTest main.cpp)
set_target_properties(Collage PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(Collage PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(Collage PUBLIC J3ML) target_link_libraries(Collage PUBLIC J3ML)
target_link_libraries(CollageTest PUBLIC Collage) target_link_libraries(CollageTest PUBLIC Collage)
set_target_properties(CollageTest PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(CollageTest PROPERTIES LINKER_LANGUAGE CXX)

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <chrono>
#include <Collage/types/bone.h> #include <Collage/types/bone.h>
struct KeyFrame { struct KeyFrame {
@@ -8,21 +7,4 @@ struct KeyFrame {
Bone bone; Bone bone;
}; };
class Animation { typedef std::vector<KeyFrame> Animation;
public:
std::string name;
float deltaBetweenKeyFrames;
std::vector<KeyFrame> keyFrames;
};
class AnimationState { //Information which would be stored on each animated entity.
protected:
Animation* animation = nullptr;
public:
std::vector<Animation*>* animations; //Will point to the list of animations on the model.
std::chrono::high_resolution_clock::time_point start; //When the current animation was started.
[[nodiscard]] float animationTime() const; //The amount of time in ms that the animation has been running for.
Animation* getAnimation();
void setAnimation(Animation* anim);
void reset();
};

View File

@@ -5,11 +5,10 @@ class Bone {
protected: protected:
std::string name; std::string name;
Matrix4x4 matrix; Matrix4x4 matrix;
//float weight; float weight;
Bone* parent; Bone* parent;
std::vector<Bone*> children; std::vector<Bone*> children;
public: public:
int index;
bool isRootBone(); bool isRootBone();
bool hasChildren(); bool hasChildren();
const Matrix4x4& getMatrix(); const Matrix4x4& getMatrix();
@@ -17,11 +16,7 @@ public:
void appendChild(const Bone& bone); void appendChild(const Bone& bone);
unsigned int getDepth(); //The "depth" refers to how far in the bone is on the bonemap. For ex, the fingers would be deeper than the elbow. unsigned int getDepth(); //The "depth" refers to how far in the bone is on the bonemap. For ex, the fingers would be deeper than the elbow.
Bone* getParent(); Bone* getParent();
void setParent(Bone* b);
Bone* getChildByName(const std::string& bName); Bone* getChildByName(const std::string& bName);
Bone* getChildByNameRecursive(const std::string& bName); Bone* getChildByNameRecursive(const std::string& bName);
Bone* getChildByIndexRecursive(int i);
Bone* getFirstChild(); Bone* getFirstChild();
const std::string& getName();
void setName(const std::string& n);
}; };

View File

@@ -1,13 +1,13 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include<J3ML/Geometry.hpp> #include <sstream>
#include <fstream>
#include <J3ML/LinearAlgebra.hpp> #include <J3ML/LinearAlgebra.hpp>
#include <J3ML/LinearAlgebra/Vector3.hpp> #include <J3ML/LinearAlgebra/Vector3.hpp>
#include<J3ML/Geometry.hpp>
#include <Collage/types/textureInfo.h> #include <Collage/types/textureInfo.h>
#include <Collage/types/bone.h>
typedef Vector3 Vertex; typedef Vector3 Vertex;
typedef Vector3 TextureCoordinate;
enum struct ModelType : uint8_t { enum struct ModelType : uint8_t {
WAVEFRONT_OBJ = 0, WAVEFRONT_OBJ = 0,
@@ -16,32 +16,35 @@ enum struct ModelType : uint8_t {
COLLADA = 3, //*Very* complicated. COLLADA = 3, //*Very* complicated.
}; };
struct FaceIndices {
unsigned int vertexIndex[3];
unsigned int texCoordIndex[3];
};
class SkeletalVertex : public Vertex {
int8_t joints[3]; //The index of 4 bones that can effect the vertex. 0 represents an empty slot. -1 represents the root bone.
Vector4 weights; //The 4 weights must total to 1.0
};
class Model { class Model {
protected: protected:
void load(const std::string& file); void load(const std::string& file);
void loadOBJ(const std::string& filename); void loadOBJ(const std::string& filename);
void loadAMO(const std::string& filename);
public:
std::string name;
ModelType type;
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
std::vector<TextureCoordinate> textureCoords; std::vector<TextureInformation> textureInfo;
//std::vector<TextureInformation> textureInfo; public:
ModelType type;
const std::vector<Vertex>& getVertices();
const std::vector<unsigned int>& getIndices();
const std::vector<TextureInformation>& getTextureInformation();
Model() = default; Model() = default;
explicit Model(const std::string& file); explicit Model(const std::string& file);
}; };
class SkeletalVertex : public Vertex {
public:
std::vector<int> bones; //The index of bones that can effect the vertex. 0 represents an empty slot. -1 represents the root bone.
std::vector<float> weights;
};
class SkeletalModel : public Model { class SkeletalModel : public Model {
protected: protected:
void loadAMO(const std::string& filename);
public:
std::vector<SkeletalVertex> vertices; std::vector<SkeletalVertex> vertices;
Bone boneMap; public:
}; std::vector<SkeletalVertex>& getSkeletalVertices();
};

View File

@@ -1,5 +1,4 @@
#include <Collage/collage.h> #include <iostream>
int main() { int main() {
Model m = Model("chicken.amo");
} }

View File

@@ -1,678 +0,0 @@
#include <sstream>
#include <fstream>
#include <iostream>
#include <tuple>
#include <vector>
#include <Collage/types/model.h>
/*
* This is unfinished and janky as shit. You have been warned.
*
* Currently values are parsed into temporary structs until we
* figure out what to do with them. The animation parsing is
* particularly fucked right now. There's plans to do more
* cleanup later when we throw this all at the game engine.
*
* I hope for us to be able to load the chicken into the
* engine soon.
*
* - Maxine Hayes
*
* p.s perhaps stringers are a good idea for exporting.
*/
struct Frame {
int id;
std::vector<float> n;
};
void operator>>(std::istream& in, Frame& q) {
in >> q.id;
int i;
for (i=0; i<7; i++) {
float v;
in >> v;
q.n.push_back(v);
}
}
struct KeyFrame {
float start;
int frame_cnt;
};
void operator>>(std::istream& in, KeyFrame& q) {
// throw away prefix
std::string p;
in >> p;
in >> q.start;
in >> q.frame_cnt;
}
struct FrameSet {
KeyFrame k;
std::vector<Frame> f;
};
FrameSet parse_fs(std::istringstream& s, std::ifstream& f) {
FrameSet fs;
s >> fs.k;
int i;
for (i=0; i<fs.k.frame_cnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Frame frame;
stream >> frame;
fs.f.push_back(frame);
} else {
break;
}
}
return fs;
}
/*
void operator>>(std::istream& in, FrameSet& q) {
in >> q.k;
int i;
for (i=0; i<q.k.frame_cnt; i++) {
Frame f;
in >> f;
q.f.push_back(f);
}
}
*/
struct Animation_Meta {
std::string name;
int duration;
int keyframe_cnt;
};
void operator>>(std::istream& in, Animation_Meta& q) {
// throw away prefix
std::string p;
in >> p;
in >> q.name;
in >> q.duration;
in >> q.keyframe_cnt;
}
struct Animation {
Animation_Meta meta;
std::vector<FrameSet> fs;
};
// Parse animations
std::vector<Animation> parse_a(std::istringstream& s, std::ifstream& f) {
int acnt;
s >> acnt;
std::cout << "a " << acnt << std::endl;
std::vector<Animation> a;
int i;
for (i=0; i<acnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Animation animation;
stream >> animation.meta;
int i;
for (i=0; i<animation.meta.keyframe_cnt; i++) {
std::string ll;
getline(f, ll);
std::istringstream stream(ll);
FrameSet frameset;
frameset = parse_fs(stream, f);
animation.fs.push_back(frameset);
}
a.push_back(animation);
} else {
break;
}
}
return a;
}
struct Joint {
std::string name;
int x;
std::vector<float> n;
};
void operator>>(std::istream& in, Joint& q) {
in >> q.name >> q.x;
int i;
for (i=0; i<16; i++) {
float f;
in >> f;
q.n.push_back(f);
}
}
// Parse joints
std::vector<Joint> parse_j(std::istringstream& s, std::ifstream& f) {
// get count
int jcnt;
s >> jcnt;
std::cout << "j " << jcnt << std::endl;
// return later
std::vector<Joint> js;
// parse lines until count
int i;
for (i=0; i<jcnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Joint j;
stream >> j;
js.push_back(j);
} else {
break;
}
}
return js;
}
struct Face {
std::vector<int> n;
};
void operator>>(std::istream& in, Face& q) {
int i;
for (i=0; i<15; i++) {
int v;
in >> v;
q.n.push_back(v);
}
}
// Parse faces
std::vector<Face> parse_f(std::istringstream& s, std::ifstream& f) {
// get count
int facescnt;
s >> facescnt;
std::cout << "f " << facescnt << std::endl;
// return later
std::vector<Face> faces;
// parse until count
int i;
for (i=0; i<facescnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Face face;
stream >> face;
faces.push_back(face);
} else {
break;
}
}
return faces;
}
struct Vweight {
std::vector<float> n;
};
void operator>>(std::istream& in, Vweight& q) {
int i;
for (i=0; i<4; i++) {
float v;
in >> v;
q.n.push_back(v);
}
}
// Parse vertex weights
std::vector<Vweight> parse_vw(std::istringstream& s, std::ifstream& f) {
// get count
int vwcnt;
s >> vwcnt;
std::cout << "vw " << vwcnt << std::endl;
// return later
std::vector<Vweight> vw;
// parse lines until count
int i;
for (i=0; i<vwcnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Vweight vweight;
stream >> vweight;
vw.push_back(vweight);
} else {
break;
}
}
return vw;
}
struct Vjoint {
std::vector<int> n;
};
void operator>>(std::istream& in, Vjoint& q) {
int i;
for (i=0; i<4; i++) {
int v;
in >> v;
q.n.push_back(v);
}
}
// Parse vertex joints
std::vector<Vjoint> parse_vj(std::istringstream& s, std::ifstream& f) {
// get count
int vjcnt;
s >> vjcnt;
std::cout << "vj " << vjcnt << std::endl;
// return later
std::vector<Vjoint> vj;
// parse lines until count
int i;
for (i=0; i<vjcnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Vjoint vjoint;
stream >> vjoint;
vj.push_back(vjoint);
} else {
break;
}
}
return vj;
}
struct Vnormal {
std::vector<float> n;
};
void operator>>(std::istream& in, Vnormal& q) {
int i;
for (i=0; i<3; i++) {
float v;
in >> v;
q.n.push_back(v);
}
}
// Parse vertex normals
std::vector<Vnormal> parse_vn(std::istringstream& s, std::ifstream& f) {
// get count
int vncnt;
s >> vncnt;
std::cout << "vn " << vncnt << std::endl;
// return later
std::vector<Vnormal> vn;
// parse lines until count
int i;
for (i=0; i<vncnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Vnormal vnormal;
stream >> vnormal;
vn.push_back(vnormal);
} else {
break;
}
}
return vn;
}
struct Vtexture {
std::vector<float> n;
};
void operator>>(std::istream& in, Vtexture& q) {
int i;
for (i=0; i<2; i++) {
float v;
in >> v;
q.n.push_back(v);
}
}
// Parse vertex textures
std::vector<Vtexture> parse_vt(std::istringstream& s, std::ifstream& f) {
// get count
int vtcnt;
s >> vtcnt;
std::cout << "vt " << vtcnt << std::endl;
// return later
std::vector<Vtexture> vt;
// parse until count
int i;
for (i=0; i<vtcnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Vtexture vtexture;
stream >> vtexture;
vt.push_back(vtexture);
} else {
break;
}
}
return vt;
}
struct Vertice {
std::vector<float> n;
};
void operator>>(std::istream& in, Vertice& q) {
int i;
for (i=0; i<3; i++) {
float v;
in >> v;
q.n.push_back(v);
}
}
// Parse vertices
std::vector<Vertice> parse_v(std::istringstream& s, std::ifstream& f) {
// get count
int vcnt;
s >> vcnt;
std::cout << "v " << vcnt << std::endl;
// return later
std::vector<Vertice> v;
// parses lines until count
int i;
for (i=0; i<vcnt; i++) {
std::string l;
if (getline(f, l)) {
std::istringstream stream(l);
Vertice vertice;
stream >> vertice;
v.push_back(vertice);
} else {
break;
}
}
return v;
}
// Parse Animated Object
std::tuple<std::string, int> parse_ao(std::istringstream& s) {
std::string name;
int statecnt;
s >> name >> statecnt;
return {name, statecnt};
}
void Model::loadAMO(const std::string& filename) {
// Print filename
std::cout << filename << std::endl;
// Create ifstream from AMO file
std::ifstream file(filename);
std::string line;
while (getline(file, line)) {
// Get prefix
std::istringstream stream(line);
std::string prefix;
stream >> prefix;
if (prefix == "ao") {
std::tuple<std::string, int> r;
r = parse_ao(stream);
std::cout << get<0>(r) << " " << get<1>(r) << std::endl;
} else if (prefix == "v") {
std::vector<Vertice> v;
v = parse_v(stream, file);
for (const Vertice& i: v) {
for (const float& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "vt") {
std::vector<Vtexture> vt;
vt = parse_vt(stream, file);
for (const Vtexture& i: vt) {
for (const float& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "vn") {
std::vector<Vnormal> vn;
vn = parse_vn(stream, file);
for (const Vnormal& i: vn) {
for (const float& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "vj") {
std::vector<Vjoint> vj;
vj = parse_vj(stream, file);
for (const Vjoint& i: vj) {
for (const int& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "vw") {
std::vector<Vweight> vw;
vw = parse_vw(stream, file);
for (const Vweight& i: vw) {
for (const float& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "f") {
std::vector<Face> faces;
faces = parse_f(stream, file);
for (const Face& i: faces) {
for (const int& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "j") {
std::vector<Joint> j;
j = parse_j(stream, file);
for (const Joint& i: j) {
std::cout << i.name << " " << i.x << " ";
for (const float& ii: i.n) {
std::cout << ii << " ";
}
std::cout << std::endl;
}
} else if (prefix == "a") {
std::vector<Animation> a;
a = parse_a(stream, file);
for (const Animation& i: a) {
std::cout << i.meta.name << " " << i.meta.duration << " " << i.meta.keyframe_cnt << std::endl;
for (const FrameSet& ii: i.fs) {
std::cout << "k " << ii.k.start << " " << ii.k.frame_cnt << std::endl;
for (const Frame& iii: ii.f) {
std::cout << "FRAME " << iii.id << " ";
for (const float& iiii: iii.n) {
std::cout << iiii << " ";
}
std::cout << std::endl;
}
}
}
}
}
file.close();
}
/*
void Model::loadAMO(const std::string& filename) {
std::cout << filename << std::endl;
std::ifstream file(filename);
std::vector<Vector3> positions;
std::vector<Vector2> uvs;
TextureInformation tInfo = {};
std::string line;
while (std::getline(file, line)) {
std::istringstream stream(line);
std::string prefix;
stream >> prefix;
// Animated Object
if (prefix == "ao") {
std::string name;
int statecnt;
stream >> name >> statecnt;
std::cout << "ao " << name << " " << statecnt << std::endl;
// Vertices Count
} else if (prefix == "v") {
int vcnt;
stream >> vcnt;
std::cout << "v " << vcnt << std::endl;
for (int i=0; i<=vcnt; i++) {
Vector3 v;
v = parse_v(stream);
std::cout << v.x << " " << v.y << " " << v.z << std::endl;
}
// Vertex Texture Count
} else if (prefix == "vt") {
int vtcnt;
stream >> vtcnt;
std::cout << "vt " << vtcnt << std::endl;
// Vertex Normals Count
} else if (prefix == "vn") {
int vncnt;
stream >> vncnt;
std::cout << "vn " << vncnt << std::endl;
// Vertex Joint Count
} else if (prefix == "vj") {
int vjcnt;
stream >> vjcnt;
std::cout << "vj " << vjcnt << std::endl;
// Vertex Weights Count
} else if (prefix == "vw") {
int vwcnt;
stream >> vwcnt;
std::cout << "vw " << vwcnt << std::endl;
// Faces Count
} else if (prefix == "f") {
int fcnt;
stream >> fcnt;
std::cout << "f " << fcnt << std::endl;
// Joints Count
} else if (prefix == "j") {
int jcnt;
stream >> jcnt;
std::cout << "j " << jcnt << std::endl;
// Animations Count
} else if (prefix == "a") {
int acnt;
stream >> acnt;
std::cout << "a " << acnt << std::endl;
// Start Animation Definition
} else if (prefix == "an") {
std::string aname;
int atimems; // Animation time in milliseconds
int n_interps; // Number of interpolations between key frames
stream >> aname >> atimems >> n_interps;
std::cout << "an " << aname << " " << atimems << " " << n_interps << std::endl;
// Animation Key Frame
} else if (prefix == "k") {
float kstart; // Timestamp of when key fram starts.
int n_movbones; // Number of moving bones.
stream >> kstart >> n_movbones;
std::cout << "k " << kstart << " " << n_movbones << std::endl;
// End
} else if (prefix == "end") {
std::cout << "End of AMO" << std::endl;
break;
}
}
file.close();
}
*/

View File

@@ -1,9 +1,6 @@
#include <sstream> #include <iostream>
#include <fstream>
#include <Collage/types/model.h> #include <Collage/types/model.h>
//The OBJ *must* be exported as a triangle mesh and without normals.
//TODO support more options.
void Model::loadOBJ(const std::string& filename) { void Model::loadOBJ(const std::string& filename) {
std::ifstream file(filename); std::ifstream file(filename);
std::vector<Vector3> positions; std::vector<Vector3> positions;
@@ -31,6 +28,7 @@ void Model::loadOBJ(const std::string& filename) {
vertexIndex[i]--; vertexIndex[i]--;
texCoordIndex[i]--; texCoordIndex[i]--;
} }
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
Vertex vertex; Vertex vertex;
Vector2 textureCoordinate; Vector2 textureCoordinate;
@@ -42,7 +40,6 @@ void Model::loadOBJ(const std::string& filename) {
} }
} }
} }
//textureInfo.push_back(tInfo); // <- Fix yo shit textureInfo.push_back(tInfo);
file.close(); file.close();
type = ModelType::WAVEFRONT_OBJ; };
};

View File

@@ -1,21 +1,2 @@
#include <Collage/types/animation.h> #include <Collage/types/animation.h>
#include <Collage/types/keyFrame.h>
Animation* AnimationState::getAnimation() {
if (animation == nullptr)
throw std::runtime_error("There is no current animation.");
return animation;
}
void AnimationState::setAnimation(Animation* anim) {
animation = anim;
start = std::chrono::high_resolution_clock::now();
}
void AnimationState::reset() {
animation = animations[0][0]; //The "idle" or "default" animation should *always* be in slot 0.
start = std::chrono::high_resolution_clock::now();
}
float AnimationState::animationTime() const {
return std::chrono::duration<float, std::milli>(std::chrono::high_resolution_clock::now() - start).count();
}

View File

@@ -33,22 +33,12 @@ Bone* Bone::getChildByName(const std::string& bName) {
for (auto& bone : children) for (auto& bone : children)
if (bone->name == bName) if (bone->name == bName)
return bone; return bone;
return nullptr;
} }
Bone* Bone::getChildByNameRecursive(const std::string& bName) { Bone *Bone::getChildByNameRecursive(const std::string &bName) {
if (children.empty()) if (children.empty())
return nullptr; return nullptr;
for (auto& bone : children) {
if (bone->name == bName)
return bone;
Bone* result = bone->getChildByNameRecursive(bName);
if (result != nullptr)
return result;
}
return nullptr;
} }
bool Bone::hasChildren() { bool Bone::hasChildren() {
@@ -77,29 +67,3 @@ unsigned int Bone::getDepth() {
return depth; return depth;
} }
const std::string &Bone::getName() {
return name;
}
void Bone::setName(const std::string &n) {
name = n;
}
void Bone::setParent(Bone * b) {
parent = b;
}
Bone* Bone::getChildByIndexRecursive(int ind) {
if (children.empty())
return nullptr;
for (auto& bone : children) {
if (bone->index == ind)
return bone;
Bone* result = bone->getChildByIndexRecursive(ind);
if (result != nullptr)
return result;
}
return nullptr;
}

View File

@@ -3,10 +3,24 @@
void Model::load(const std::string& file) { void Model::load(const std::string& file) {
if (file.ends_with(".obj")) if (file.ends_with(".obj"))
loadOBJ(file); loadOBJ(file);
if (file.ends_with(".amo")) }
loadAMO(file);
const std::vector<Vector3>& Model::getVertices() {
return vertices;
}
const std::vector<unsigned int>& Model::getIndices() {
return indices;
}
const std::vector<TextureInformation>& Model::getTextureInformation() {
return textureInfo;
} }
Model::Model(const std::string &file) { Model::Model(const std::string &file) {
load(file); load(file);
} }
std::vector<SkeletalVertex>& SkeletalModel::getSkeletalVertices() {
return vertices;
}