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();
}
Beispiel #2
0
static void initBones(const aiScene * scene, const aiMesh * nodeMesh, Mesh * mesh, SubMesh * subMesh)
{
	Armature * armature = mesh->getArmature();
	
	BoneData bdata;
	map<unsigned int, AssimpSkinData> skinDatas;
	
	
	// bones
	for(unsigned int i=0; i<nodeMesh->mNumBones; i++)
	{
		aiBone * nodeBone = nodeMesh->mBones[i];
		
		unsigned int boneId;
		if(! armature->getBoneId(nodeBone->mName.data, &boneId))
			continue;
		
		OBone * bone = armature->getBone(boneId);
		
		aiMatrix4x4 offsetMat = nodeBone->mOffsetMatrix;
		aiTransposeMatrix4(&offsetMat);
		Matrix4x4 matrix = (*bone->getMatrix()) * Matrix4x4((float*)&offsetMat);
		
		
		// pose skinning
		Vector3 * vertices = subMesh->getVertices();
		Vector3 * normals = subMesh->getNormals();
		Vector3 * tangents = subMesh->getTangents();
		
		unsigned int w;
		for(w=0; w<nodeBone->mNumWeights; w++)
		{
			unsigned int vid = nodeBone->mWeights[w].mVertexId;
			float weight = nodeBone->mWeights[w].mWeight; 
			
			bdata.id = boneId;
			bdata.weight = weight;
			skinDatas[vid].bones.push_back(bdata);

			if(skinDatas[vid].bones.size() == 1)
			{
				if(vertices) vertices[vid] = Vector3(0, 0, 0);
				if(normals) normals[vid] = Vector3(0, 0, 0);
				if(tangents) tangents[vid] = Vector3(0, 0, 0);
			}
			
			if(vertices)
				vertices[vid] += matrix * Vector3(nodeMesh->mVertices[vid].x, nodeMesh->mVertices[vid].y, nodeMesh->mVertices[vid].z) * weight;
			
			if(normals)
				normals[vid] += matrix.getRotatedVector3(Vector3(nodeMesh->mNormals[vid].x, nodeMesh->mNormals[vid].y, nodeMesh->mNormals[vid].z)) * weight;
			
			if(tangents)
				tangents[vid] += matrix.getRotatedVector3(Vector3(nodeMesh->mTangents[vid].x, nodeMesh->mTangents[vid].y, nodeMesh->mTangents[vid].z)) * weight;
		}
	}
	
	
	// alloc skin
	unsigned int skinSize = skinDatas.size();
	if(skinSize > 0)
	{
		SkinData * skin = subMesh->createSkinData();
		SkinPoint * skinPoints = skin->allocPoints(skinSize);
		
		map<unsigned int, AssimpSkinData>::iterator
			mit (skinDatas.begin()),
			mend(skinDatas.end());
		
		unsigned int p = 0;
		for(; mit!=mend; ++mit)
		{
			unsigned int vertexId = mit->first;
			AssimpSkinData * sdata = &mit->second;
			
			unsigned int b, bSize = sdata->bones.size();
			
			if(skinPoints[p].allocateBonesLinks(bSize))
			{
				skinPoints[p].setVertexId(vertexId);
				
				unsigned short * ids = skinPoints[p].getBonesIds();
				float * weights = skinPoints[p].getBonesWeights();
				
				for(b=0; b<bSize; b++)
				{
					ids[b] = sdata->bones[b].id;
					weights[b] = sdata->bones[b].weight;
				}
			}
			
			p++;
		}
	}
}