readable models via the new reader (verts, faces, bones...)

This commit is contained in:
devZoGok
2021-10-19 19:06:41 +03:00
parent 34f1f6293a
commit dba02e7944
13 changed files with 62 additions and 460 deletions
+2 -1
View File
@@ -14,10 +14,11 @@ set(gui text.cpp rectangle.cpp)
set(utils util.cpp)
set(math quaternion.cpp vector.cpp matrix.cpp ray.cpp)
set(render waterPlane.cpp particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp)
set(model modelReader.cpp assimpModelReader.cpp vbModelReader.cpp)
set(anim animationChannel.cpp animation.cpp)
set(armature skeleton.cpp bone.cpp)
add_library(vb01 SHARED main.cpp ${render} ${math} ${utils} ${gui} ${armature} ${anim})
add_library(vb01 SHARED main.cpp ${render} ${math} ${model} ${utils} ${gui} ${armature} ${anim})
target_link_libraries(vb01 glfw)
target_link_libraries(vb01 glad)
target_link_libraries(vb01 assimp)
+2
View File
@@ -175,6 +175,8 @@ namespace vb01{
shader->setMat4(model,"model");
if(skeleton){
skeleton->update();
shader->editShader(Shader::VERTEX_SHADER,2,"const int numBones="+to_string(skeleton->getNumBones())+";");
shader->editShader(Shader::VERTEX_SHADER,3,"const int numVertGroups="+to_string(numVertexGroups)+";");
+10 -175
View File
@@ -7,6 +7,8 @@
#include"root.h"
#include"skeleton.h"
#include"animation.h"
#include"vbModelReader.h"
#include"assimpModelReader.h"
#include<vector>
#include<Importer.hpp>
@@ -18,181 +20,14 @@ using namespace std;
using namespace Assimp;
namespace vb01{
void Model::processNode(aiNode *node, const aiScene *scene, Node *currentNode){
for(int i=0;i<node->mNumMeshes;i++){
aiMesh *mesh=scene->mMeshes[node->mMeshes[i]];
processMesh(mesh,scene,currentNode);
}
for(int i=0;i<node->mNumChildren;i++){
Node *childNode=new Node();
currentNode->attachChild(childNode);
processNode(node->mChildren[i],scene,childNode);
}
}
void Model::processMesh(aiMesh *mesh, const aiScene *scene, Node *currentNode){
const int numTris=mesh->mNumFaces;
Mesh::Vertex *vertices=new Mesh::Vertex[3*numTris];
u32 *indices=new u32[3*numTris];
for(int i=0;i<3*numTris;i++){
Mesh::Vertex v;
v.pos.x=mesh->mVertices[i].x;
v.pos.y=mesh->mVertices[i].y;
v.pos.z=mesh->mVertices[i].z;
v.norm.x=mesh->mNormals[i].x;
v.norm.y=mesh->mNormals[i].y;
v.norm.z=mesh->mNormals[i].z;
v.tan.x=mesh->mTangents[i].x;
v.tan.y=mesh->mTangents[i].y;
v.tan.z=mesh->mTangents[i].z;
v.biTan.x=mesh->mBitangents[i].x;
v.biTan.y=mesh->mBitangents[i].y;
v.biTan.z=mesh->mBitangents[i].z;
if(mesh->mTextureCoords[0]){
v.uv.x=mesh->mTextureCoords[0][i].x;
v.uv.y=mesh->mTextureCoords[0][i].y;
}
else
v.uv=Vector2::VEC_ZERO;
vertices[i]=v;
}
for(int i=0;i<numTris;i++){
int numFaceIndices=mesh->mFaces[i].mNumIndices;
for(int j=0;j<numFaceIndices;j++){
indices[numFaceIndices*i+j]=mesh->mFaces[i].mIndices[j];
}
}
//if(mesh->mMaterialIndex>=0){
// aiMaterial *material=scene->mMaterial[mesh->mMaterialIndex];
//}
currentNode->attachMesh(new Mesh(vertices,indices,numTris));
}
Model::Model(string path,bool b) : Node(){
Node *rootNode=Root::getSingleton()->getRootNode();
if(b){
Importer importer;
const aiScene *scene=importer.ReadFile(path,aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals | aiProcess_CalcTangentSpace);
if(!scene||scene->mFlags&AI_SCENE_FLAGS_INCOMPLETE||!scene->mRootNode){
cout<<"Failed to load model:"<<importer.GetErrorString()<<endl;
exit(-1);
}
processNode(scene->mRootNode,scene,this);
}
else{
enum Stage{ARMATURE,MESH};
Stage stage;
ifstream in(path);
string l,name="";
Vector3 localPos=Vector3::VEC_ZERO,localScale=Vector3::VEC_IJK;
Quaternion localRot=Quaternion::QUAT_W;
vector<string> childrenChain;
vector<Skeleton*> skeletons;
vector<Mesh*> meshes;
vector<Light*> lights;
vector<Node*> nodes;
Skeleton *skeleton=nullptr;
string animName="";
Bone *animBone=nullptr;
const int numVertsPerFace=3;
int numFaces=0,vertId=0,faceId=0,groupId=0,groupVertId=0,numGroups=0,numShapeKeys=0,numBones=0;
Mesh::Vertex *vertices;
u32 *indices;
vector<Vector3> vertPos,vertNorm;
vector<float> vertWeights;
string *groups=nullptr,*shapeKeys=nullptr;
while(getline(in,l)){
int colonId=-1;
for(int i=0;i<l.length();i++)
if(l[i]==':'){
colonId=i;
break;
}
string preColon=l.substr(0,colonId);
string postColon=l.length()==colonId+1?"":l.substr(colonId+2,string::npos);
if(preColon=="ARMATURE"){
stage=ARMATURE;
skeleton=new Skeleton(postColon);
name=postColon;
continue;
}
else if(preColon=="MESH"){
stage=MESH;
name=postColon;
continue;
}
else if(preColon=="pos"){
continue;
}
else if(preColon=="rot"){
continue;
}
else if(preColon=="scale"){
continue;
}
else if(preColon=="parent"){
childrenChain.push_back(name+" "+postColon);
continue;
}
}
for(Mesh *mesh : meshes){
Node *meshNode=new Node(localPos,localRot,localScale);
meshNode->attachMesh(mesh);
nodes.push_back(meshNode);
for(string line : childrenChain){
int spaceId=-1;
for(int i=0;i<line.length();i++)
if(line[i]==' ')
spaceId=i;
string childName=line.substr(0,spaceId),parentName=line.substr(spaceId+1,string::npos);
if(mesh->getName()==childName){
for(Skeleton *sk : skeletons){
if(sk->getName()==parentName)
mesh->setSkeleton(sk);
}
}
}
}
for(Light *light : lights){
Node *lightNode=new Node(localPos,localRot,localScale);
lightNode->addLight(light);
nodes.push_back(lightNode);
}
for(string line : childrenChain){
int spaceId=-1;
for(int i=0;i<line.length();i++)
if(line[i]==' ')
spaceId=i;
string childName=line.substr(0,spaceId),parentName=line.substr(spaceId+1,string::npos);
Node *childNode=nullptr,*parentNode=this;
for(int i=0;i<nodes.size();i++){
Mesh *m0=nodes[i]->getMesh(0);
Skeleton *sk0=m0->getSkeleton();
if(m0->getName()==childName||(sk0&&sk0->getName()==childName)){
childNode=nodes[i];
for(int j=0;j<nodes.size();j++){
Mesh *m1=nodes[j]->getMesh(0);
Skeleton *sk1=m1->getSkeleton();
if(m1->getName()==parentName||(sk1&&sk1->getName()==parentName))
parentNode=nodes[j];
}
}
}
if(childNode!=parentNode)
parentNode->attachChild(childNode);
}
}
Model::Model(string path) : Node(){
int dotId = getCharId(path, '.', true);
string extension = path.substr(dotId + 1, string::npos);
ModelReader *modelReader = nullptr;
if(extension == "vb")
modelReader = new VbModelReader(this, path);
else
modelReader = new AssimpModelReader(this, path);
}
Model::~Model(){
+1 -6
View File
@@ -17,7 +17,7 @@ namespace vb01{
class Model : public Node{
public:
Model(std::string,bool=true);
Model(std::string);
~Model();
void update();
void setMaterial(Material*);
@@ -25,11 +25,6 @@ namespace vb01{
void setReflect(bool);
void setWireframe(bool);
private:
void processNode(aiNode*, const aiScene*, Node*);
void processMesh(aiMesh*, const aiScene*, Node*);
// std::vector<Texture*> processTexture(aiMaterial*, Assimp::aiTextureType);
void processMaterial();
Material* material;
bool castShadow=false,reflect=false,wireframe=false;
};
+3 -252
View File
@@ -1,265 +1,16 @@
#include"modelReader.h"
#include"model.h"
#include<vector>
#include<fstream>
using namespace std;
namespace vb01{
ModelReader::ModelReader(string path){
ModelReader::ModelReader(Model *model, string path){
this->model = model;
this->path = path;
const string meshType = "MESH", skeletonType = "ARMATURE", lightType = "LIGHT";
vector<int> meshBracketIds, skeletonBracketIds, lightBracketIds;
int curBracketId = -1;
string line;
ifstream file(path);
for(int i = 0; getline(file, line); i++){
if(line[0] == '{' || line[0] == '}')
curBracketId = i;
else{
int colonId = getCharId(':');
string type = line.substr(0, colonId - 1);
if(type == meshType)
meshBracketIds.push_back(curBracketId);
else if(type == skeletonType)
skeletonBracketIds.push_back(curBracketId);
else if(type == lightType)
lightBracketIds.push_back(curBracketId);
}
}
file.close();
for(int i = 0; i < meshBracketIds.size() / 2; i++)
readMeshes(meshBracketIds[i * 2], meshBracketIds[i * 2 + 1]);
for(int i = 0; i < skeletonBracketIds.size() / 2; i++)
readSkeletons(skeletonBracketIds[i * 2], skeletonBracketIds[i * 2 + 1]);
for(int i = 0; i < lightBracketIds.size() / 2; i++)
readLights(lightBracketIds[i * 2], lightBracketIds[i * 2 + 1]);
}
ModelReader::~ModelReader(){
}
void ModelReader::readSkeletons(int startLine, int endLine){
/*
if(stage==ARMATURE){
enum ArmatureStage{BONES,ANIMATIONS};
ArmatureStage armatureStage;
if(preColon=="bones"){
numBones=atoi(postColon.c_str());
armatureStage=BONES;
continue;
}
else if(preColon=="animations"){
armatureStage=ANIMATIONS;
continue;
}
switch(armatureStage){
case BONES:
{
int numData=11;
string data[numData];
getLineData(postColon,data,numData);
float length = atof(data[1].c_str());
Vector3 head=Vector3(atof(data[2].c_str()),atof(data[3].c_str()),atof(data[4].c_str()));
Vector3 xAxis=Vector3(atof(data[5].c_str()),atof(data[6].c_str()),atof(data[7].c_str()));
Vector3 yAxis=Vector3(atof(data[8].c_str()),atof(data[9].c_str()),atof(data[10].c_str()));
Vector3 zAxis=xAxis.cross(yAxis);
Vector3 pos = head;
string parName=string(data[0].c_str());
Node *parent=skeleton->getBone(parName);
if(!parent){
parent=this;
swap(xAxis.y,xAxis.z);
xAxis.z=-xAxis.z;
swap(yAxis.y,yAxis.z);
yAxis.z=-yAxis.z;
swap(zAxis.y,zAxis.z);
zAxis.z=-zAxis.z;
}
else
pos = pos + Vector3(0,((Bone*)parent)->getLength(),0);
Bone *bone=new Bone(preColon,length,pos);
skeleton->addBone(bone,(Bone*)parent);
bone->lookAt(zAxis,yAxis,parent);
break;
}
case ANIMATIONS:
{
if(preColon=="animationName"){
animName=postColon;
skeleton->addAnimation(new Animation(animName));
continue;
}
Bone *b=skeleton->getBone(preColon);
if(b){
animBone=b;
Animation *anim=skeleton->getAnimation(animName);
Animation::KeyframeGroup *group=anim->getKeyframeGroup(animBone);
if(!group){
Animation::KeyframeGroup kg;
kg.bone=animBone;
anim->addKeyframeGroup(kg);
}
continue;
}
else{
Animation::KeyframeGroup::Keyframe::Type type;
Animation::KeyframeGroup::Keyframe::Interpolation interp;
if(preColon=="pos_x")
type=Animation::KeyframeGroup::Keyframe::Type::POS_X;
else if(preColon=="pos_y")
type=Animation::KeyframeGroup::Keyframe::Type::POS_Y;
else if(preColon=="pos_z")
type=Animation::KeyframeGroup::Keyframe::Type::POS_Z;
else if(preColon=="rot_w")
type=Animation::KeyframeGroup::Keyframe::Type::ROT_W;
else if(preColon=="rot_x")
type=Animation::KeyframeGroup::Keyframe::Type::ROT_X;
else if(preColon=="rot_y")
type=Animation::KeyframeGroup::Keyframe::Type::ROT_Y;
else if(preColon=="rot_z")
type=Animation::KeyframeGroup::Keyframe::Type::ROT_Z;
else if(l==""){
skeletons.push_back(skeleton);
break;
}
else{
int numData=3;
string data[numData];
getLineData(l,data,numData);
float value=atof(data[0].c_str()),frame=atoi(data[1].c_str());
interp=(Animation::KeyframeGroup::Keyframe::Interpolation)atoi(data[2].c_str());
Animation::KeyframeGroup::Keyframe keyframe;
keyframe.type=type;
keyframe.interpolation=interp;
keyframe.value=value;
keyframe.frame=frame;
skeleton->getAnimation(animName)->getKeyframeGroup(animBone)->keyframes.push_back(keyframe);
}
}
break;
}
}
}
*/
}
void ModelReader::readMeshes(int startLine, int endLine){
vector<string> meshData;
readFile(path, meshData, startLine - 4, endLine - 1);
for(String line : meshData){
int colonId = getCharId(':');
string preColonSubstring = line.substr(0, colonId - 1);
string postColonSubstring = line.substr(colonId + 1, string::npos);
}
numFaces=atoi(data[1].c_str());
numGroups=atoi(data[2].c_str());
vertices=new Mesh::Vertex[numFaces*numVertsPerFace];
indices=new u32[numFaces*numVertsPerFace];
if(preColon=="vertices"){
const int numData=4;
string data[numData];
getLineData(postColon,data,numData);
meshStage=VERTICES;
continue;
}
else if(preColon=="faces"){
meshStage=FACES;
continue;
}
else if(preColon=="groups"){
groups=new string[numGroups];
meshStage=GROUPS;
continue;
}
else if(preColon=="shapeKeys"){
meshStage=SHAPE_KEYS;
continue;
}
switch(meshStage){
{
case VERTICES:
int numData = 6 + numBones;
string data[numData];
getLineData(l,data,numData);
Vector3 vPos=Vector3(atof(data[0].c_str()),atof(data[2].c_str()),-atof(data[1].c_str()));
Vector3 vNorm=Vector3(atof(data[3].c_str()),atof(data[5].c_str()),-atof(data[4].c_str()));
vertPos.push_back(vPos);
vertNorm.push_back(vNorm);
for(int j=0;j<numBones;j++)
vertWeights.push_back(atof(data[6 + j].c_str()));
break;
}
{
case FACES:
int numData=9;
string data[numData];
getLineData(l,data,numData);
int index=atoi(data[0].c_str());
Vector2 uv=Vector2(atof(data[1].c_str()),atof(data[2].c_str()));
Vector3 tan=Vector3(atof(data[3].c_str()),atof(data[5].c_str()),-atof(data[4].c_str()));
Vector3 biTan=Vector3(atof(data[6].c_str()),atof(data[8].c_str()),-atof(data[7].c_str()));
Mesh::Vertex vert;
vert.pos=vertPos[index];
vert.norm=vertNorm[index];
vert.tan=tan;
vert.biTan=biTan;
vert.uv=uv;
for(int j = 0, boneIndex = 0; j < numBones; j++){
if(vertWeights[index * numBones + j] > 0){
vert.boneIndices[boneIndex] = j;
vert.weights[boneIndex] = vertWeights[index * numBones + j];
boneIndex++;
}
}
indices[vertId]=vertId;
vertices[vertId]=vert;
vertId++;
break;
}
{
case GROUPS:
if(l==""){
meshes.push_back(new Mesh(vertices,indices,numFaces,groups,numGroups,shapeKeys,numShapeKeys,name));
break;
}
else{
groups[groupId]=l;
groupId++;
}
break;
}
{
case SHAPE_KEYS:
if(l==""){
meshes.push_back(new Mesh(vertices,indices,numFaces,groups,numGroups,shapeKeys,numShapeKeys,name));
break;
}
break;
}
}
}
void ModelReader::readLights(int startLine, int endLine){
}
}
+4 -6
View File
@@ -2,17 +2,15 @@
#define MODEL_READER
#include<string>
#include"model.h"
namespace vb01{
class ModelReader{
public:
ModelReader(std::string);
protected:
ModelReader(Model*, std::string);
~ModelReader();
private:
void readSkeletons(int, int);
void readMeshes(int, int);
void readLights(int, int);
Model *model = nullptr;
std::string path;
};
}
+9 -3
View File
@@ -1,14 +1,20 @@
import sys
def exportData(ob):
par=ob.parent
par = ob.parent
if(par is not None and par.type == 'ARMATURE'):
while(par is not None):
par = par.parent
file.write('{\n' + ob.type+": "+ob.name+"\n")
file.write("pos: "+str(ob.location.x)+" "+str(ob.location.y)+" "+str(ob.location.z)+"\n")
file.write("rot: "+str(ob.rotation_quaternion.w)+" "+str(ob.rotation_quaternion.x)+" "+str(ob.rotation_quaternion.y)+" "+str(-ob.rotation_quaternion.z)+"\n")
file.write("scale: "+str(ob.scale.x)+" "+str(ob.scale.y)+" "+str(ob.scale.z)+"\n")
file.write("parent: "+('-' if par is None else par.name)+"\n")
if(ob.type=="ARMATURE"):
file.write("bones: "+str(len(ob.data.bones)))
numAnims=len(ob.animation_data.nla_tracks[0].strips)
file.write("bones: "+str(len(ob.data.bones)) + ' ' + str(numAnims) + ' ')
for bone in ob.data.bones:
head=bone.head
tail=bone.tail
@@ -16,7 +22,6 @@ def exportData(ob):
yAxis=bone.y_axis
file.write("\n"+bone.name+": "+('None' if bone.parent is None else bone.parent.name)+" "+str(bone.length)+" "+str(head.x)+" "+str(head.y)+" "+str(head.z)+" "+str(xAxis.x)+" "+str(xAxis.y)+" "+str(xAxis.z)+" "+str(yAxis.x)+" "+str(yAxis.y)+" "+str(yAxis.z)+" ")
numAnims=len(ob.animation_data.nla_tracks[0].strips)
if numAnims>0:
file.write("\nanimations: "+str(numAnims))
for nlaStrip in ob.animation_data.nla_tracks[0].strips:
@@ -80,6 +85,7 @@ def exportData(ob):
file.write(str(keyframe.handle_right_type)+" "+str(keyframe.handle_right.x)+" "+str(keyframe.handle_right.y))
file.write("\n")
elif(ob.type=="MESH"):
file.write('skeleton: ' + ob.modifiers['Armature'].object.name + '\n')
mesh=ob.data
numFaces=len(mesh.polygons)
+3
View File
@@ -9,6 +9,9 @@ namespace vb01{
this->name=name;
}
void Skeleton::update(){
}
void Skeleton::addBone(Bone *bone, Bone *parent){
parent->attachChild(bone);
bone->setSkeleton(this);
+1
View File
@@ -11,6 +11,7 @@ namespace vb01{
class Skeleton{
public:
Skeleton(std::string="");
void update();
void addBone(Bone*,Bone*);
Bone* getBone(std::string);
Animation* getAnimation(std::string);
+16 -5
View File
@@ -34,13 +34,24 @@ namespace vb01{
}
}
int getCharId(char ch){
int getCharId(string line, char ch, bool reverse){
int charId = -1;
for(int i = 0; i < line.length(); i++)
if(line[i] == ch){
colonId = i;
break;
if(!reverse){
for(int i = 0; i < line.length(); i++){
if(line[i] == ch){
charId = i;
break;
}
}
}
else{
for(int i = line.length() - 1; i >= 0; i--){
if(line[i] == ch){
charId = i;
break;
}
}
}
return charId;
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ namespace vb01{
void readFile(std::string, std::vector<std::string>&, int = 0, int = -1);
void getLineData(std::string&, std::string[], int, int = 0);
int getCharId(char);
int getCharId(std::string, char, bool = false);
inline s64 getTime(){return s64(std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1));}
}
+5 -7
View File
@@ -76,14 +76,14 @@ namespace vb01{
void VbModelReader::readSkeletons(int startLine, int endLine){
vector<string> meshData;
readFile(path, meshData, startLine + 1, startLine + 7);
string line = meshData[5];
string name = meshData[0].substr(getCharId(meshData[0], ':') + 2, string::npos);
string line = meshData[5];
string data[3];
getLineData(line, data, 3);
int numBones = atoi(data[1].c_str());
int numAnimations = atoi(data[2].c_str());
int boneStartLine = startLine + 8;
int boneStartLine = startLine + 7;
int animationStartLine = boneStartLine + numBones + 1;
Skeleton *skeleton = new Skeleton(name);
@@ -254,7 +254,7 @@ namespace vb01{
}
meshData.clear();
readFile(path, meshData, faceStartLine, faceStartLine + numFaces);
readFile(path, meshData, faceStartLine, faceStartLine + numFaces * numVertsPerFace);
int i = 0;
for(string line : meshData){
int numData = 9;
@@ -281,10 +281,8 @@ namespace vb01{
}
}
vertices[i * numVertsPerFace] = vert;
indices[i * numVertsPerFace] = i * numVertsPerFace;
for(int j = 0; j < numVertsPerFace; j++){
}
vertices[i] = vert;
indices[i] = i;
i++;
}
+5 -4
View File
@@ -1,11 +1,13 @@
#ifndef MODEL_READER
#define MODEL_READER
#ifndef VB_MODEL_READER
#define VB_MODEL_READER
#include<string>
#include"modelReader.h"
#include<string>
#include<vector>
namespace vb01{
class Model;
class Node;
class Mesh;
class Skeleton;
@@ -18,7 +20,6 @@ namespace vb01{
void readMeshes(int, int);
void readLights(int, int);
std::string path;
std::vector<std::string> relationships;
std::vector<Skeleton*> skeletons;
std::vector<Mesh*> meshes;