ColladaAnimatedMesh::ColladaAnimatedMesh(FCDController * animationController )
{
	mesh = 0;
	controller = animationController;
	bool isMorph = animationController->IsMorph();
	bool isSkin = animationController->IsSkin();

	if (isSkin)
	{
		FCDSkinController * skinController = animationController->GetSkinController();
		int jointCount = skinController->GetJointCount();
		FCDSkinControllerJoint * origJoints = skinController->GetJoints();

		joints.resize(jointCount);
		for (int j = 0; j < jointCount;  ++j)
		{
			joints[j].joint = &origJoints[j];
			joints[j].parentJoint = 0;
			joints[j].node = 0;
			joints[j].index = j;
			joints[j].parentIndex = -1;
		
			FMMatrix44 bindPoseInverse = joints[j].joint->GetBindPoseInverse();
			joints[j].colladaInverse0 = bindPoseInverse;
			joints[j].inverse0 = ConvertMatrix(joints[j].colladaInverse0);
			
			printf("%s, ", joints[j].joint->GetId().c_str());
		}

		colladaBindShapeMatrix = skinController->GetBindShapeTransform();
		bindShapeMatrix = ConvertMatrix(colladaBindShapeMatrix);
		
		printf("- controller: %s influence: %ld influence-entity: %s\n", animationController->GetDaeId().c_str(), skinController->GetInfluenceCount(), skinController->GetTarget()->GetDaeId().c_str());

		vertexWeights.resize(skinController->GetInfluenceCount());
		int maxJoints = 0;
		for (int index = 0; index < (int)skinController->GetInfluenceCount(); ++index)
		{
			FCDSkinControllerVertex * vert = skinController->GetVertexInfluence(index);
			vertexWeights[index].jointCount = 0;
			for (int pp = 0; pp < (int)vert->GetPairCount(); ++pp)
			{
				FCDJointWeightPair * jointWeightPar = vert->GetPair(pp);
				
				vertexWeights[index].AddWeight(jointWeightPar->jointIndex, jointWeightPar->weight);
			}
			if (vertexWeights[index].jointCount > maxJoints)
				maxJoints = vertexWeights[index].jointCount;

			vertexWeights[index].Normalize();
		}
		printf("- max joints: %d\n", maxJoints);
		
		mesh = new ColladaMesh( animationController->GetBaseGeometry()->GetMesh(), &(vertexWeights.front()));
	}
}
예제 #2
0
	bool CheckControllerSkin(FULogFile& fileOut, FCDSkinController* controller)
	{
		FailIf(controller == NULL);

		// Check the base target's identity
		FailIf(controller->GetTarget() == NULL);
		PassIf(controller->GetTarget()->GetType() == FCDEntity::GEOMETRY);
		PassIf(controller->GetTarget()->GetDaeId() == meshId);

		// Retrieve the two joints and verify their ids/bind-pose.
		PassIf(controller->GetJointCount() == 2);
		const FMMatrix44* joint1 = NULL,* joint2 = NULL;
		for (size_t i = 0; i < 2; ++i)
		{
			FCDSkinControllerJoint* joint = controller->GetJoint(i);
			if (joint->GetId() == jointId1) { FailIf(joint1 != NULL); joint1 = &joint->GetBindPoseInverse(); }
			else if (joint->GetId() == jointId2) { FailIf(joint2 != NULL); joint2 = &joint->GetBindPoseInverse(); }
			else Fail;
		}
		FailIf(joint1 == NULL || joint2 == NULL);
		PassIf(IsEquivalent(*joint1, FMMatrix44::Identity));
		FMMatrix44 sbp = FMMatrix44(sampleBindPose1).Inverted();
		PassIf(IsEquivalent(*joint2, FMMatrix44(sampleBindPose1).Inverted()));

		// Verify the influences
		PassIf(controller->GetInfluenceCount() == 4);
		FCDSkinControllerVertex* influence = controller->GetVertexInfluence(0);
		FailIf(influence == NULL);
		PassIf(influence->GetPairCount() == 2);
		PassIf(IsEquivalent(influence->GetPair(0)->jointIndex, 0));
		PassIf(IsEquivalent(influence->GetPair(0)->weight, 0.5f));
		PassIf(IsEquivalent(influence->GetPair(1)->jointIndex, 1));
		PassIf(IsEquivalent(influence->GetPair(1)->weight, 0.5f));

		influence = controller->GetVertexInfluence(1);
		FailIf(influence == NULL);
		PassIf(influence->GetPairCount() == 0);

		influence = controller->GetVertexInfluence(2);
		FailIf(influence == NULL);
		PassIf(influence->GetPairCount() == 1);
		PassIf(IsEquivalent(influence->GetPair(0)->jointIndex, 0));
		PassIf(IsEquivalent(influence->GetPair(0)->weight, 1.0f)); // the weight should have been normalized.

		influence = controller->GetVertexInfluence(3);
		FailIf(influence == NULL);
		PassIf(influence->GetPairCount() == 1);
		PassIf(IsEquivalent(influence->GetPair(0)->jointIndex, 1));
		PassIf(IsEquivalent(influence->GetPair(0)->weight, 1.0f));
		return true;
	}
예제 #3
0
	bool FillControllerSkin(FULogFile& fileOut, FCDSkinController* controller)
	{
		FailIf(controller == NULL);

		// Create two joints.
		FCDSceneNode* visualScene = controller->GetDocument()->GetVisualSceneLibrary()->AddEntity();
		PassIf(visualScene != NULL);
		FCDSceneNode* joint1 = visualScene->AddChildNode();
		PassIf(joint1 != NULL);
		FCDSceneNode* joint2 = joint1->AddChildNode();
		PassIf(joint2 != NULL);
		// In the standard course of operations, we would either load a file
		// with subId Info, or link it in when loading the instance.  Here we have no instance
		fm::string jid1("joint1");
		fm::string jid2("joint2");
		joint1->SetSubId(jid1);
		joint2->SetSubId(jid2);
		jointId1 = joint1->GetSubId();
		jointId2 = joint2->GetSubId();
		FailIf(jointId1.empty() || jointId2.empty());
		controller->AddJoint(joint1->GetSubId(), FMMatrix44::Identity);
		controller->AddJoint(joint2->GetSubId(), FMMatrix44(sampleBindPose1).Inverted());
		controller->SetBindShapeTransform(FMMatrix44(sampleBindPose2));
		PassIf(controller->GetJointCount() == 2);

		// Retrieve and assign the base target
		FCDGeometry* geometricTarget = controller->GetDocument()->FindGeometry(meshId);
		controller->SetTarget(geometricTarget);

		// Set some influences
		PassIf(controller->GetInfluenceCount() == 4);
		FCDSkinControllerVertex* influence = controller->GetVertexInfluence(0);
		FailIf(influence == NULL);
		influence->AddPair(0, 0.5f);
		influence->AddPair(1, 0.5f);

		influence = controller->GetVertexInfluence(3);
		FailIf(influence == NULL);
		influence->AddPair(1, 1.0f);

		influence = controller->GetVertexInfluence(2);
		FailIf(influence == NULL);
		influence->AddPair(0, 0.1f);
		return true;
	}
예제 #4
0
void ColladaMeshFactory::GenerateMeshDatafromPolygonsFull(	
	RevModel** aModel,
	RevIndexData& aIndexData,
	RevVertexDataNormal& aVertexData,
	RevInputData& aInputData,
	FCDGeometryInstance* aInstance,
	FCDGeometryMesh* aMesh,
	FCDocument* aColladaDocument,
	bool aHasBoneWeightsFlag,
	FCDController* aController,
	FCDControllerInstance* aControllerInstance)
{
	int polygonalMeshes= static_cast<int>(aMesh->GetPolygonsCount());

	//	assert(polygonalMeshes==1); // how to handle multiple meshes ? handle later

	// To do add support for multiple meshes ?

	FCDSkinController* skinControl=NULL;
	if(aHasBoneWeightsFlag==true)
	{
		skinControl=aController->GetSkinController();
		skinControl->ReduceInfluences(4);
	}

	int myVertexCount=0;
	int duplicatesCount=0;
	int currentIndex=0;

	std::map<RevVertexIndexmapKey,int> vertexList;
	std::map<RevVertexIndexmapKey,int>::iterator vertexIterator;
	std::vector<RevVertexIndexmapKey> vertexes;

	aIndexData.myNrOfIndexes =0;
	aIndexData.myFormat =DXGI_FORMAT_R32_UINT;
	for(int polygonMeshIndex=0;polygonMeshIndex<static_cast<int>(polygonalMeshes);polygonMeshIndex++)
	{
		FCDGeometryPolygons* somePolygons=aMesh->GetPolygons(polygonMeshIndex);
		FCDGeometryPolygonsInput* positionInput=somePolygons->FindInput(FUDaeGeometryInput::POSITION);
		aIndexData.myNrOfIndexes+=positionInput->GetIndexCount();

	}

	aIndexData.mySize=aIndexData.myNrOfIndexes*sizeof(unsigned int);

	aIndexData.myIndexData = new char [aIndexData.mySize] ();
	UINT* indexArray=reinterpret_cast<unsigned int*>(aIndexData.myIndexData);

	FCDGeometrySource* positionSource=aMesh->FindSourceByType(FUDaeGeometryInput::POSITION);
	FCDGeometrySource* normalSource=aMesh->FindSourceByType(FUDaeGeometryInput::NORMAL);
	FCDGeometrySource* colorSource=aMesh->FindSourceByType(FUDaeGeometryInput::COLOR);
	FCDGeometrySource* textureCordinatesSource=aMesh->FindSourceByType(FUDaeGeometryInput::TEXCOORD);
	FCDGeometrySource* geoTangentSource=aMesh->FindSourceByType(FUDaeGeometryInput::GEOTANGENT);
	FCDGeometrySource* texTangentSource=aMesh->FindSourceByType(FUDaeGeometryInput::TEXTANGENT);
	FCDGeometrySource* geoBiNormalSource=aMesh->FindSourceByType(FUDaeGeometryInput::GEOBINORMAL);
	FCDGeometrySource* texBiNormalSource=aMesh->FindSourceByType(FUDaeGeometryInput::TEXBINORMAL);


	RevModelRenderEssentials renderEssentials( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

	SelectEffectOnModel(aModel, aInputData);

	RevTextures tex;

	for(int polygonMeshIndex=0;polygonMeshIndex<polygonalMeshes;polygonMeshIndex++)
	{	
		(*aModel)->SetIsNullObjectFlag( false );
		FCDGeometryPolygons* somePolygons=aMesh->GetPolygons(polygonMeshIndex);

		FCDGeometryPolygonsInput* positionInput=somePolygons->FindInput(FUDaeGeometryInput::POSITION);
		FCDGeometryPolygonsInput* normalInput=somePolygons->FindInput(FUDaeGeometryInput::NORMAL);
		FCDGeometryPolygonsInput* colorInput=somePolygons->FindInput(FUDaeGeometryInput::COLOR);
		FCDGeometryPolygonsInput* texCoordInput=somePolygons->FindInput(FUDaeGeometryInput::TEXCOORD);
		FCDGeometryPolygonsInput* geoTangentInput=somePolygons->FindInput(FUDaeGeometryInput::GEOTANGENT);
		FCDGeometryPolygonsInput* texTangentInput=somePolygons->FindInput(FUDaeGeometryInput::TEXTANGENT);
		FCDGeometryPolygonsInput* geoBiNormalInput=somePolygons->FindInput(FUDaeGeometryInput::GEOBINORMAL);
		FCDGeometryPolygonsInput* texBiNormalInput=somePolygons->FindInput(FUDaeGeometryInput::TEXBINORMAL);

		somePolygons->GetFaceVertexCount();


		renderEssentials.myVertexStart = 0;
		renderEssentials.myIndexStart = currentIndex;
		renderEssentials.myIndexCount = positionInput->GetIndexCount();

		for(int i=0;i<static_cast<int>(positionInput->GetIndexCount());i++)
		{
			RevVertexIndexmapKey key;
			if(positionInput!=NULL)
			{
				key.myKeys[0]=positionInput->GetIndices()[i];
			}
			if(normalInput!=NULL)
			{
				key.myKeys[1]=normalInput->GetIndices()[i];
			}
			if(colorInput!=NULL)
			{
				key.myKeys[2]=colorInput->GetIndices()[i];
			}
			if(texCoordInput!=NULL)
			{
				key.myKeys[3]=texCoordInput->GetIndices()[i];
			}
			if(geoTangentInput!=NULL)
			{
				key.myKeys[4]=geoTangentInput->GetIndices()[i];
			}
			if(texTangentInput!=NULL)
			{
				key.myKeys[5]=texTangentInput->GetIndices()[i];
			}

			if(geoBiNormalInput!=NULL)
			{
				key.myKeys[6]=geoBiNormalInput->GetIndices()[i];
			}

			if(texBiNormalInput!=NULL)
			{
				key.myKeys[7]=texBiNormalInput->GetIndices()[i];
			}


			vertexIterator=vertexList.find(key);
			if(vertexIterator==vertexList.end())
			{
				indexArray[currentIndex]=myVertexCount;
				std::pair<RevVertexIndexmapKey,int> tempPair(key,myVertexCount);
				vertexList.insert(tempPair);
				vertexes.push_back(key);
				myVertexCount++;
				// create indexes
			}
			else
			{
				indexArray[currentIndex]=(*vertexIterator).second;
				duplicatesCount++;
				// Read Created Vertex
			}
			currentIndex++;
		}

		for (unsigned int k=0; k<aInstance->GetMaterialInstanceCount(); k++) 
		{
			FCDMaterialInstance* materialInstance;
			materialInstance=aInstance->GetMaterialInstance(k);
			if(aMesh->GetPolygons(polygonMeshIndex)->GetMaterialSemantic()==materialInstance->GetSemantic())
			{
				LoadMaterialNew(polygonMeshIndex,materialInstance->GetMaterial(),aColladaDocument, tex);
			}
		}
	}

	(*aModel)->SetModelTextures( tex );


	aVertexData.myNrOfVertexes=myVertexCount;
	aVertexData.mySize=aVertexData.myStride*aVertexData.myNrOfVertexes;
	aVertexData.myVertexData =new char [aVertexData.mySize] ();

	for(int i=0;i<aIndexData.myNrOfIndexes;i+=3)
	{
		unsigned int temp;	
		temp=indexArray[i+0];
		indexArray[i+0]=indexArray[i+2];
		indexArray[i+2]=temp;
	}

	myVertexCount=0;
	for(int i=0;i<static_cast<int>(vertexes.size());i++)
	{
		RevVertexIndexmapKey key=vertexes[i];

		int offset=0;
		std::pair<RevVertexIndexmapKey,int> tempPair(key,myVertexCount);
		vertexList.insert(tempPair);

		// Create Vertex
		if(key.myKeys[0]!=-1)
		{
			CU::Vector3f pos;
			memcpy(&pos,
				&positionSource->GetData()[key.myKeys[0]*positionSource->GetStride()],12);

			//			pos.y=-pos.y;
			//			pos.z=-pos.z;
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&pos,12);

			offset+=12;
		}
		if(aHasBoneWeightsFlag==true)
		{
			assert(key.myKeys[0]!=-1);
			FCDSkinControllerVertex* vertexsInfluence;

			vertexsInfluence=skinControl->GetVertexInfluence(key.myKeys[0]);

			int boneData=0;
			int weightData=0;

			assert(vertexsInfluence->GetPairCount()<=4);
			for(int j=0;j<static_cast<int>(vertexsInfluence->GetPairCount());j++)
			{
				assert(j<4);
				FCDJointWeightPair* pair=vertexsInfluence->GetPair(j);

				assert(pair->jointIndex<256);
				boneData |= pair->jointIndex << (j*8);

				int weight=static_cast<int>((pair->weight*255.0f+0.5));
				assert(weight>=0);
				assert(weight<=255);
				weightData |= weight << (j*8);
			}
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],&weightData,4);
			offset+=4;
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],&boneData,4);
			offset+=4;

		}
		if(key.myKeys[1]!=-1)
		{
			CU::Vector3f normal;
			memcpy(&normal,
				&normalSource->GetData()[key.myKeys[1]*normalSource->GetStride()],12);

			//			normal.y=-normal.y;
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&normal,12);
			offset+=12;
		}
		if(key.myKeys[2]!=-1)
		{
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&colorSource->GetData()[key.myKeys[2]*colorSource->GetStride()],16);
			offset+=16;
		}
		if(key.myKeys[3]!=-1)
		{
			CU::Vector2f UV;
			memcpy(&UV,
				&textureCordinatesSource->GetData()[key.myKeys[3]*textureCordinatesSource->GetStride()],8);

			UV.v=1.0f-UV.v;




			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&UV,8);
			offset+=8;
		}
		if(key.myKeys[4]!=-1)
		{
			CU::Vector3f tangent;
			memcpy(&tangent,
				&geoTangentSource->GetData()[key.myKeys[4]*geoTangentSource->GetStride()],12);
			//			tangent.y=-tangent.y;
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&tangent,12);
			offset+=12;
		}
		if(key.myKeys[5]!=-1)
		{
			CU::Vector3f tangent;
			memcpy(&tangent,
				&texTangentSource->GetData()[key.myKeys[5]*texTangentSource->GetStride()],12);
			//			tangent.y=-tangent.y;
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&tangent,12);
			offset+=12;
		}

		if(key.myKeys[6]!=-1)
		{
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&geoBiNormalSource->GetData()[key.myKeys[6]*geoBiNormalSource->GetStride()],12);
			offset+=12;
		}
		if(key.myKeys[7]!=-1)
		{
			memcpy(&aVertexData.myVertexData[myVertexCount*aVertexData.myStride+offset],
				&texBiNormalSource->GetData()[key.myKeys[7]*texBiNormalSource->GetStride()],12);
			offset+=12;
		}

		myVertexCount++;
	}
	if( (*aModel)->Init( aVertexData, aIndexData, aInputData, renderEssentials ) ==false)
	{
		assert(0 && "Something went wrong in trying to init the current model");
	}
}
예제 #5
0
파일: GeomReindex.cpp 프로젝트: 2asoft/0ad
void ReindexGeometry(FCDGeometryPolygons* polys, FCDSkinController* skin)
{
	// Given geometry with:
	//   positions, normals, texcoords, bone blends
	// each with their own data array and index array, change it to
	// have a single optimised index array shared by all vertexes.

	FCDGeometryPolygonsInput* inputPosition = polys->FindInput(FUDaeGeometryInput::POSITION);
	FCDGeometryPolygonsInput* inputNormal   = polys->FindInput(FUDaeGeometryInput::NORMAL);
	FCDGeometryPolygonsInput* inputTexcoord = polys->FindInput(FUDaeGeometryInput::TEXCOORD);

	size_t numVertices = polys->GetFaceVertexCount();

	assert(inputPosition->GetIndexCount() == numVertices);
	assert(inputNormal  ->GetIndexCount() == numVertices);
	assert(inputTexcoord->GetIndexCount() == numVertices);

	const uint32* indicesPosition = inputPosition->GetIndices();
	const uint32* indicesNormal   = inputNormal->GetIndices();
	const uint32* indicesTexcoord = inputTexcoord->GetIndices();

	assert(indicesPosition);
	assert(indicesNormal);
	assert(indicesTexcoord); // TODO - should be optional, because textureless meshes aren't unreasonable

	FCDGeometrySourceList texcoordSources;
	polys->GetParent()->FindSourcesByType(FUDaeGeometryInput::TEXCOORD, texcoordSources);

	FCDGeometrySource* sourcePosition = inputPosition->GetSource();
	FCDGeometrySource* sourceNormal   = inputNormal  ->GetSource();

	const float* dataPosition = sourcePosition->GetData();
	const float* dataNormal   = sourceNormal  ->GetData();

	if (skin)
	{
#ifndef NDEBUG
		size_t numVertexPositions = sourcePosition->GetDataCount() / sourcePosition->GetStride();
		assert(skin->GetInfluenceCount() == numVertexPositions);
#endif
	}

	uint32 stridePosition = sourcePosition->GetStride();
	uint32 strideNormal   = sourceNormal  ->GetStride();

	std::vector<uint32> indicesCombined;
	std::vector<VertexData> vertexes;
	InserterWithoutDuplicates<VertexData> inserter(vertexes);

	for (size_t i = 0; i < numVertices; ++i)
	{
		std::vector<FCDJointWeightPair> weights;
		if (skin)
		{
			FCDSkinControllerVertex* influences = skin->GetVertexInfluence(indicesPosition[i]);
			assert(influences != NULL);
			for (size_t j = 0; j < influences->GetPairCount(); ++j)
			{
				FCDJointWeightPair* pair = influences->GetPair(j);
				assert(pair != NULL);
				weights.push_back(*pair);
			}
			CanonicaliseWeights(weights);
		}

		std::vector<uv_pair_type> uvs;
		for (size_t set = 0; set < texcoordSources.size(); ++set)
		{
			const float* dataTexcoord = texcoordSources[set]->GetData();
			uint32 strideTexcoord = texcoordSources[set]->GetStride();

			uv_pair_type p;
			p.first = dataTexcoord[indicesTexcoord[i]*strideTexcoord];
			p.second = dataTexcoord[indicesTexcoord[i]*strideTexcoord + 1];
			uvs.push_back(p);
		}

		VertexData vtx (
			&dataPosition[indicesPosition[i]*stridePosition],
			&dataNormal  [indicesNormal  [i]*strideNormal],
			uvs,
			weights
		);
		size_t idx = inserter.add(vtx);
		indicesCombined.push_back((uint32)idx);
	}

	// TODO: rearrange indicesCombined (and rearrange vertexes to match) to use
	// the vertex cache efficiently
	// (<http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html> etc)

	FloatList newDataPosition;
	FloatList newDataNormal;
	FloatList newDataTexcoord;
	std::vector<std::vector<FCDJointWeightPair> > newWeightedMatches;

	for (size_t i = 0; i < vertexes.size(); ++i)
	{
		newDataPosition.push_back(vertexes[i].x);
		newDataPosition.push_back(vertexes[i].y);
		newDataPosition.push_back(vertexes[i].z);
		newDataNormal  .push_back(vertexes[i].nx);
		newDataNormal  .push_back(vertexes[i].ny);
		newDataNormal  .push_back(vertexes[i].nz);
		newWeightedMatches.push_back(vertexes[i].weights);
	}

	// (Slightly wasteful to duplicate this array so many times, but FCollada
	// doesn't seem to support multiple inputs with the same source data)
	inputPosition->SetIndices(&indicesCombined.front(), indicesCombined.size());
	inputNormal  ->SetIndices(&indicesCombined.front(), indicesCombined.size());
	inputTexcoord->SetIndices(&indicesCombined.front(), indicesCombined.size());

	for (size_t set = 0; set < texcoordSources.size(); ++set)
	{
		newDataTexcoord.clear();
		for (size_t i = 0; i < vertexes.size(); ++i)
		{
			newDataTexcoord.push_back(vertexes[i].uvs[set].first);
			newDataTexcoord.push_back(vertexes[i].uvs[set].second);
		}
		texcoordSources[set]->SetData(newDataTexcoord, 2);
	}

	sourcePosition->SetData(newDataPosition, 3);
	sourceNormal  ->SetData(newDataNormal,   3);

	if (skin)
	{
		skin->SetInfluenceCount(newWeightedMatches.size());
		for (size_t i = 0; i < newWeightedMatches.size(); ++i)
		{
			skin->GetVertexInfluence(i)->SetPairCount(0);
			for (size_t j = 0; j < newWeightedMatches[i].size(); ++j)
				skin->GetVertexInfluence(i)->AddPair(newWeightedMatches[i][j].jointIndex, newWeightedMatches[i][j].weight);
		}
	}
}