#include "ofxAssimpModelLoader.h"
#include "ofxAssimpUtils.h"
#include "ofLight.h"
#include "ofImage.h"
#include <assimp/cimport.h>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <assimp/config.h>
ofxAssimpModelLoader::ofxAssimpModelLoader(){
clear();
}
ofxAssimpModelLoader::~ofxAssimpModelLoader(){
clear();
}
bool ofxAssimpModelLoader::loadModel(string modelName, bool optimize){
file.open(modelName, ofFile::ReadOnly, true);
if(!file.exists()) {
ofLogVerbose("ofxAssimpModelLoader") << "loadModel(): model does not exist: \"" << modelName << "\"";
return false;
}
ofLogVerbose("ofxAssimpModelLoader") << "loadModel(): loading \"" << file.getFileName()
<< "\" from \"" << file.getEnclosingDirectory() << "\"";
if(scene.get() != nullptr){
clear();
scene.reset();
}
unsigned int flags = initImportProperties(optimize);
std::string path = file.getAbsolutePath();
scene = shared_ptr<const aiScene>(aiImportFileExWithProperties(path.c_str(), flags, NULL, store.get()), aiReleaseImport);
bool bOk = processScene();
return bOk;
}
bool ofxAssimpModelLoader::loadModel(ofBuffer & buffer, bool optimize, const char * extension){
ofLogVerbose("ofxAssimpModelLoader") << "loadModel(): loading from memory buffer \"." << extension << "\"";
if(scene.get() != nullptr){
clear();
scene.reset();
}
unsigned int flags = initImportProperties(optimize);
scene = shared_ptr<const aiScene>(aiImportFileFromMemoryWithProperties(buffer.getData(), buffer.size(), flags, extension, store.get()), aiReleaseImport);
bool bOk = processScene();
return bOk;
}
unsigned int ofxAssimpModelLoader::initImportProperties(bool optimize) {
store.reset(aiCreatePropertyStore(), aiReleasePropertyStore);
aiSetImportPropertyInteger(store.get(), AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT );
aiSetImportPropertyInteger(store.get(), AI_CONFIG_PP_PTV_NORMALIZE, true);
unsigned int flags = aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_Triangulate | aiProcess_FlipUVs;
if(optimize) flags |= aiProcess_ImproveCacheLocality | aiProcess_OptimizeGraph |
aiProcess_OptimizeMeshes | aiProcess_JoinIdenticalVertices |
aiProcess_RemoveRedundantMaterials;
return flags;
}
bool ofxAssimpModelLoader::processScene() {
normalizeFactor = ofGetWidth() / 2.0;
if(scene){
loadGLResources();
update();
calculateDimensions();
if(getAnimationCount())
ofLogVerbose("ofxAssimpModelLoader") << "loadModel(): scene has " << getAnimationCount() << "animations";
else {
ofLogVerbose("ofxAssimpModelLoader") << "loadMode(): no animations";
}
return true;
}else{
ofLogError("ofxAssimpModelLoader") << "loadModel(): " + (string) aiGetErrorString();
clear();
return false;
}
return false;
}
void ofxAssimpModelLoader::createEmptyModel(){
if(scene){
clear();
scene.reset();
}
}
void ofxAssimpModelLoader::setNormalizationFactor(float factor){
normalizeFactor = factor;
}
void ofxAssimpModelLoader::calculateDimensions(){
if(!scene) return;
ofLogVerbose("ofxAssimpModelLoader") << "calculateDimensions(): inited scene with "
<< scene->mNumMeshes << " meshes & " << scene->mNumAnimations << " animations";
getBoundingBoxWithMinVector(&scene_min, &scene_max);
scene_center.x = (scene_min.x + scene_max.x) / 2.0f;
scene_center.y = (scene_min.y + scene_max.y) / 2.0f;
scene_center.z = (scene_min.z + scene_max.z) / 2.0f;
normalizedScale = scene_max.x-scene_min.x;
normalizedScale = MAX(scene_max.y - scene_min.y,normalizedScale);
normalizedScale = MAX(scene_max.z - scene_min.z,normalizedScale);
if (abs(normalizedScale) < std::numeric_limits<float>::epsilon()){
ofLogWarning("ofxAssimpModelLoader") << "Error calculating normalized scale of scene" << endl;
normalizedScale = 1.0;
} else {
normalizedScale = 1.f / normalizedScale;
normalizedScale *= normalizeFactor;
}
updateModelMatrix();
}
void ofxAssimpModelLoader::createLightsFromAiModel(){
lights.clear();
lights.resize(scene->mNumLights);
for(unsigned int i = 0; i < scene->mNumLights; i++){
lights[i].enable();
if(scene->mLights[i]->mType==aiLightSource_DIRECTIONAL){
lights[i].setDirectional();
lights[i].setOrientation(aiVecToOfVec(scene->mLights[i]->mDirection));
}
if(scene->mLights[i]->mType!=aiLightSource_POINT){
lights[i].setSpotlight();
lights[i].setPosition(aiVecToOfVec(scene->mLights[i]->mPosition));
}
lights[i].setAmbientColor(aiColorToOfColor(scene->mLights[i]->mColorAmbient));
lights[i].setDiffuseColor(aiColorToOfColor(scene->mLights[i]->mColorDiffuse));
lights[i].setSpecularColor(aiColorToOfColor(scene->mLights[i]->mColorSpecular));
}
}
void ofxAssimpModelLoader::optimizeScene(){
aiApplyPostProcessing(scene.get(),aiProcess_ImproveCacheLocality | aiProcess_OptimizeGraph |
aiProcess_OptimizeMeshes | aiProcess_JoinIdenticalVertices |
aiProcess_RemoveRedundantMaterials);
}
void ofxAssimpModelLoader::loadGLResources(){
ofLogVerbose("ofxAssimpModelLoader") << "loadGLResources(): starting";
modelMeshes.resize(scene->mNumMeshes,ofxAssimpMeshHelper());
for (unsigned int i = 0; i < scene->mNumMeshes; ++i){
ofLogVerbose("ofxAssimpModelLoader") << "loadGLResources(): loading mesh " << i;
aiMesh* mesh = scene->mMeshes[i];
ofxAssimpMeshHelper & meshHelper = modelMeshes[i];
aiMaterial* mtl = scene->mMaterials[mesh->mMaterialIndex];
aiColor4D dcolor, scolor, acolor, ecolor;
if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &dcolor)){
meshHelper.material.setDiffuseColor(aiColorToOfColor(dcolor));
}
if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &scolor)){
meshHelper.material.setSpecularColor(aiColorToOfColor(scolor));
}
if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &acolor)){
meshHelper.material.setAmbientColor(aiColorToOfColor(acolor));
}
if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &ecolor)){
meshHelper.material.setEmissiveColor(aiColorToOfColor(ecolor));
}
float shininess;
if(AI_SUCCESS == aiGetMaterialFloat(mtl, AI_MATKEY_SHININESS, &shininess)){
meshHelper.material.setShininess(shininess);
}
int blendMode;
if(AI_SUCCESS == aiGetMaterialInteger(mtl, AI_MATKEY_BLEND_FUNC, &blendMode)){
if(blendMode==aiBlendMode_Default){
meshHelper.blendMode=OF_BLENDMODE_ALPHA;
}else{
meshHelper.blendMode=OF_BLENDMODE_ADD;
}
}
unsigned int max = 1;
int two_sided;
if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided)
meshHelper.twoSided = true;
else
meshHelper.twoSided = false;
int texIndex = 0;
aiString texPath;
if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath)){
ofLogVerbose("ofxAssimpModelLoader") << "loadGLResource(): loading image from \"" << texPath.data << "\"";
string modelFolder = file.getEnclosingDirectory();
string relTexPath = ofFilePath::getEnclosingDirectory(texPath.data,false);
string texFile = ofFilePath::getFileName(texPath.data);
string realPath = ofFilePath::join(ofFilePath::join(modelFolder, relTexPath), texFile);
if(ofFile::doesFileExist(realPath) == false) {
ofLogError("ofxAssimpModelLoader") << "loadGLResource(): texture doesn't exist: \""
<< file.getFileName() + "\" in \"" << realPath << "\"";
}
ofxAssimpTexture assimpTexture;
bool bTextureAlreadyExists = false;
for(size_t j = 0; j < textures.size(); j++) {
assimpTexture = textures[j];
if(assimpTexture.getTexturePath() == realPath) {
bTextureAlreadyExists = true;
break;
}
}
if(bTextureAlreadyExists) {
meshHelper.assimpTexture = assimpTexture;
ofLogVerbose("ofxAssimpModelLoader") << "loadGLResource(): texture already loaded: \""
<< file.getFileName() + "\" from \"" << realPath << "\"";
} else {
ofTexture texture;
bool bTextureLoadedOk = ofLoadImage(texture, realPath);
if(bTextureLoadedOk) {
textures.push_back(ofxAssimpTexture(texture, realPath));
assimpTexture = textures.back();
meshHelper.assimpTexture = assimpTexture;
ofLogVerbose("ofxAssimpModelLoader") << "loadGLResource(): texture loaded, dimensions: "
<< texture.getWidth() << "x" << texture.getHeight();
} else {
ofLogError("ofxAssimpModelLoader") << "loadGLResource(): couldn't load texture: \""
<< file.getFileName() + "\" from \"" << realPath << "\"";
}
}
}
meshHelper.mesh = mesh;
aiMeshToOfMesh(mesh, meshHelper.cachedMesh, &meshHelper);
meshHelper.cachedMesh.setMode(OF_PRIMITIVE_TRIANGLES);
meshHelper.validCache = true;
meshHelper.hasChanged = false;
int numOfAnimations = scene->mNumAnimations;
for (int i = 0; i<numOfAnimations; i++) {
aiAnimation * animation = scene->mAnimations[i];
animations.push_back(ofxAssimpAnimation(scene, animation));
}
if(hasAnimations()){
meshHelper.animatedPos.resize(mesh->mNumVertices);
if(mesh->HasNormals()){
meshHelper.animatedNorm.resize(mesh->mNumVertices);
}
}
int usage;
if(getAnimationCount()){
#ifndef TARGET_OPENGLES
if(!ofIsGLProgrammableRenderer()){
usage = GL_STATIC_DRAW;
}else{
usage = GL_STREAM_DRAW;
}
#else
usage = GL_DYNAMIC_DRAW;
#endif
}else{
usage = GL_STATIC_DRAW;
}
meshHelper.vbo.setVertexData(&mesh->mVertices[0].x,3,mesh->mNumVertices,usage,sizeof(aiVector3D));
if(mesh->HasVertexColors(0)){
meshHelper.vbo.setColorData(&mesh->mColors[0][0].r,mesh->mNumVertices,GL_STATIC_DRAW,sizeof(aiColor4D));
}
if(mesh->HasNormals()){
meshHelper.vbo.setNormalData(&mesh->mNormals[0].x,mesh->mNumVertices,usage,sizeof(aiVector3D));
}
if (meshHelper.cachedMesh.hasTexCoords()){
meshHelper.vbo.setTexCoordData(&meshHelper.cachedMesh.getTexCoords()[0].x, mesh->mNumVertices,GL_STATIC_DRAW,sizeof(ofVec2f));
}
meshHelper.indices.resize(mesh->mNumFaces * 3);
int j=0;
for (unsigned int x = 0; x < mesh->mNumFaces; ++x){
for (unsigned int a = 0; a < mesh->mFaces[x].mNumIndices; ++a){
meshHelper.indices[j++]=mesh->mFaces[x].mIndices[a];
}
}
meshHelper.vbo.setIndexData(&meshHelper.indices[0],meshHelper.indices.size(),GL_STATIC_DRAW);
}
ofLogVerbose("ofxAssimpModelLoader") << "loadGLResource(): finished";
}
void ofxAssimpModelLoader::clear(){
ofLogVerbose("ofxAssimpModelLoader") << "clear(): deleting GL resources";
modelMeshes.clear();
animations.clear();
pos.set(0,0,0);
scale.set(1,1,1);
rotAngle.clear();
rotAxis.clear();
lights.clear();
scale = ofPoint(1, 1, 1);
normalizeScale = true;
bUsingMaterials = true;
bUsingNormals = true;
bUsingTextures = true;
bUsingColors = true;
currentAnimation = -1;
textures.clear();
updateModelMatrix();
}
void ofxAssimpModelLoader::update() {
if(!scene) return;
updateAnimations();
updateMeshes(scene->mRootNode, ofMatrix4x4());
if(hasAnimations() == false) {
return;
}
updateBones();
updateGLResources();
}
void ofxAssimpModelLoader::updateAnimations() {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].update();
}
}
void ofxAssimpModelLoader::updateMeshes(aiNode * node, ofMatrix4x4 parentMatrix) {
aiMatrix4x4 m = node->mTransformation;
m.Transpose();
ofMatrix4x4 matrix(m.a1, m.a2, m.a3, m.a4,
m.b1, m.b2, m.b3, m.b4,
m.c1, m.c2, m.c3, m.c4,
m.d1, m.d2, m.d3, m.d4);
matrix *= parentMatrix;
for(unsigned int i = 0; i < node->mNumMeshes; i++) {
int meshIndex = node->mMeshes[i];
ofxAssimpMeshHelper & mesh = modelMeshes[meshIndex];
mesh.matrix = matrix;
}
for(unsigned int i = 0; i < node->mNumChildren; i++) {
updateMeshes(node->mChildren[i], matrix);
}
}
void ofxAssimpModelLoader::updateBones() {
if (!hasAnimations()){
return;
}
for(size_t i = 0; i < modelMeshes.size(); ++i) {
const aiMesh* mesh = modelMeshes[i].mesh;
vector<aiMatrix4x4> boneMatrices(mesh->mNumBones);
for(unsigned int a = 0; a < mesh->mNumBones; ++a) {
const aiBone* bone = mesh->mBones[a];
aiNode* node = scene->mRootNode->FindNode(bone->mName);
boneMatrices[a] = bone->mOffsetMatrix;
const aiNode* tempNode = node;
while(tempNode) {
boneMatrices[a] = tempNode->mTransformation * boneMatrices[a];
tempNode = tempNode->mParent;
}
modelMeshes[i].hasChanged = true;
modelMeshes[i].validCache = false;
}
modelMeshes[i].animatedPos.assign(modelMeshes[i].animatedPos.size(), aiVector3D(0.0f));
if(mesh->HasNormals()){
modelMeshes[i].animatedNorm.assign(modelMeshes[i].animatedNorm.size(), aiVector3D(0.0f));
}
for(unsigned int a = 0; a < mesh->mNumBones; ++a) {
const aiBone* bone = mesh->mBones[a];
const aiMatrix4x4& posTrafo = boneMatrices[a];
for(unsigned int b = 0; b < bone->mNumWeights; ++b) {
const aiVertexWeight& weight = bone->mWeights[b];
size_t vertexId = weight.mVertexId;
const aiVector3D& srcPos = mesh->mVertices[vertexId];
modelMeshes[i].animatedPos[vertexId] += weight.mWeight * (posTrafo * srcPos);
}
if(mesh->HasNormals()){
aiMatrix3x3 normTrafo = aiMatrix3x3( posTrafo);
for(unsigned int b = 0; b < bone->mNumWeights; ++b) {
const aiVertexWeight& weight = bone->mWeights[b];
size_t vertexId = weight.mVertexId;
const aiVector3D& srcNorm = mesh->mNormals[vertexId];
modelMeshes[i].animatedNorm[vertexId] += weight.mWeight * (normTrafo * srcNorm);
}
}
}
}
}
void ofxAssimpModelLoader::updateGLResources(){
for (unsigned int i = 0; i < modelMeshes.size(); ++i){
if(modelMeshes[i].hasChanged){
const aiMesh* mesh = modelMeshes[i].mesh;
if(hasAnimations()){
modelMeshes[i].vbo.updateVertexData(&modelMeshes[i].animatedPos[0].x,mesh->mNumVertices);
if(mesh->HasNormals()){
modelMeshes[i].vbo.updateNormalData(&modelMeshes[i].animatedNorm[0].x,mesh->mNumVertices);
}
}
modelMeshes[i].hasChanged = false;
}
}
}
void ofxAssimpModelLoader::updateModelMatrix() {
modelMatrix.makeIdentityMatrix();
modelMatrix.glTranslate(pos);
modelMatrix.glRotate(180, 0, 0, 1);
if(normalizeScale) {
modelMatrix.glScale(normalizedScale , normalizedScale, normalizedScale);
}
for(size_t i = 0; i < rotAngle.size(); i++){
modelMatrix.glRotate(rotAngle[i], rotAxis[i].x, rotAxis[i].y, rotAxis[i].z);
}
modelMatrix.glScale(scale.x, scale.y, scale.z);
}
bool ofxAssimpModelLoader::hasAnimations() {
return animations.size() > 0;
}
unsigned int ofxAssimpModelLoader::getAnimationCount(){
return animations.size();
}
ofxAssimpAnimation & ofxAssimpModelLoader::getAnimation(int animationIndex) {
animationIndex = ofClamp(animationIndex, 0, animations.size()-1);
return animations[animationIndex];
}
void ofxAssimpModelLoader::playAllAnimations() {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].play();
}
}
void ofxAssimpModelLoader::stopAllAnimations() {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].stop();
}
}
void ofxAssimpModelLoader::resetAllAnimations() {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].reset();
}
}
void ofxAssimpModelLoader::setPausedForAllAnimations(bool pause) {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].setPaused(pause);
}
}
void ofxAssimpModelLoader::setLoopStateForAllAnimations(ofLoopType state) {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].setLoopState(state);
}
}
void ofxAssimpModelLoader::setPositionForAllAnimations(float position) {
for(size_t i = 0; i < animations.size(); i++) {
animations[i].setPosition(position);
}
}
void ofxAssimpModelLoader::setAnimation(int animationIndex) {
if(!hasAnimations()) {
return;
}
currentAnimation = ofClamp(animationIndex, 0, getAnimationCount() - 1);
}
void ofxAssimpModelLoader::setNormalizedTime(float time) {
if(!hasAnimations()) {
return;
}
currentAnimation = ofClamp(currentAnimation, 0, getAnimationCount() - 1);
ofxAssimpAnimation & animation = animations[currentAnimation];
float realT = ofMap(time, 0.0, 1.0, 0.0, animation.getDurationInSeconds(), false);
animation.setPosition(realT);
update();
}
void ofxAssimpModelLoader::setTime(float time) {
if(!hasAnimations()) {
return;
}
currentAnimation = ofClamp(currentAnimation, 0, getAnimationCount() - 1);
ofxAssimpAnimation & animation = animations[currentAnimation];
animation.setPosition(time);
update();
}
float ofxAssimpModelLoader::getDuration(int animationIndex) {
if(!hasAnimations()) {
return 0;
}
animationIndex = ofClamp(animationIndex, 0, getAnimationCount() - 1);
float duration = animations[animationIndex].getDurationInSeconds();
return duration;
}
bool ofxAssimpModelLoader::hasMeshes() {
return modelMeshes.size() > 0;
}
unsigned int ofxAssimpModelLoader::getMeshCount() {
return modelMeshes.size();
}
ofxAssimpMeshHelper & ofxAssimpModelLoader::getMeshHelper(int meshIndex) {
meshIndex = ofClamp(meshIndex, 0, modelMeshes.size()-1);
return modelMeshes[meshIndex];
}
void ofxAssimpModelLoader::getBoundingBoxWithMinVector( aiVector3D* min, aiVector3D* max )
{
aiMatrix4x4 trafo;
aiIdentityMatrix4(&trafo);
min->x = min->y = min->z = 1e10f;
max->x = max->y = max->z = -1e10f;
for(auto & mesh: modelMeshes){
this->getBoundingBoxForNode(mesh, min, max);
}
}
void ofxAssimpModelLoader::getBoundingBoxForNode(const ofxAssimpMeshHelper & mesh, aiVector3D* min, aiVector3D* max){
if (!hasAnimations()){
for(unsigned int i = 0; i < mesh.mesh->mNumVertices; i++){
auto vertex = mesh.mesh->mVertices[i];
auto tmp = ofVec3f(vertex.x,vertex.y,vertex.z) * mesh.matrix;
min->x = MIN(min->x,tmp.x);
min->y = MIN(min->y,tmp.y);
min->z = MIN(min->z,tmp.z);
max->x = MAX(max->x,tmp.x);
max->y = MAX(max->y,tmp.y);
max->z = MAX(max->z,tmp.z);
}
} else {
for (auto & animPos: mesh.animatedPos){
auto tmp = ofVec3f(animPos.x,animPos.y,animPos.z) * mesh.matrix;
min->x = MIN(min->x,tmp.x);
min->y = MIN(min->y,tmp.y);
min->z = MIN(min->z,tmp.z);
max->x = MAX(max->x,tmp.x);
max->y = MAX(max->y,tmp.y);
max->z = MAX(max->z,tmp.z);
}
}
}
void ofxAssimpModelLoader::setPosition(float x, float y, float z){
pos.x = x;
pos.y = y;
pos.z = z;
updateModelMatrix();
}
void ofxAssimpModelLoader::setScale(float x, float y, float z){
scale.x = x;
scale.y = y;
scale.z = z;
updateModelMatrix();
}
void ofxAssimpModelLoader::setScaleNormalization(bool normalize) {
normalizeScale = normalize;
updateModelMatrix();
}
void ofxAssimpModelLoader::setRotation(int which, float angle, float rot_x, float rot_y, float rot_z){
if(which + 1 > (int)rotAngle.size()){
int diff = 1 + (which - rotAngle.size());
for(int i = 0; i < diff; i++){
rotAngle.push_back(0);
rotAxis.push_back(ofPoint());
}
}
rotAngle[which] = angle;
rotAxis[which].x = rot_x;
rotAxis[which].y = rot_y;
rotAxis[which].z = rot_z;
updateModelMatrix();
}
void ofxAssimpModelLoader::drawWireframe(){
draw(OF_MESH_WIREFRAME);
}
void ofxAssimpModelLoader::drawFaces(){
draw(OF_MESH_FILL);
}
void ofxAssimpModelLoader::drawVertices(){
draw(OF_MESH_POINTS);
}
void ofxAssimpModelLoader::draw(ofPolyRenderMode renderType) {
if(scene == NULL) {
return;
}
ofPushStyle();
ofPushMatrix();
ofMultMatrix(modelMatrix);
#ifndef TARGET_OPENGLES
glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
#endif
for(size_t i = 0; i < modelMeshes.size(); i++) {
ofxAssimpMeshHelper & mesh = modelMeshes[i];
ofPushMatrix();
ofMultMatrix(mesh.matrix);
if(bUsingTextures){
if(mesh.hasTexture()) {
mesh.getTextureRef().bind();
}
}
if(bUsingMaterials){
mesh.material.begin();
}
if(mesh.twoSided) {
glEnable(GL_CULL_FACE);
}
else {
glDisable(GL_CULL_FACE);
}
ofEnableBlendMode(mesh.blendMode);
#ifndef TARGET_OPENGLES
mesh.vbo.drawElements(GL_TRIANGLES,mesh.indices.size());
#else
switch(renderType){
case OF_MESH_FILL:
mesh.vbo.drawElements(GL_TRIANGLES,mesh.indices.size());
break;
case OF_MESH_WIREFRAME:
mesh.vbo.drawElements(GL_LINES,mesh.indices.size());
break;
case OF_MESH_POINTS:
mesh.vbo.drawElements(GL_POINTS,mesh.indices.size());
break;
}
#endif
if(bUsingTextures){
if(mesh.hasTexture()) {
mesh.getTextureRef().unbind();
}
}
if(bUsingMaterials){
mesh.material.end();
}
ofPopMatrix();
}
#ifndef TARGET_OPENGLES
if( renderType != OF_MESH_FILL ){
glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(OF_MESH_FILL));
}
#endif
ofPopMatrix();
ofPopStyle();
}
vector<string> ofxAssimpModelLoader::getMeshNames(){
vector<string> names(scene->mNumMeshes);
for(unsigned int i=0; i< scene->mNumMeshes; i++){
names[i] = scene->mMeshes[i]->mName.data;
}
return names;
}
unsigned int ofxAssimpModelLoader::getNumMeshes(){
return scene->mNumMeshes;
}
ofMesh ofxAssimpModelLoader::getMesh(string name){
ofMesh ofm;
ofm.setMode(OF_PRIMITIVE_TRIANGLES);
aiMesh * aim = NULL;
for(unsigned int i=0; i < scene->mNumMeshes; i++){
if(string(scene->mMeshes[i]->mName.data)==name){
aim = scene->mMeshes[i];
break;
}
}
if(!aim){
ofLogError("ofxAssimpModelLoader") <<"getMesh(): couldn't find mesh: \"" << name << "\"";
return ofm;
}
aiMeshToOfMesh(aim,ofm);
return ofm;
}
ofMesh ofxAssimpModelLoader::getMesh(unsigned int num){
ofMesh ofm;
if(scene->mNumMeshes <= num){
ofLogError("ofxAssimpModelLoader") << "getMesh(): mesh id " << num
<< " out of range for total num meshes: " << scene->mNumMeshes;
return ofm;
}
aiMeshToOfMesh(scene->mMeshes[num],ofm);
return ofm;
}
ofMesh ofxAssimpModelLoader::getCurrentAnimatedMesh(string name){
for(size_t i=0; i < modelMeshes.size(); i++){
if(string(modelMeshes[i].mesh->mName.data)==name){
if(!modelMeshes[i].validCache){
modelMeshes[i].cachedMesh.clearVertices();
modelMeshes[i].cachedMesh.clearNormals();
if(hasAnimations()){
modelMeshes[i].cachedMesh.addVertices(aiVecVecToOfVecVec(modelMeshes[i].animatedPos));
modelMeshes[i].cachedMesh.addNormals(aiVecVecToOfVecVec(modelMeshes[i].animatedNorm));
}
modelMeshes[i].validCache = true;
}
return modelMeshes[i].cachedMesh;
}
}
ofLogError("ofxAssimpModelLoader") << "getCurrentAnimatedMesh(): couldn't find mesh: \"" + name << "\"";
return ofMesh();
}
ofMesh ofxAssimpModelLoader::getCurrentAnimatedMesh(unsigned int num){
if(modelMeshes.size() <= num){
ofLogError("ofxAssimpModelLoader") << "getCurrentAnimatedMesh(): mesh id: " << num
<< "out of range for total num meshes: " << scene->mNumMeshes;
return ofMesh();
}
if(!modelMeshes[num].validCache){
modelMeshes[num].cachedMesh.clearVertices();
modelMeshes[num].cachedMesh.clearNormals();
modelMeshes[num].cachedMesh.addVertices(aiVecVecToOfVecVec(modelMeshes[num].animatedPos));
modelMeshes[num].cachedMesh.addNormals(aiVecVecToOfVecVec(modelMeshes[num].animatedNorm));
modelMeshes[num].validCache = true;
}
return modelMeshes[num].cachedMesh;
}
ofMaterial ofxAssimpModelLoader::getMaterialForMesh(string name){
for(size_t i = 0; i < modelMeshes.size(); i++){
if(string(modelMeshes[i].mesh->mName.data)==name){
return modelMeshes[i].material;
}
}
ofLogError("ofxAssimpModelLoader") << "getMaterialForMesh(): couldn't find mesh: \"" + name << "\"";
return ofMaterial();
}
ofMaterial ofxAssimpModelLoader::getMaterialForMesh(unsigned int num){
if(modelMeshes.size() <= num){
ofLogError("ofxAssimpModelLoader") << "getMaterialForMesh(): mesh id: " << num
<< "out of range for total num meshes: " << scene->mNumMeshes;
return ofMaterial();
}
return modelMeshes[num].material;
}
ofTexture ofxAssimpModelLoader::getTextureForMesh(string name){
for(size_t i = 0; i < modelMeshes.size(); i++){
if(string(modelMeshes[i].mesh->mName.data)==name){
if(modelMeshes[i].hasTexture()) {
return modelMeshes[i].getTextureRef();
}
}
}
ofLogError("ofxAssimpModelLoader") << "getTextureForMesh(): couldn't find mesh: \"" + name << "\"";
return ofTexture();
}
ofTexture ofxAssimpModelLoader::getTextureForMesh(unsigned int i){
if(i < modelMeshes.size()){
if(modelMeshes[i].hasTexture()) {
return modelMeshes[i].getTextureRef();
}
}
ofLogError("ofxAssimpModelLoader") << "getTextureForMesh(): mesh id: " << i
<< "out of range for total num meshes: " << scene->mNumMeshes;
return ofTexture();
}
ofPoint ofxAssimpModelLoader::getPosition(){
return pos;
}
ofPoint ofxAssimpModelLoader::getSceneCenter(){
return aiVecToOfVec(scene_center);
}
float ofxAssimpModelLoader::getNormalizedScale(){
return normalizedScale;
}
ofPoint ofxAssimpModelLoader::getScale(){
return scale;
}
ofMatrix4x4 ofxAssimpModelLoader::getModelMatrix() {
return modelMatrix;
}
ofPoint ofxAssimpModelLoader::getSceneMin(bool bScaled ){
ofPoint sceneMin(scene_min.x, scene_min.y, scene_min.z);
if( bScaled ){
return sceneMin * scale;
}else{
return sceneMin;
}
}
ofPoint ofxAssimpModelLoader::getSceneMax(bool bScaled ){
ofPoint sceneMax(scene_max.x, scene_max.y, scene_max.z);
if( bScaled ){
return sceneMax * scale;
}else{
return sceneMax;
}
}
int ofxAssimpModelLoader::getNumRotations(){
return rotAngle.size();
}
ofPoint ofxAssimpModelLoader::getRotationAxis(int which){
if((int)rotAxis.size() > which){
return rotAxis[which];
}else{
return ofPoint();
}
}
float ofxAssimpModelLoader::getRotationAngle(int which){
if((int)rotAngle.size() > which){
return rotAngle[which];
}else{
return 0.0;
}
}
const aiScene* ofxAssimpModelLoader::getAssimpScene(){
return scene.get();
}
void ofxAssimpModelLoader::enableTextures(){
bUsingTextures = true;
}
void ofxAssimpModelLoader::enableNormals(){
bUsingNormals = true;
}
void ofxAssimpModelLoader::enableColors(){
bUsingColors = true;
}
void ofxAssimpModelLoader::enableMaterials(){
bUsingMaterials = true;
}
void ofxAssimpModelLoader::disableTextures(){
bUsingTextures = false;
}
void ofxAssimpModelLoader::disableNormals(){
bUsingNormals = false;
}
void ofxAssimpModelLoader::disableColors(){
bUsingColors = false;
}
void ofxAssimpModelLoader::disableMaterials(){
bUsingMaterials = false;
}
Comments