Esempio n. 1
0
		void FbxLoader::ComputeNodeMatrix(FbxNode* node, Node& meshNode, bool local)
		{
			if(!node)
				return;
			FbxAnimEvaluator* evaluator = scene->GetAnimationEvaluator();
			FbxAMatrix global;
			global.SetIdentity();

			FbxTime time;
			time.SetSecondDouble(0.0);
			
			if(node != scene->GetRootNode()) {
				if(local) {
					global = evaluator->GetNodeLocalTransform(node, time);
				}
				else {
					global = evaluator->GetNodeGlobalTransform(node, time);
				}
			}
			auto T = global.GetT() * factor;
			
			if(axismode == eLeftHanded) {
				auto R = global.GetR();
				R[1] *= -1; R[2] *= -1;
				T[0] *= -1;
				global.SetR(R);
			}
			global.SetT(T);

			meshNode.matrix = Matrix(
				(float)global[0][0], (float)global[0][1], (float)global[0][2], (float)global[0][3],
				(float)global[1][0], (float)global[1][1], (float)global[1][2], (float)global[1][3],
				(float)global[2][0], (float)global[2][1], (float)global[2][2], (float)global[2][3],
				(float)global[3][0], (float)global[3][1], (float)global[3][2], (float)global[3][3]);
		}
FbxAMatrix	LoaderFbxMesh::parseTransformMatrixOther(FbxCluster* cluster, FbxMesh* mesh, FbxPose* fbxPose, FbxAMatrix globalPosition)
{
	FbxAMatrix referenceGeometry;
	FbxAMatrix referenceGlobalInitPosition;
	FbxAMatrix referenceGlobalCurrentPosition;

	FbxAMatrix clusterGeometry;
	FbxAMatrix clusterGlobalInitPosition;
	FbxAMatrix clusterGlobalCurrentPosition;

	FbxAMatrix clusterRelativeInitPosition;
	FbxAMatrix clusterRelativeCurrentPositionInverse;

	FbxTime time(0);

	FbxAMatrix fbxMatrixIdentity;
	fbxMatrixIdentity.SetIdentity();

	cluster->GetTransformMatrix(referenceGlobalInitPosition);
	referenceGlobalCurrentPosition = globalPosition;
	referenceGeometry = getGeometry(mesh->GetNode());
	referenceGlobalInitPosition *= referenceGeometry;

	cluster->GetTransformLinkMatrix(clusterGlobalInitPosition);
	clusterGlobalCurrentPosition = getGlobalPosition(cluster->GetLink(), time, fbxPose, nullptr);

	clusterRelativeInitPosition = clusterGlobalInitPosition.Inverse() * referenceGlobalInitPosition;
	clusterRelativeCurrentPositionInverse = referenceGlobalCurrentPosition.Inverse() * clusterGlobalCurrentPosition;
	
	FbxAMatrix offsetMatrix;
	offsetMatrix = clusterRelativeCurrentPositionInverse * clusterRelativeInitPosition;
	
	return offsetMatrix;
}
Esempio n. 3
0
FbxMatrix FBXScene::GetGeometricOffset2(FbxNode* pNode)
{
	if( !pNode )
	{
		FbxAMatrix mat;
		mat.SetIdentity();
		return mat;
	}

	// CheckMe: E Source Set = E Source Pivot?
	FbxVector4 T = pNode->GetGeometricTranslation(FbxNode::eSourcePivot);
	FbxVector4 R = pNode->GetGeometricRotation(FbxNode::eSourcePivot);
	FbxVector4 S = pNode->GetGeometricScaling(FbxNode::eSourcePivot);

	FbxAMatrix matFBXGeometryOffset;
	matFBXGeometryOffset.SetIdentity();
	matFBXGeometryOffset.SetTRS(T,R,S);

	return matFBXGeometryOffset;
}
Esempio n. 4
0
MeshData* FBXImporter::GetMeshInfo()
{
	mMeshData = new MeshData();

	int indicesIndexOffset = 0;		// 记录当前mesh在整个ib中的索引位移。
	int verticesIndexOffset = 0;	// 记录当前mesh在整个vb中的顶点位移。

	for (int meshIndex = 0; meshIndex < mFBXMeshDatas.size(); meshIndex++)
	{
		FbxMesh* mesh = mFBXMeshDatas[meshIndex]->mMesh;
		FBXMeshData* fbxMeshData = mFBXMeshDatas[meshIndex];
		fbxMeshData->mVerticesCount = mesh->GetControlPointsCount();
		fbxMeshData->mIndicesCount = mesh->GetPolygonVertexCount();
		fbxMeshData->mTrianglesCount = mesh->GetPolygonCount();

		// 获取3dsmax中的全局变换矩阵,稍后可以在DX中还原。
		FbxMatrix gloableTransform = mesh->GetNode()->EvaluateGlobalTransform();

		FbxAMatrix matrixGeo;
		matrixGeo.SetIdentity();

		const FbxVector4 lT = mesh->GetNode()->GetGeometricTranslation(FbxNode::eSourcePivot);
		const FbxVector4 lR = mesh->GetNode()->GetGeometricRotation(FbxNode::eSourcePivot);
		const FbxVector4 lS = mesh->GetNode()->GetGeometricScaling(FbxNode::eSourcePivot);

		matrixGeo.SetT(lT);
		matrixGeo.SetR(lR);
		matrixGeo.SetS(lS);

		FbxAMatrix matrixL2W;
		matrixL2W.SetIdentity();

		matrixL2W = mesh->GetNode()->EvaluateGlobalTransform();

		matrixL2W *= matrixGeo;

		XMMATRIX globalTransform = XMLoadFloat4x4(&fbxMeshData->globalTransform);
		FbxMatrixToXMMATRIX(globalTransform, matrixL2W);
		XMStoreFloat4x4(&fbxMeshData->globalTransform, globalTransform);

		// 读取顶点。
		ReadVertices(fbxMeshData);
		// 读取索引。
		ReadIndices(fbxMeshData);

		// 先读取网格对应的材质索引信息,以便优化稍后纹理读取。
		// 一个网格可能只对应一个materialId,也可能对应多个materialId(3dsmax里的Multi/Sub-Object材质)。
		// 如果只对应一个材质,简单的读取就行,不过普遍情况可能是为了优化渲染合并mesh从而拥有多材质。
		// 这个函数调用完毕我们会得到materialId和拥有这个materialId的三角形列表(三角形编号列表),保存在vector<MaterialIdOffset>的容器中。
		//struct Material
		//{
		//	Material() {}
		//	Material(int id, string diffuse, string normalMap)
		//		: materialId(id),
		//		diffuseTextureFile(diffuse),
		//		normalMapTextureFile(normalMap)
		//	{}
		//
		//	int materialId;
		//	string diffuseTextureFile;
		//	string normalMapTextureFile;
		//};
		// struct MaterialIdOffset
		//{
		//	MaterialIdOffset()
		//		: polygonCount(0)
		//	{}
		//	int polygonCount;
		//	Material material;
		//};
		ConnectMaterialsToMesh(mesh, fbxMeshData->mTrianglesCount);

		// 根据ConnectMaterialsToMesh得到的信息读取材质纹理信息,同样存入vector<MaterialIdOffset>容器。
		LoadMaterials(fbxMeshData);

		int triangleCount = mesh->GetPolygonCount();
		int controlPointIndex = 0;
		int normalIndex = 0;
		fbxMeshData->mUVs.resize(fbxMeshData->mIndicesCount, XMFLOAT2(-1.0f, -1.0f));

		// Extract normals and uvs from FbxMesh.
		for (int i = 0; i < triangleCount; i++)
		{
			int polygonSize = mesh->GetPolygonSize(i);

			for (int j = 0; j < polygonSize; j++)
			{ 
				controlPointIndex = mesh->GetPolygonVertex(i, j);

				ReadNormals(fbxMeshData, controlPointIndex, normalIndex);

				// 有纹理我们才读取uv,tangent以及binormal。
				if (fbxMeshData->hasDiffuseTexture())
				{
					ReadUVs(fbxMeshData, controlPointIndex, normalIndex, mesh->GetTextureUVIndex(i, j), 0);
					ReadTangents(fbxMeshData, controlPointIndex, normalIndex);
					ReadBinormals(fbxMeshData, controlPointIndex, normalIndex);
				}

				normalIndex++;
			}
		}

		SplitVertexByNormal(fbxMeshData);

		if (fbxMeshData->hasDiffuseTexture())
		{
			SplitVertexByUV(fbxMeshData);
		}
		else
		{
			fbxMeshData->mUVs.resize(fbxMeshData->mVerticesCount);
		}

		if (fbxMeshData->hasNormalMapTexture())
		{
			SplitVertexByTangent(fbxMeshData);
			SplitVertexByBinormal(fbxMeshData);
		}
		else
		{
			fbxMeshData->mTangents.resize(fbxMeshData->mVerticesCount);
			fbxMeshData->mBinormals.resize(fbxMeshData->mVerticesCount);
		}

		// 如果.fbx包含一个以上的mesh,需要计算当前FBXMeshData的索引在全局索引中的位置。
		for (int i = 0; i < fbxMeshData->mIndicesCount; i++)
		{
			fbxMeshData->mIndices[i] = fbxMeshData->mIndices[i] + verticesIndexOffset;
		}

		mMeshData->verticesCount += fbxMeshData->mVerticesCount;
		mMeshData->indicesCount += fbxMeshData->mIndicesCount;
		mMeshData->meshesCount++;

		// 多材质的情况。
		// 根据之前填充的materialIdOffsets容器保存的materialId和三角形的对应关系,
		// 计算每个RenderPackage渲染所需的索引数量和索引起始位置(偏移)。
		if (isByPolygon && fbxMeshData->hasDiffuseTexture())
		{
			vector<MaterialIdOffset> materialIdOffsets = mMeshData->materialIdOffsets;

			for (int i = 0; i < materialIdOffsets.size(); i++)
			{
				RenderPackage renderPacakge;
				renderPacakge.globalTransform = fbxMeshData->globalTransform;
				renderPacakge.indicesCount = materialIdOffsets[i].polygonCount * 3;
	
				if (i == 0)
				{
					renderPacakge.indicesOffset = indicesIndexOffset;
				}
				else
				{
					renderPacakge.indicesOffset += indicesIndexOffset;
				}

				renderPacakge.material = materialIdOffsets[i].material;

				mMeshData->renderPackages.push_back(renderPacakge);

				indicesIndexOffset += renderPacakge.indicesCount;
			}
		}
		else
		// 单一材质的情况。
		{
			RenderPackage renderPackage;
			renderPackage.indicesCount = fbxMeshData->mIndicesCount;
			renderPackage.indicesOffset = indicesIndexOffset;
			renderPackage.material = fbxMeshData->mMaterial;
			renderPackage.globalTransform = fbxMeshData->globalTransform;

			mMeshData->renderPackages.push_back(renderPackage);

			indicesIndexOffset += fbxMeshData->mIndices.size();
		}

		verticesIndexOffset += fbxMeshData->mVertices.size();

		// 将当前mesh的数据追加到全局数据容器。
		Merge(mMeshData->vertices, fbxMeshData->mVertices);
		Merge(mMeshData->indices, fbxMeshData->mIndices);
		Merge(mMeshData->normals, fbxMeshData->mNormals);
		Merge(mMeshData->uvs, fbxMeshData->mUVs);
		Merge(mMeshData->tangents, fbxMeshData->mTangents);
		Merge(mMeshData->binormals, fbxMeshData->mBinormals);

		mMeshData->materialIdOffsets.clear();
	}

	clear();

	return mMeshData;
}
Esempio n. 5
0
// Deform the vertex array in classic linear way.
void fbxLoader2::ComputeLinearDeformation(FbxAMatrix& pGlobalPosition, FbxMesh* pMesh,  FbxTime& pTime, FbxPose* pPose, int frame)
{
	// All the links must have the same link mode.
	FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();

	int lVertexCount = pMesh->GetControlPointsCount();
	FbxAMatrix* lClusterDeformation = new FbxAMatrix[lVertexCount];
	memset(lClusterDeformation, 0, lVertexCount * sizeof(FbxAMatrix));

	double* lClusterWeight = new double[lVertexCount];
	memset(lClusterWeight, 0, lVertexCount * sizeof(double));

	if (lClusterMode == FbxCluster::eAdditive)
	{
		for (int i = 0; i < lVertexCount; ++i)
		{
			lClusterDeformation[i].SetIdentity();
		}
	}

	// For all skins and all clusters, accumulate their deformation and weight
	// on each vertices and store them in lClusterDeformation and lClusterWeight.
	int lSkinCount = pMesh->GetDeformerCount(FbxDeformer::eSkin);
	for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex)
	{
		FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
		
		int lClusterCount = lSkinDeformer->GetClusterCount();
		for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex)
		{
			FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
			if (!lCluster->GetLink())
				continue;

			FbxAMatrix lVertexTransformMatrix;

			ComputeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose, frame);

			//lVertexTransformMatrix.Transpose();
			FbxAMatrix identityM;
			identityM.SetIdentity();

			FbxVector4 rotation = lVertexTransformMatrix.GetROnly();
			FbxVector4 translation = lVertexTransformMatrix.GetT();
			FbxVector4 scaling = lVertexTransformMatrix.GetS();

			//rotation = FbxVector4(rotation.mData[0], rotation.mData[1], rotation.mData[2], rotation.mData[3]);
			//translation = FbxVector4 (translation.mData[0], translation.mData[1], translation.mData[2], translation.mData[3]);
			//scaling = FbxVector4 (scaling.mData[0], scaling.mData[1], scaling.mData[2], scaling.mData[3]);

			//lVertexTransformMatrix = FbxAMatrix(translation, rotation, scaling);			
			//lVertexTransformMatrix = FbxAMatrix(translation, rotation, scaling);	


			identityM = lVertexTransformMatrix * identityM;

			D3DXMATRIX convert = D3DXMATRIX(1,0,0,0,
											0,0,1,0,
											0,1,0,0,
											0,0,0,1);

			D3DXMATRIX setMatrix = D3DXMATRIX(	(float)identityM.mData[0].mData[0], (float)identityM.mData[1].mData[0], (float)identityM.mData[2].mData[0], (float)identityM.mData[3].mData[0],
												(float)identityM.mData[0].mData[1], (float)identityM.mData[1].mData[1], (float)identityM.mData[2].mData[1], (float)identityM.mData[3].mData[1],
												(float)identityM.mData[0].mData[2], (float)identityM.mData[1].mData[2], (float)identityM.mData[2].mData[2], (float)identityM.mData[3].mData[2],
												(float)identityM.mData[0].mData[3], (float)identityM.mData[1].mData[3], (float)identityM.mData[2].mData[3],1);

			//setMatrix *=0.5f;

			setMatrix = D3DXMATRIX(	(float)identityM.mData[0].mData[0], (float)identityM.mData[1].mData[0], (float)identityM.mData[2].mData[0], (float)identityM.mData[3].mData[0],
									(float)identityM.mData[0].mData[1], (float)identityM.mData[1].mData[1], (float)identityM.mData[2].mData[1], (float)identityM.mData[3].mData[1],
									//(float)identityM.mData[0].mData[2], (float)identityM.mData[1].mData[2], (float)identityM.mData[2].mData[2], (float)identityM.mData[3].mData[1],
									(float)identityM.mData[0].mData[2], (float)identityM.mData[1].mData[2], (float)identityM.mData[2].mData[2], (float)identityM.mData[3].mData[2],
									(float)identityM.mData[0].mData[3], (float)identityM.mData[1].mData[3], (float)identityM.mData[2].mData[3], 1);

			//setMatrix = setMatrix*convert;

			///////// juz prawie dziala. sprawdz jeszcze te addytywne itp.
			/// generalnie dodaj to do włosów i dorzuć poprzednią macierz, żeby liczyć przesunięcia.


			//setMatrix /= 2.54f; //skala jedna jest w cm, druga w inchach, nieważne czy zmieniam system skali ręcznie... bzdurka fbxa
			

			std::string nametype = lCluster->GetLink()->GetName();	

			animationStructure->GetSkeleton(frame)->GetBone(animationStructure->GetSkeleton(frame)->GetBoneByName(lCluster->GetLink()->GetName()))->SetTransformation(setMatrix);
		}//lClusterCount
	}

	delete [] lClusterDeformation;
	delete [] lClusterWeight;
}
Esempio n. 6
0
BabylonLight::BabylonLight(BabylonNode & babnode) :
	diffuse(1, 1, 1),
	specular(1, 1, 1)
{
	auto node = babnode.fbxNode();
	std::string ansiName = node->GetName();
	name = std::wstring(ansiName.begin(), ansiName.end());
	id = getNodeId(node);
	auto parent = node->GetParent();
	if (parent) {
		parentId = getNodeId(parent);
	}
	auto localTransform = babnode.GetLocal();
	position = localTransform.translation();
	auto light = node->GetLight();
	switch (light->LightType)
	{
	case FbxLight::ePoint:
		type = type_omni;
		break;
	case FbxLight::eDirectional:
		type = type_direct;
		{
			FbxDouble3 vDir(0, -1, 0);
			FbxAMatrix rotM;
			rotM.SetIdentity();

			rotM.SetQ(localTransform.fbxrot());
			auto transDir = rotM.MultT(vDir);
			direction = transDir;

		}
		break;
	case FbxLight::eSpot:
		type = type_Spot;
		{
			FbxDouble3 vDir(0, -1, 0);
			FbxAMatrix rotM;
			rotM.SetIdentity();
			rotM.SetQ(localTransform.fbxrot());
			auto transDir = rotM.MultT(vDir);
			direction = transDir;
			exponent = 1;
			angle = static_cast<float>(light->OuterAngle*Euler2Rad);

		}
		break;
	default:
		break;
	}
	diffuse = light->Color.Get();
	intensity = static_cast<float>(light->Intensity.Get() / 100.0);
	if (light->EnableFarAttenuation.Get()) {
		range = static_cast<float>(light->FarAttenuationEnd.Get());
	}
	auto hasAnimStack = node->GetScene()->GetSrcObjectCount<FbxAnimStack>() > 0;
	if (!hasAnimStack) {
		return;
	}
	castShadows = light->CastShadows.Get();
	if (castShadows) {
		shadowGenerator = std::make_shared<BabylonShadowGenerator>(node);
	}
	auto animStack = node->GetScene()->GetSrcObject<FbxAnimStack>(0);
	FbxString animStackName = animStack->GetName();
	FbxTakeInfo* takeInfo = node->GetScene()->GetTakeInfo(animStackName);
	auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
	auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
	auto startFrame = takeInfo->mLocalTimeSpan.GetStart().GetFrameCount(animTimeMode);
	auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
	auto animLengthInFrame = endFrame - startFrame + 1;
	auto posAnimName = getNodeId(node);
	auto dirAnimName = getNodeId(node);
	posAnimName.append(L"_position");
	dirAnimName.append(L"_direction");
	auto posAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), posAnimName, L"position", true, 0, static_cast<int>(animLengthInFrame), true);
	auto dirAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), dirAnimName, L"direction", true, 0, static_cast<int>(animLengthInFrame), true);
	if (node->LclRotation.GetCurveNode() || node->LclTranslation.GetCurveNode()) {
		for (auto ix = 0; ix < animLengthInFrame; ix++) {
			babylon_animation_key<babylon_vector3> key;
			key.frame = ix;
			FbxTime currTime;
			currTime.SetFrame(startFrame + ix, animTimeMode);
			auto currTransform = babnode.GetLocal(currTime);
			key.values = currTransform.translation();
			posAnim->appendKey(key);

			if (type == type_direct || type == type_Spot) {
				babylon_animation_key<babylon_vector3> dirkey;
				dirkey.frame = ix;
				FbxDouble3 vDir(0, -1, 0);
				FbxAMatrix rotM;
				rotM.SetIdentity();
				rotM.SetQ(currTransform.fbxrot());
				auto transDir = rotM.MultT(vDir);
				dirkey.values = transDir;
				dirAnim->appendKey(dirkey);
			}
		}
	}
	if (!posAnim->isConstant()) {
		animations.push_back(posAnim);
	}
	if (!dirAnim->isConstant()) {
		animations.push_back(dirAnim);
	}
}