Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
c4f4cffbdc |
@@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <types/keyFrame.h>
|
#include <types/bone.h>
|
||||||
|
|
||||||
|
struct KeyFrame {
|
||||||
|
uint index;
|
||||||
|
Bone bone;
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::vector<KeyFrame> Animation;
|
typedef std::vector<KeyFrame> Animation;
|
@@ -14,6 +14,7 @@ public:
|
|||||||
const Matrix4x4& getMatrix();
|
const Matrix4x4& getMatrix();
|
||||||
void setMatrix(const Matrix4x4& m);
|
void setMatrix(const Matrix4x4& m);
|
||||||
void appendChild(const Bone& bone);
|
void appendChild(const Bone& bone);
|
||||||
|
uint 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();
|
||||||
Bone* getChildByName(const std::string& bName);
|
Bone* getChildByName(const std::string& bName);
|
||||||
Bone* getChildByNameRecursive(const std::string& bName);
|
Bone* getChildByNameRecursive(const std::string& bName);
|
||||||
|
@@ -1,7 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <types/bone.h>
|
#include <types/bone.h>
|
||||||
|
|
||||||
struct KeyFrame {
|
|
||||||
uint index;
|
|
||||||
Bone bone;
|
|
||||||
};
|
|
||||||
|
@@ -16,25 +16,32 @@ 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 {
|
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.
|
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
|
Vector4 weights; //The 4 weights must total to 1.0
|
||||||
};
|
};
|
||||||
|
|
||||||
class Model {
|
class Model {
|
||||||
|
private:
|
||||||
|
void loadOBJ(const std::string& filename);
|
||||||
|
void load(const std::string& file);
|
||||||
protected:
|
protected:
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> vertices;
|
||||||
std::vector<uint> indices;
|
std::vector<uint> indices;
|
||||||
std::vector<TextureInformation> textureInfo;
|
std::vector<TextureInformation> textureInfo;
|
||||||
void load(const std::string& file);
|
void mapFaces(const FaceIndices& facedata, const std::vector<Vector3>& positions, const std::vector<Vector2>& uvs);
|
||||||
void load(const std::string& file, const ModelType& type);
|
|
||||||
public:
|
public:
|
||||||
ModelType type;
|
ModelType type;
|
||||||
const std::vector<Vertex>& getVertices();
|
const std::vector<Vertex>& getVertices();
|
||||||
const std::vector<uint>& getIndices();
|
const std::vector<uint>& getIndices();
|
||||||
const std::vector<TextureInformation>& getTextureInformation();
|
const std::vector<TextureInformation>& getTextureInformation();
|
||||||
Model() = default;
|
Model() = default;
|
||||||
Model(const std::string& file);
|
explicit Model(const std::string& file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SkeletalModel : public Model {
|
class SkeletalModel : public Model {
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
#include <J3ML/LinearAlgebra.h>
|
#include <J3ML/LinearAlgebra.h>
|
||||||
|
|
||||||
struct TextureInformation {
|
struct TextureInformation {
|
||||||
std::string name;
|
std::string path;
|
||||||
std::vector<Vector2> textureCoordinates;
|
std::vector<Vector2> textureCoordinates;
|
||||||
};
|
};
|
85
src/obj.cpp
Normal file
85
src/obj.cpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <types/model.h>
|
||||||
|
|
||||||
|
Vector3 ParseVertexCoordinatesFromOBJ(std::istringstream& stream) {
|
||||||
|
float x, y, z;
|
||||||
|
stream >> x >> y >> z;
|
||||||
|
return {x,y,z};
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 ParseVertexTextureCoordinatesFromOBJ(std::istringstream& stream) {
|
||||||
|
float u, v;
|
||||||
|
stream >> u >> v;
|
||||||
|
return {u,v};
|
||||||
|
}
|
||||||
|
|
||||||
|
FaceIndices ParseFaceIndicesFromOBJ(std::istringstream& stream) {
|
||||||
|
FaceIndices face{};
|
||||||
|
char slash;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
unsigned int vI;
|
||||||
|
unsigned int tCI;
|
||||||
|
|
||||||
|
stream >> vI >> slash >> tCI;
|
||||||
|
|
||||||
|
face.vertexIndex[i] = vI;
|
||||||
|
face.texCoordIndex[i] = tCI;
|
||||||
|
|
||||||
|
// Shift vertexindex by 1
|
||||||
|
face.vertexIndex[i]--;
|
||||||
|
// shift texcoordindex by 1
|
||||||
|
face.texCoordIndex[i]--;
|
||||||
|
}
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
void Model::loadOBJ(const std::string& filename) {
|
||||||
|
std::ifstream file(filename);
|
||||||
|
if (!file.is_open())
|
||||||
|
std::cerr << filename << " not found." << std::endl;
|
||||||
|
|
||||||
|
std::vector<Vector3> positions;
|
||||||
|
std::vector<Vector2> uvs;
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
// First: We read every (unique) vertex entry and textureCoord entry from the file.
|
||||||
|
// Then: Use Face data to map the bulk data into correct locations.
|
||||||
|
|
||||||
|
// TODO: Check the assumption that we can **always** read all "v", "vt" etc. tokens first,
|
||||||
|
// allowing us to perform a second-pass to reconstruct faces?
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
std::istringstream stream(line);
|
||||||
|
std::string prefix;
|
||||||
|
stream >> prefix;
|
||||||
|
|
||||||
|
|
||||||
|
if (prefix == "v") {
|
||||||
|
auto result = ParseVertexCoordinatesFromOBJ(stream);
|
||||||
|
positions.emplace_back(result);
|
||||||
|
} else if (prefix == "vt") {
|
||||||
|
auto result = ParseVertexTextureCoordinatesFromOBJ(stream);
|
||||||
|
uvs.emplace_back(result);
|
||||||
|
} else if (prefix == "f") {
|
||||||
|
auto result = ParseFaceIndicesFromOBJ(stream);
|
||||||
|
mapFaces(result, positions, uvs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
// map face of model to positions and texture coords
|
||||||
|
void Model::mapFaces(const FaceIndices& facedata, const std::vector<Vector3>& positions, const std::vector<Vector2>& uvs) {
|
||||||
|
TextureInformation tInfo{};
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
Vector3 vertex;
|
||||||
|
Vector2 textureCoordinate;
|
||||||
|
vertex = positions[facedata.vertexIndex[i]];
|
||||||
|
textureCoordinate = uvs[facedata.texCoordIndex[i]];
|
||||||
|
|
||||||
|
vertices.push_back(vertex);
|
||||||
|
tInfo.path = "default"; //Placeholder
|
||||||
|
tInfo.textureCoordinates.push_back(textureCoordinate);
|
||||||
|
indices.push_back(static_cast<unsigned int>(indices.size()));
|
||||||
|
}
|
||||||
|
textureInfo.push_back(tInfo);
|
||||||
|
}
|
@@ -53,3 +53,17 @@ Bone* Bone::getParent() {
|
|||||||
return this;
|
return this;
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint Bone::getDepth() {
|
||||||
|
if (isRootBone())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Bone* b = parent;
|
||||||
|
uint depth = 1;
|
||||||
|
while (b != nullptr && !b->isRootBone()) {
|
||||||
|
b = b->getParent();
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1,64 +1,8 @@
|
|||||||
#include <types/model.h>
|
#include <types/model.h>
|
||||||
|
|
||||||
struct FaceIndices {
|
|
||||||
unsigned int vertexIndex[3];
|
|
||||||
unsigned int texCoordIndex[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector3 ParseVertexCoordinatesFromOBJ(std::istringstream& stream) {
|
|
||||||
float x, y, z;
|
|
||||||
stream >> x >> y >> z;
|
|
||||||
return {x,y,z};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 ParseVertexTextureCoordinatesFromOBJ(std::istringstream& stream) {
|
|
||||||
float u, v;
|
|
||||||
stream >> u >> v;
|
|
||||||
return {u,v};
|
|
||||||
}
|
|
||||||
|
|
||||||
FaceIndices ParseFaceIndicesFromOBJ(std::istringstream& stream) {
|
|
||||||
FaceIndices face{};
|
|
||||||
char slash;
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
unsigned int vI;
|
|
||||||
unsigned int tCI;
|
|
||||||
|
|
||||||
stream >> vI >> slash >> tCI;
|
|
||||||
|
|
||||||
face.vertexIndex[i] = vI;
|
|
||||||
face.texCoordIndex[i] = tCI;
|
|
||||||
|
|
||||||
// Shift vertexindex by 1
|
|
||||||
face.vertexIndex[i]--;
|
|
||||||
// shift texcoordindex by 1
|
|
||||||
face.texCoordIndex[i]--;
|
|
||||||
}
|
|
||||||
return face;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// map face of model to positions and texture coords
|
|
||||||
void Model::mapfaces(const FaceIndices& facedata, const std::vector<Vector3>& positions, const std::vector<Vector2>& uvs) {
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
Vector3 vertex;
|
|
||||||
Vector2 textureCoordinate;
|
|
||||||
vertex = positions[facedata.vertexIndex[i]];
|
|
||||||
textureCoordinate = uvs[facedata.texCoordIndex[i]];
|
|
||||||
|
|
||||||
vertices.push_back(vertex);
|
|
||||||
textureCoor.push_back(textureCoordinate);
|
|
||||||
indices.push_back(static_cast<unsigned int>(indices.size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Model::load(const std::string& file, const ModelType& modelType) {
|
|
||||||
//TODO: Call correct func.
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::load(const std::string& file) {
|
void Model::load(const std::string& file) {
|
||||||
//TODO: Determine model type and call correct func.
|
if (file.ends_with(".obj"))
|
||||||
|
loadOBJ(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Vector3>& Model::getVertices() {
|
const std::vector<Vector3>& Model::getVertices() {
|
||||||
|
Reference in New Issue
Block a user