Beispiel #1
0
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();
}