void readAssimpMesh(const char * filename, const aiScene * scene, const aiNode * node, Mesh * mesh, const char * meshRep, bool rotate90) { unsigned int i; char globalPath[256]; // clear mesh mesh->clear(); // textures unsigned int nb_textures = 0; for(i=0; i<scene->mNumMaterials; i++) { aiMaterial * mtl = scene->mMaterials[i]; aiString path; if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, 0, &path)) nb_textures++; if(AI_SUCCESS == mtl->GetTexture(aiTextureType_SPECULAR, 0, &path)) nb_textures++; if(AI_SUCCESS == mtl->GetTexture(aiTextureType_NORMALS, 0, &path)) nb_textures++; if(AI_SUCCESS == mtl->GetTexture(aiTextureType_EMISSIVE, 0, &path)) nb_textures++; } mesh->allocTextures(nb_textures); // materials mesh->allocMaterials(scene->mNumMaterials); for(i=0; i<scene->mNumMaterials; i++) { aiMaterial * mtl = scene->mMaterials[i]; Material * material = mesh->addNewMaterial(); float value; aiColor4D color; material->setType(1); if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &color)) material->setDiffuse(Vector3(color.r, color.g, color.b)); if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &color)) material->setSpecular(Vector3(color.r, color.g, color.b)); if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &color)) material->setEmit(Vector3(color.r, color.g, color.b)); if(AI_SUCCESS == aiGetMaterialFloat(mtl, AI_MATKEY_OPACITY, &value)) material->setOpacity(value); if(AI_SUCCESS == aiGetMaterialFloat(mtl, AI_MATKEY_SHININESS, &value)) material->setShininess(value); // blend { int blendMode; if(AI_SUCCESS == aiGetMaterialInteger(mtl, AI_MATKEY_BLEND_FUNC, &blendMode)) { switch(blendMode) { default: case aiBlendMode_Default: material->setBlendMode(BLENDING_NONE); break; case aiBlendMode_Additive: material->setBlendMode(BLENDING_ADD); break; } } } // textures { aiString path; aiTextureMapping mapping; unsigned int uvindex; float blend; aiTextureOp op; aiTextureMapMode mapmode; if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping, &uvindex, &blend, &op, &mapmode)) { material->allocTexturesPass(4); getGlobalFilename(globalPath, meshRep, path.C_Str()); TextureRef * texRef = level->loadTexture(globalPath, true); Texture * texture = mesh->addNewTexture(texRef); if(mapmode == aiTextureMapMode_Clamp){ texture->setUWrapMode(WRAP_CLAMP); texture->setVWrapMode(WRAP_CLAMP); } material->addTexturePass(texture, TEX_COMBINE_MODULATE, uvindex); } if(AI_SUCCESS == mtl->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping, &uvindex, &blend, &op, &mapmode)) { getGlobalFilename(globalPath, meshRep, path.C_Str()); TextureRef * texRef = level->loadTexture(globalPath, true); Texture * texture = mesh->addNewTexture(texRef); if(mapmode == aiTextureMapMode_Clamp){ texture->setUWrapMode(WRAP_CLAMP); texture->setVWrapMode(WRAP_CLAMP); } while(material->getTexturesPassNumber() < 1) material->addTexturePass(NULL, TEX_COMBINE_MODULATE, 0); material->addTexturePass(texture, TEX_COMBINE_MODULATE, uvindex); } if(AI_SUCCESS == mtl->GetTexture(aiTextureType_NORMALS, 0, &path, &mapping, &uvindex, &blend, &op, &mapmode)) { getGlobalFilename(globalPath, meshRep, path.C_Str()); TextureRef * texRef = level->loadTexture(globalPath, true); Texture * texture = mesh->addNewTexture(texRef); if(mapmode == aiTextureMapMode_Clamp){ texture->setUWrapMode(WRAP_CLAMP); texture->setVWrapMode(WRAP_CLAMP); } while(material->getTexturesPassNumber() < 2) material->addTexturePass(NULL, TEX_COMBINE_MODULATE, 0); material->addTexturePass(texture, TEX_COMBINE_MODULATE, uvindex); } if(AI_SUCCESS == mtl->GetTexture(aiTextureType_EMISSIVE, 0, &path, &mapping, &uvindex, &blend, &op, &mapmode)) { getGlobalFilename(globalPath, meshRep, path.C_Str()); TextureRef * texRef = level->loadTexture(globalPath, true); Texture * texture = mesh->addNewTexture(texRef); if(mapmode == aiTextureMapMode_Clamp){ texture->setUWrapMode(WRAP_CLAMP); texture->setVWrapMode(WRAP_CLAMP); } while(material->getTexturesPassNumber() < 3) material->addTexturePass(NULL, TEX_COMBINE_MODULATE, 0); material->addTexturePass(texture, TEX_COMBINE_MODULATE, uvindex); } } } // subMeshs unsigned int nb_subMeshs = 0, nb_bones = 0; countMeshs(scene, node, &nb_subMeshs); countNodes(scene, scene->mRootNode, &nb_bones); if(nb_subMeshs > 0) { Matrix4x4 rootMatrix; if(rotate90) rootMatrix.rotate(Vector3(1, 0, 0), 90); // create armature if(nb_bones > 0) { Armature * armature = mesh->createArmature(); armature->allocBones(nb_bones); createArmature(scene, scene->mRootNode, armature, NULL, rootMatrix); armature->constructBonesInversePoseMatrix(); } // create subMeshs SubMesh * subMeshs = mesh->allocSubMeshs(nb_subMeshs); unsigned int count = 0; createSubMesh(scene, node, mesh, subMeshs, &count, rootMatrix); } // do we need armature { bool skinning = false; unsigned int s, sSize = mesh->getSubMeshsNumber(); for(s=0; s<sSize; s++) { if(mesh->getSubMeshs()[s].getSkinData()) { skinning = true; break; } } if(! skinning) mesh->clearArmature(); } // animation if(mesh->getArmature() && scene->mNumAnimations > 0) { Armature * armature = mesh->getArmature(); char maaName[256]; sprintf(maaName, "%s.maa", filename); ArmatureAnim * armatureAnim = ArmatureAnim::getNew(); ArmatureAnimRef * armatureAnimRef = ArmatureAnimRef::getNew(armatureAnim, maaName); level->getArmatureAnimManager()->addRef(armatureAnimRef); mesh->setArmatureAnimRef(armatureAnimRef); AnimRange * animRanges = mesh->allocAnimsRanges(scene->mNumAnimations); // armature anim if(armatureAnim) { unsigned int a, aSize = scene->mNumAnimations; Object3dAnim * bonesAnim = armatureAnim->allocBonesAnim(armature->getBonesNumber()); // node infos (for multiple anims merging) map <string, NodeInfos> nodesInfos; for(a=0; a<aSize; a++) { aiAnimation * anim = scene->mAnimations[a]; unsigned int c, cSize; for(c=0; c<anim->mNumChannels; c++) { aiNodeAnim * channel = anim->mChannels[c]; NodeInfos * infos = &(nodesInfos[channel->mNodeName.data]); infos->nbKeyPos += channel->mNumPositionKeys; infos->nbKeyRot += channel->mNumRotationKeys; infos->nbKeyScale += channel->mNumScalingKeys; } } // alloc keys { map<string, NodeInfos>::iterator mit (nodesInfos.begin()), mend(nodesInfos.end()); for(; mit!=mend; mit++) { unsigned int boneId; if(armature->getBoneId(mit->first.c_str(), &boneId)) { Object3dAnim * boneAnim = &(bonesAnim[boneId]); if(mit->second.nbKeyPos > 0) boneAnim->allocPositionKeys(mit->second.nbKeyPos); if(mit->second.nbKeyRot > 0) boneAnim->allocRotationKeys(mit->second.nbKeyRot); if(mit->second.nbKeyScale > 0) boneAnim->allocScaleKeys(mit->second.nbKeyScale); mit->second.nbKeyPos = 0; mit->second.nbKeyRot = 0; mit->second.nbKeyScale = 0; } } } // anims int prevT = 0; for(a=0; a<aSize; a++) { aiAnimation * anim = scene->mAnimations[a]; animRanges[a].start = prevT; animRanges[a].end = prevT + getMaratisTick(anim->mDuration, anim->mTicksPerSecond); unsigned int c, cSize; for(c=0; c<anim->mNumChannels; c++) { aiNodeAnim * channel = anim->mChannels[c]; NodeInfos * infos = &(nodesInfos[channel->mNodeName.data]); unsigned int boneId; if(armature->getBoneId(channel->mNodeName.data, &boneId)) { unsigned int k; Object3dAnim * boneAnim = &(bonesAnim[boneId]); Key * posKeys = boneAnim->getPositionKeys(); Key * rotKeys = boneAnim->getRotationKeys(); Key * scaleKeys = boneAnim->getScaleKeys(); // pos for(k=0; k<channel->mNumPositionKeys; k++) { posKeys[infos->nbKeyPos+k].setT(prevT + getMaratisTick(channel->mPositionKeys[k].mTime, anim->mTicksPerSecond)); *(posKeys[infos->nbKeyPos+k].createVector3Data()) = Vector3( channel->mPositionKeys[k].mValue.x, channel->mPositionKeys[k].mValue.y, channel->mPositionKeys[k].mValue.z ); } // rot for(k=0; k<channel->mNumRotationKeys; k++) { rotKeys[infos->nbKeyRot+k].setT(prevT + getMaratisTick(channel->mRotationKeys[k].mTime, anim->mTicksPerSecond)); *(rotKeys[infos->nbKeyRot+k].createQuaternionData()) = Quaternion( channel->mRotationKeys[k].mValue.x, channel->mRotationKeys[k].mValue.y, channel->mRotationKeys[k].mValue.z, channel->mRotationKeys[k].mValue.w ); } // scale for(k=0; k<channel->mNumScalingKeys; k++) { scaleKeys[infos->nbKeyScale+k].setT(prevT + getMaratisTick(channel->mScalingKeys[k].mTime, anim->mTicksPerSecond)); *(scaleKeys[infos->nbKeyScale+k].createVector3Data()) = Vector3( channel->mScalingKeys[k].mValue.x, channel->mScalingKeys[k].mValue.y, channel->mScalingKeys[k].mValue.z ); } infos->nbKeyPos += channel->mNumPositionKeys; infos->nbKeyRot += channel->mNumRotationKeys; infos->nbKeyScale += channel->mNumScalingKeys; } } prevT = animRanges[a].end + 1; } } } mesh->updateBoundingBox(); }