I think that I have everything here. This is for OpenFrameWorks because the ofxAssimp module conflicts with the python interpreter.
#pragma once
#include <vector>
#include <string>
#include <ofMain.h>
#include "assimp/scene.h"
#include "assimp/postprocess.h"
using namespace std;
class Bone
{
public:
Bone();
void setMatrix(const aiMatrix4x4& from);
void setTrans(const aiMatrix4x4& from);
vector<unsigned int> induces;
vector<float> weights;
string name;
string meshName;
glm::mat4 offsetMat;
glm::mat4 transform;
int refNum;
vector<Bone> children;
private:
glm::mat4 Assimp2Glm(const aiMatrix4x4& from);
aiMatrix4x4 Glm2Assimp(const glm::mat4& from);
};
#include "Bone.h"
Bone::Bone() {
name = "";
refNum = 0;
offsetMat = glm::mat4(1.0);
}
void Bone::setMatrix(const aiMatrix4x4& from) {
offsetMat = Assimp2Glm(from);
}
void Bone::setTrans(const aiMatrix4x4& from) {
transform = Assimp2Glm(from);
}
glm::mat4 Bone::Assimp2Glm(const aiMatrix4x4& from)
{
return glm::mat4(
(double)from.a1, (double)from.b1, (double)from.c1, (double)from.d1,
(double)from.a2, (double)from.b2, (double)from.c2, (double)from.d2,
(double)from.a3, (double)from.b3, (double)from.c3, (double)from.d3,
(double)from.a4, (double)from.b4, (double)from.c4, (double)from.d4
);
}
aiMatrix4x4 Bone::Glm2Assimp(const glm::mat4& from)
{
return aiMatrix4x4(from[0][0], from[1][0], from[2][0], from[3][0],
from[0][1], from[1][1], from[2][1], from[3][1],
from[0][2], from[1][2], from[2][2], from[3][2],
from[0][3], from[1][3], from[2][3], from[3][3]
);
}
#pragma once
#include <vector>
#include "ofMain.h"
#include "assimp/scene.h"
#include "Bone.h"
#include "Texture2D.h"
class MeshObj
{
public:
ofMesh mySelf;
ofTexture diffuse;
glm::vec4 diff;
ofTexture normal;
ofTexture roughness;
float rough;
ofTexture metalic;
float metal;
bool hasdif;
bool hasnorm;
bool hasrough;
bool hasMetal;
string name;
private:
};
#pragma once
#include <vector>
#include "assimp/Importer.hpp"
#include "assimp/scene.h"
#include "assimp/postprocess.h"
#include "ofMain.h"
#include "MeshObj.h"
#include "Texture2D.h"
#pragma comment(lib, "assimp.lib")
struct Vertex {
glm::vec3 pos;
glm::vec3 norm;
glm::vec2 tex;
};
class MeshHolder
{
public:
MeshHolder();
void loadmodel(string path);
glm::vec3 pos;
glm::vec3 size;
vector<MeshObj> meshes;
string errorType;
bool error;
Bone skeleton;
vector<Bone> astruct;
aiMatrix4x4 GlobalInverseTransform;
private:
void processNode(aiNode* node, const aiScene* scene);
void processMesh(aiNode* anode, aiMesh* mesh, const aiScene* scene);
vector<ofTexture> processTextures(aiMaterial* mat, aiTextureType type);
bool readSkeleton(Bone& boneOut, aiNode* node, vector<Bone>& structureRef);
ofTexture loadTexture(string path);
string directory;
};
#include "MeshHolder.h"
MeshHolder::MeshHolder() {
}
void MeshHolder::loadmodel(string path) {
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
errorType = importer.GetErrorString();
error = true;
return;
}
error = false;
directory = path.substr(0, path.find_last_of("/"));
GlobalInverseTransform = scene->mRootNode->mTransformation;
GlobalInverseTransform.Inverse();
for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[i];
for (unsigned int j = 0; j < mesh->mNumBones; j++) {
Bone temp;
temp.name = mesh->mBones[j]->mName.C_Str();
temp.meshName = mesh->mName.C_Str();
temp.setMatrix(mesh->mBones[j]->mOffsetMatrix);
temp.induces.clear();
temp.weights.clear();
for (unsigned int k = 0; k < mesh->mBones[j]->mNumWeights; k++) {
aiVertexWeight vw = mesh->mBones[j]->mWeights[k];
temp.induces.push_back(vw.mVertexId);
temp.weights.push_back(vw.mWeight);
}
astruct.push_back(temp);
}
}
processNode(scene->mRootNode, scene);
aiMesh* parMesh = scene->mMeshes[0];
readSkeleton(skeleton, scene->mRootNode, astruct);
}
bool MeshHolder::readSkeleton(Bone& boneOut, aiNode* node, vector<Bone>& structureRef) {
bool found = false;
int idx;
for (int i = 0; i < structureRef.size(); i++) {
if (node->mName.C_Str() == structureRef.at(i).name) {
found = true;
idx = i;
break;
}
}
if (found) {
boneOut = structureRef.at(idx);
for (int i = 0; i < node->mNumChildren; i++) {
Bone child;
child.setTrans(node->mTransformation);
readSkeleton(child, node->mChildren[i], structureRef);
boneOut.children.push_back(child);
}
return true;
}
else {
for (int i = 0; i < node->mNumChildren; i++) {
if (readSkeleton(boneOut, node->mChildren[i], structureRef)) {
return true;
}
}
}
return false;
}
void MeshHolder::processNode(aiNode* node, const aiScene* scene) {
for (int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
processMesh(node, mesh, scene);
}
for (int i = 0; i < node->mNumChildren; i++) {
processNode(node->mChildren[i], scene);
}
aiMatrix4x4 transform = node->mTransformation;
}
void MeshHolder::processMesh(aiNode* anode, aiMesh* mesh, const aiScene* scene) {
static int meshNum = 0;
vector<Vertex> vertices;
vector<unsigned int> induces;
vector<ofTexture> textures;
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vertex vert;
vert.pos = glm::vec3(
mesh->mVertices[i].x,
mesh->mVertices[i].y,
mesh->mVertices[i].z);
vert.norm = glm::vec3(
mesh->mNormals[i].x,
mesh->mNormals[i].y,
mesh->mNormals[i].z);
if (mesh->mTextureCoords[0]) {
vert.tex = glm::vec2(
mesh->mTextureCoords[0][i].x,
mesh->mTextureCoords[0][i].y
);
}else{
vert.tex = glm::vec2(0, 0);
}
vertices.push_back(vert);
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
for (unsigned int j = 0; j < 3; j++) {
induces.push_back(face.mIndices[j]);
}
}
MeshObj mymesh;
if (mesh->mMaterialIndex >= 0) {
aiMaterial* maters = scene->mMaterials[mesh->mMaterialIndex];
vector<ofTexture> diffuseMaps = processTextures(maters, aiTextureType_DIFFUSE);
if (diffuseMaps.size() > 0) {
mymesh.diffuse = diffuseMaps.at(0);
mymesh.hasdif = true;
}else {
aiColor3D color(0.f, 0.f, 0.f);
maters->Get(AI_MATKEY_COLOR_DIFFUSE, color);
mymesh.hasdif = false;
}
vector<ofTexture> normalMaps = processTextures(maters, aiTextureType_NORMALS);
if (normalMaps.size() > 0) {
mymesh.normal = normalMaps.at(0);
mymesh.hasnorm = true;
}
else {
mymesh.hasnorm = false;
}
vector<ofTexture> roughnessMaps = processTextures(maters, aiTextureType_SHININESS);
if (roughnessMaps.size() > 0) {
mymesh.roughness = normalMaps.at(0);
mymesh.hasnorm = true;
}
else {
mymesh.hasnorm = false;
}
}
for (unsigned int i = 0; i < vertices.size();i++) {
mymesh.mySelf.addVertex(vertices.at(i).pos);
mymesh.mySelf.addNormal(vertices.at(i).norm);
mymesh.mySelf.addTexCoord(vertices.at(i).tex);
}
for (unsigned int i = 0; i < induces.size(); i++) {
mymesh.mySelf.addIndex(induces.at(i));
}
mymesh.name = mesh->mName.C_Str();
meshes.push_back(mymesh);
}
vector<ofTexture> MeshHolder::processTextures(aiMaterial* mat, aiTextureType type) {
aiString* path;
vector<ofTexture> retv;
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
bool skip = false;
ofTexture temp;
temp = loadTexture(directory + "/" + str.C_Str());
retv.push_back(temp);
}
return retv;
}
ofTexture MeshHolder::loadTexture(string path) {
ofTexture temp;
ofLoadImage(temp, path);
return temp;
}