From 34f1f6293a041eeb59ce94f49563df6a5a9c23d5 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Wed, 12 Aug 2020 22:21:17 +0300 Subject: [PATCH] subcommit --- assimpModelReader.cpp | 74 ++++++++++ assimpModelReader.h | 21 +++ vbModelReader.cpp | 314 ++++++++++++++++++++++++++++++++++++++++++ vbModelReader.h | 30 ++++ 4 files changed, 439 insertions(+) create mode 100644 assimpModelReader.cpp create mode 100644 assimpModelReader.h create mode 100644 vbModelReader.cpp create mode 100644 vbModelReader.h diff --git a/assimpModelReader.cpp b/assimpModelReader.cpp new file mode 100644 index 0000000..2ac24eb --- /dev/null +++ b/assimpModelReader.cpp @@ -0,0 +1,74 @@ +#include"assimpModelReader.h" +#include"mesh.h" +#include +#include +#include + +using namespace std; +using namespace Assimp; + +namespace vb01{ + AssimpModelReader::AssimpModelReader(Model *model, string path) : ModelReader(model, path){ + 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:"<mRootNode, scene, this); + } + + void AssimpModelReader::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 AssimpModelReader::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)); + } +} diff --git a/assimpModelReader.h b/assimpModelReader.h new file mode 100644 index 0000000..bcf380e --- /dev/null +++ b/assimpModelReader.h @@ -0,0 +1,21 @@ +#ifndef ASSIMP_MODEL_READER_H +#define ASSIMP_MODEL_READER_H + +#include"modelReader.h" + +class aiNode; +class aiMesh; +class aiScene; + +namespace vb01{ + class AssimpModelReader : public ModelReader{ + public: + AssimpModelReader(Model*, std::string); + private: + void processNode(aiNode*, const aiScene*, Node*); + void processMesh(aiMesh*, const aiScene*, Node*); + void processMaterial(); + }; +} + +#endif diff --git a/vbModelReader.cpp b/vbModelReader.cpp new file mode 100644 index 0000000..cbb1272 --- /dev/null +++ b/vbModelReader.cpp @@ -0,0 +1,314 @@ +#include"vbModelReader.h" +#include"util.h" +#include"vector.h" +#include"mesh.h" +#include"skeleton.h" +#include"bone.h" +#include"model.h" +#include"animation.h" + +#include +#include + +using namespace std; + +namespace vb01{ + VbModelReader::VbModelReader(Model *model, string path) : ModelReader(model, path){ + this->path = path; + this->model = model; + + const string meshType = "MESH", skeletonType = "ARMATURE", lightType = "LIGHT"; + vector meshBracketIds, skeletonBracketIds, lightBracketIds; + int curBracketId = -1, lineIndex = 0; + string line, type; + ifstream file(path); + + while(getline(file, line)){ + if(line[0] == '{' || line[0] == '}'){ + curBracketId = lineIndex; + if(line[0] == '{'){ + getline(file, line); + lineIndex++; + + int colonId = getCharId(line, ':'); + type = line.substr(0, colonId); + } + if(type == meshType) + meshBracketIds.push_back(curBracketId); + else if(type == skeletonType) + skeletonBracketIds.push_back(curBracketId); + else if(type == lightType) + lightBracketIds.push_back(curBracketId); + } + lineIndex++; + } + + file.close(); + + for(int i = 0; i < skeletonBracketIds.size() / 2; i++) + readSkeletons(skeletonBracketIds[i * 2], skeletonBracketIds[i * 2 + 1]); + for(int i = 0; i < meshBracketIds.size() / 2; i++) + readMeshes(meshBracketIds[i * 2], meshBracketIds[i * 2 + 1]); + for(int i = 0; i < lightBracketIds.size() / 2; i++) + readLights(lightBracketIds[i * 2], lightBracketIds[i * 2 + 1]); + + for(string line : relationships){ + Node *child = nullptr, *parent = nullptr; + int spaceId = getCharId(line, ' '); + string childName = line.substr(0, spaceId), parentName = line.substr(spaceId + 1, string::npos); + for(Node *node : nodes){ + if(node->getName() == childName) + child = node; + else if(node->getName() == parentName) + parent = node; + } + if(parent) + parent->attachChild(child); + } + for(Node *node : nodes) + if(!node->getParent()) + model->attachChild(node); + } + + VbModelReader::~VbModelReader(){ + } + + void VbModelReader::readSkeletons(int startLine, int endLine){ + vector meshData; + readFile(path, meshData, startLine + 1, startLine + 7); + string line = meshData[5]; + string name = meshData[0].substr(getCharId(meshData[0], ':') + 2, string::npos); + 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 animationStartLine = boneStartLine + numBones + 1; + + Skeleton *skeleton = new Skeleton(name); + skeletons.push_back(skeleton); + + meshData.clear(); + readFile(path, meshData, boneStartLine, boneStartLine + numBones); + for(string line : meshData){ + int colonId = getCharId(line, ':'); + string preColon = line.substr(0, colonId); + string postColon = line.substr(colonId + 2, string::npos); + + 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 = model; + 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); + } + + string animName = ""; + Bone *animBone = nullptr; + Animation::KeyframeGroup::Keyframe::Type type; + meshData.clear(); + readFile(path, meshData, animationStartLine, endLine + 1); + for(string l : meshData){ + int colonId = getCharId(l, ':'); + string preColon = l.substr(0, colonId); + if(preColon == "animationName"){ + string postColon = l.substr(colonId + 2, string::npos); + 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); + } + } + else{ + Animation::KeyframeGroup::Keyframe::Interpolation interp; + if(l == "}") + break; + else 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{ + 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); + } + } + } + } + + void VbModelReader::readMeshes(int startLine, int endLine){ + vector meshData; + readFile(path, meshData, startLine + 1, startLine + 8); + + string nameLine = meshData[0], parentLine = meshData[4], skeletonLine = meshData[5], numElementsLine = meshData[6]; + + int skeletonLineColonId = getCharId(skeletonLine, ':'); + string skeletonName = skeletonLine.substr(skeletonLineColonId + 2, string::npos); + + int parentLineColonId = getCharId(parentLine, ':'); + string parent = parentLine.substr(parentLineColonId + 2, string::npos); + + int nameLineColonId = getCharId(nameLine, ':'); + string preColonNameLine = nameLine.substr(0, nameLineColonId); + string postColonNameLine = nameLine.substr(nameLineColonId + 2, string::npos); + + int numElementsColonId = getCharId(numElementsLine, ':'); + string numElementsPreColon = numElementsLine.substr(0, numElementsColonId); + string numElementsPostColon = numElementsLine.substr(numElementsColonId + 2, string::npos); + + string data[4]; + getLineData(numElementsPostColon, data, 4); + string name = postColonNameLine; + + relationships.push_back(postColonNameLine + " " + parent); + + const int numVertsPerFace = 3; + int numVertices = atoi(data[0].c_str()); + int numFaces = atoi(data[1].c_str()); + int numBones = atoi(data[2].c_str()); + int numShapes = atoi(data[3].c_str()); + int vertexGroupStartLine = startLine + 9; + int vertexStartLine = vertexGroupStartLine + numBones + 1; + int faceStartLine = vertexStartLine + numVertices + 1; + int shapeKeyStartLine = faceStartLine + numFaces + 1; + + vector vertPos, vertNorm; + vector vertWeights; + Mesh::Vertex *vertices = new Mesh::Vertex[numFaces * numVertsPerFace]; + u32 *indices = new u32[numFaces * numVertsPerFace]; + string *groups = new string[numBones]; + + meshData.clear(); + readFile(path, meshData, vertexGroupStartLine, vertexGroupStartLine + numBones); + groups = new string[numBones]; + for(int i = 0; i < numBones; i++){ + groups[i] = meshData[i]; + } + + meshData.clear(); + readFile(path, meshData, vertexStartLine, vertexStartLine + numVertices); + for(string line : meshData){ + int numData = 6 + numBones; + string data[numData]; + getLineData(line, 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())); + } + + meshData.clear(); + readFile(path, meshData, faceStartLine, faceStartLine + numFaces); + int i = 0; + for(string line : meshData){ + int numData = 9; + string data[numData]; + getLineData(line,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++; + } + } + + vertices[i * numVertsPerFace] = vert; + indices[i * numVertsPerFace] = i * numVertsPerFace; + for(int j = 0; j < numVertsPerFace; j++){ + } + + i++; + } + + meshData.clear(); + + readFile(path, meshData, shapeKeyStartLine, shapeKeyStartLine + numShapes); + for(int i = 0; i < numShapes; i++){ + } + + Skeleton *skeleton = nullptr; + for(Skeleton *sk : skeletons) + if(sk->getName() == skeletonName) + skeleton = sk; + + Mesh *mesh = new Mesh(vertices, indices, numFaces, groups, numBones, nullptr, numShapes, name); + mesh->setSkeleton(skeleton); + + Node *node = new Node(Vector3::VEC_ZERO, Quaternion::QUAT_W, Vector3::VEC_IJK, name); + node->attachMesh(mesh); + nodes.push_back(node); + } + + void VbModelReader::readLights(int startLine, int endLine){ + + } +} diff --git a/vbModelReader.h b/vbModelReader.h new file mode 100644 index 0000000..0061e11 --- /dev/null +++ b/vbModelReader.h @@ -0,0 +1,30 @@ +#ifndef MODEL_READER +#define MODEL_READER + +#include +#include"modelReader.h" + +namespace vb01{ + class Model; + class Mesh; + class Skeleton; + + class VbModelReader : public ModelReader{ + public: + VbModelReader(Model*, std::string); + ~VbModelReader(); + private: + void readSkeletons(int, int); + void readMeshes(int, int); + void readLights(int, int); + + std::string path; + std::vector relationships; + std::vector skeletons; + std::vector meshes; + std::vector nodes; + }; +} + +#endif +