//-------------------------------------------
void ofxAssimpModelLoader::getBoundingBoxForNode(const ofxAssimpMeshHelper & mesh, aiVector3D* min, aiVector3D* max){
    if (!hasAnimations()){
        for (size_t 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);
        }
    }
}
// DEPRECATED.
float ofxAssimpModelLoader::getDuration(int animationIndex) {
    if(!hasAnimations()) {
        return 0;
    }
    animationIndex = ofClamp(animationIndex, 0, getAnimationCount() - 1);
    float duration = animations[animationIndex].getDurationInSeconds();
    return duration;
}
// DEPRECATED.
void ofxAssimpModelLoader::setTime(float time) {
    if(!hasAnimations()) {
        return;
    }
    setAnimation(currentAnimation); // call this again to clamp animation index, in case the model is reloaded.
    ofxAssimpAnimation & animation = animations[currentAnimation];
    animation.setPosition(time);
    update();
}
// DEPRECATED.
void ofxAssimpModelLoader::setNormalizedTime(float time) {
    if(!hasAnimations()) {
        return;
    }
    setAnimation(currentAnimation); // call this again to clamp animation index, in case the model is reloaded.
    ofxAssimpAnimation & animation = animations[currentAnimation];
    float realT = ofMap(time, 0.0, 1.0, 0.0, animation.getDurationInSeconds(), false);
    setTime(realT);
}
//------------------------------------------- update.
void ofxAssimpModelLoader::update() {
    updateAnimations();
    updateMeshes(scene->mRootNode, ofMatrix4x4());
    if(hasAnimations() == false) {
        return;
    }
    updateBones();
    updateGLResources();
}
void AnimationExporter::exportAnimations(Scene *sce)
{
	if (hasAnimations(sce)) {
		this->scene = sce;

		openLibrary();

		forEachObjectInExportSet(sce, *this, this->export_settings->export_set);

		closeLibrary();
	}
}
Esempio n. 7
0
void AnimationExporter::exportAnimations(Scene *sce)
{
	if(hasAnimations(sce)) {
		this->scene = sce;

		openLibrary();

		forEachObjectInScene(sce, *this);

		closeLibrary();
	}
}
bool AnimationExporter::exportAnimations(Scene *sce)
{
	bool has_animations = hasAnimations(sce);
	if (has_animations) {
		this->scene = sce;

		openLibrary();

		forEachObjectInExportSet(sce, *this, this->export_settings->export_set);

		closeLibrary();
	}
	return has_animations;
}
void ofxAssimpModelLoader::updateGLResources(){
    // now upload the result position and normal along with the other vertex attributes into a dynamic vertex buffer, VBO or whatever
    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;
    	}
    }
}
//-------------------------------------------
ofMesh ofxAssimpModelLoader::getCurrentAnimatedMesh(string name){
	for(int i=0; i<(int)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();

}
// DEPRECATED.
void ofxAssimpModelLoader::setAnimation(int animationIndex) {
    if(!hasAnimations()) {
        return;
    }
    currentAnimation = ofClamp(animationIndex, 0, getAnimationCount() - 1);
}
void ofxAssimpModelLoader::updateBones() {
    if (!hasAnimations()){
        return;
    }
    // update mesh position for the animation
	for(unsigned int i=0; i<modelMeshes.size(); ++i) {
		// current mesh we are introspecting
		const aiMesh* mesh = modelMeshes[i].mesh;
        
		// calculate bone matrices
		vector<aiMatrix4x4> boneMatrices(mesh->mNumBones);
		for(unsigned int a=0; a<mesh->mNumBones; ++a) {
			const aiBone* bone = mesh->mBones[a];
            
			// find the corresponding node by again looking recursively through the node hierarchy for the same name
			aiNode* node = scene->mRootNode->FindNode(bone->mName);
            
			// start with the mesh-to-bone matrix
			boneMatrices[a] = bone->mOffsetMatrix;
			// and now append all node transformations down the parent chain until we're back at mesh coordinates again
			const aiNode* tempNode = node;
			while(tempNode) {
				// check your matrix multiplication order here!!!
				boneMatrices[a] = tempNode->mTransformation * boneMatrices[a];
				// boneMatrices[a] = boneMatrices[a] * tempNode->mTransformation;
				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));
		}
		// loop through all vertex weights of all bones
		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()){
				// 3x3 matrix, contains the bone matrix without the translation, only with rotation and possibly scaling
				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::loadGLResources(){

	ofLogVerbose("ofxAssimpModelLoader") << "loadGLResources(): starting";

    // create new mesh helpers for each mesh, will populate their data later.
    modelMeshes.resize(scene->mNumMeshes,ofxAssimpMeshHelper());

    // create OpenGL buffers and populate them based on each meshes pertinant info.
    for (unsigned int i = 0; i < scene->mNumMeshes; ++i){
        ofLogVerbose("ofxAssimpModelLoader") << "loadGLResources(): loading mesh " << i;
        // current mesh we are introspecting
        aiMesh* mesh = scene->mMeshes[i];

        // the current meshHelper we will be populating data into.
        ofxAssimpMeshHelper & meshHelper = modelMeshes[i];
        //ofxAssimpMeshHelper meshHelper;
		
        //meshHelper.texture = NULL;

        // Handle material info
        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;
			}
		}

        // Culling
        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;

        // Load Textures
        int texIndex = 0;
        aiString texPath;

        // TODO: handle other aiTextureTypes
        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(int 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.getTexCoordsPointer()[0].getPtr(),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);

        //modelMeshes.push_back(meshHelper);
    }
    


    ofLogVerbose("ofxAssimpModelLoader") << "loadGLResource(): finished";
}