HRESULT CStaticMesh::Load_StaticMesh(const char* szFilePath,const char* szFileName, FbxManager* _pFBXManager, FbxIOSettings* _pIOsettings, FbxScene* _pFBXScene, FbxImporter* _pImporter)
{
	HRESULT hr = E_FAIL;

	vector<UINT> vecIndeces;

	string	strFullPath;

	strFullPath.clear();
	strFullPath = szFilePath;
	strFullPath += szFileName;//경로에 파일이름 추가

	if (!(_pImporter->Initialize(strFullPath.c_str(), -1, _pFBXManager->GetIOSettings())))
		FAILED_CHECK_MSG(E_FAIL, L"Static Mesh Init Failed");
	if (!(_pImporter->Import(_pFBXScene)))
		FAILED_CHECK_MSG(E_FAIL, L"Static Mesh Import Failed");

	FbxGeometryConverter clsConverter(_pFBXManager);
	clsConverter.Triangulate(_pFBXScene, false);
	FbxNode* pRootNode = _pFBXScene->GetRootNode();

	if (!pRootNode)
		return E_FAIL;

	vector<VTXTEX> vecVTXTEX;

	for (int i = 0; i < pRootNode->GetChildCount(); ++i)
	{
		FbxNode* pChildNode = pRootNode->GetChild(i);

		if (pChildNode->GetNodeAttribute() == NULL)
			continue;

		FbxNodeAttribute::EType AttributeType = pChildNode->GetNodeAttribute()->GetAttributeType();

		if (AttributeType != FbxNodeAttribute::eMesh)
			continue;

		FbxMesh* pMesh = (FbxMesh*)pChildNode->GetNodeAttribute();  // 임폴트 하려는 메쉬의 데이터
		D3DXVECTOR3 vPos;
		D3DXVECTOR2 vOutUV;
		D3DXVECTOR3 vOutNormal;
		FbxVector4* mControlPoints = pMesh->GetControlPoints();
		int iVTXCounter = 0;



		for (int j = 0; j < pMesh->GetPolygonCount(); j++) // 폴리곤의 인덱스
		{
			int iNumVertices = pMesh->GetPolygonSize(j);
			assert(iNumVertices == 3);
			FbxGeometryElementUV* VtxUV = pMesh->GetElementUV(0);
			FbxGeometryElementNormal* VtxNormal = pMesh->GetElementNormal(0);



			for (int k = 0; k < iNumVertices; k++) // 폴리곤을 구성하는 버텍스의 인덱스
			{
				//정점 데이터 얻는곳
				int iControlPointIndex = pMesh->GetPolygonVertex(j, k); // 컨트롤 포인트 = 하나의 버텍스
				int iTextureUVIndex = pMesh->GetTextureUVIndex(j, k);  // Control = Vertex
				//int iNormalIndex = pMesh->GetPolygonVertexIndex(j, k);
				++iVTXCounter;

				vPos.x = (float)mControlPoints[iControlPointIndex].mData[0];
				vPos.y = -(float)mControlPoints[iControlPointIndex].mData[1];
				vPos.z = (float)mControlPoints[iControlPointIndex].mData[2];

				//uv 얻기
				switch (VtxUV->GetMappingMode()) // UV값 추출
				{
				case FbxGeometryElement::eByControlPoint: // 하나의 컨트롤 포인트가 하나의 노멀벡터를 가질때

					switch (VtxUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vOutUV.x = static_cast<float>(VtxUV->GetDirectArray().GetAt(iControlPointIndex).mData[0]);
						vOutUV.y = static_cast<float>(VtxUV->GetDirectArray().GetAt(iControlPointIndex).mData[1]);
					}
					break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int index = VtxUV->GetIndexArray().GetAt(iControlPointIndex);
						vOutUV.x = static_cast<float>(VtxUV->GetDirectArray().GetAt(index).mData[0]);
						vOutUV.y =  static_cast<float>(VtxUV->GetDirectArray().GetAt(index).mData[1]);
					}
					break;

					default:
						throw std::exception("Invalid Reference");
					}


					break;


				case FbxGeometryElement::eByPolygonVertex:  // Sharp Edge 포인트가 존재할때 고로 우리가 실질적으로 쓰는곳
					switch (VtxUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vOutUV.x = static_cast<float>(VtxUV->GetDirectArray().GetAt(iTextureUVIndex).mData[0]);
						vOutUV.y = 1 - static_cast<float>(VtxUV->GetDirectArray().GetAt(iTextureUVIndex).mData[1]);
					}
					case FbxGeometryElement::eIndexToDirect:
					{

						vOutUV.x = static_cast<float>(VtxUV->GetDirectArray().GetAt(iTextureUVIndex).mData[0]);
						vOutUV.y = 1 - static_cast<float>(VtxUV->GetDirectArray().GetAt(iTextureUVIndex).mData[1]);
					}
					break;
					default:
						throw std::exception("invalid Reference");
					}
					break;
				default:
					throw std::exception("Invalid Reference");
					break;
				}

				//노멀얻기
				switch (VtxNormal->GetMappingMode()) // 노멀값 추출
				{
				case FbxGeometryElement::eByControlPoint: // 하나의 컨트롤 포인트가 하나의 노멀벡터를 가질때

					switch (VtxNormal->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vOutNormal.x = static_cast<float>(VtxNormal->GetDirectArray().GetAt(iControlPointIndex).mData[0]);
						vOutNormal.y = static_cast<float>(VtxNormal->GetDirectArray().GetAt(iControlPointIndex).mData[1]);
						vOutNormal.z = static_cast<float>(VtxNormal->GetDirectArray().GetAt(iControlPointIndex).mData[2]);
					}
					break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int index = VtxNormal->GetIndexArray().GetAt(iControlPointIndex);
						vOutNormal.x = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[0]);
						vOutNormal.y = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[1]);
						vOutNormal.z = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[2]);
					}
					break;

					default:
						throw std::exception("Invalid Reference");
					}


					break;


				case FbxGeometryElement::eByPolygonVertex:  // Sharp Edge 포인트가 존재할때 고로 우리가 실질적으로 쓰는곳
					switch (VtxNormal->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						int index = VtxNormal->GetIndexArray().GetAt(iVTXCounter);
						vOutNormal.x = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[0]);
						vOutNormal.y = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[1]);
						vOutNormal.z = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[2]);
					}
					case FbxGeometryElement::eIndexToDirect:
					{
						int index = VtxNormal->GetIndexArray().GetAt(iVTXCounter);
						vOutNormal.x = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[0]);
						vOutNormal.y = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[1]);
						vOutNormal.z = static_cast<float>(VtxNormal->GetDirectArray().GetAt(index).mData[2]);
					}
					break;
					default:
						throw std::exception("invalid Reference");
					}
					break;
				default:
					throw std::exception("Invalid Reference");
					break;
				}


				VTXTEX vtxtex;
				vtxtex.vPos = vPos;
				vtxtex.vNormal = vOutNormal;
				vtxtex.vTexUV = vOutUV;
				vecVTXTEX.push_back(vtxtex);


				//int index = VtxUV->GetIndexArray().GetAt(iTextureUVIndex);
				vecIndeces.push_back(VtxUV->GetIndexArray().GetAt(iTextureUVIndex));
			}
		}
	}

	unsigned int n = vecVTXTEX.size();
	VTXTEX* pVTXTex = new VTXTEX[n];
	for (unsigned int i = 0; i < vecVTXTEX.size(); ++i)
	{
		pVTXTex[i].vPos = vecVTXTEX[i].vPos;
		pVTXTex[i].vNormal = vecVTXTEX[i].vNormal;
		pVTXTex[i].vTexUV = vecVTXTEX[i].vTexUV;
	}

	m_iVertices = vecVTXTEX.size();
	m_iVertexStrides = sizeof(VTXTEX);
	m_iVertexOffsets = 0;

	MakeVertexNormal((BYTE*)pVTXTex, NULL);

	D3D11_BUFFER_DESC tBufferDesc;
	ZeroMemory(&tBufferDesc, sizeof(D3D11_BUFFER_DESC));
	tBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	tBufferDesc.ByteWidth = m_iVertexStrides * m_iVertices;
	tBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	tBufferDesc.CPUAccessFlags = 0;

	D3D11_SUBRESOURCE_DATA tData;
	ZeroMemory(&tData, sizeof(D3D11_SUBRESOURCE_DATA));
	tData.pSysMem = pVTXTex;
	hr = CDevice::GetInstance()->m_pDevice->CreateBuffer(&tBufferDesc, &tData, &m_VertexBuffer);


	::Safe_Delete(pVTXTex);
	if (FAILED(hr))
		return E_FAIL;


	D3D11_BUFFER_DESC cbd;
	cbd.Usage = D3D11_USAGE_DEFAULT;
	cbd.ByteWidth = sizeof(ConstantBuffer);
	cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	cbd.CPUAccessFlags = 0;
	cbd.MiscFlags = 0;
	cbd.StructureByteStride = 0;
	hr = CDevice::GetInstance()->m_pDevice->CreateBuffer(&cbd, NULL, &m_ConstantBuffer);

	if (FAILED(hr))
	{
		MessageBox(NULL, L"System Message", L"Constant Buffer Error", MB_OK);
		return hr;
	}


	return S_OK;
}
Exemple #2
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;
}
Exemple #3
0
JNIEXPORT jintArray JNICALL Java_de_tesis_dynaware_javafx_graphics_importers_fbx_JFbxLib_getMeshFaces(JNIEnv *env, jobject obj, jint attributeIndex) {

	// Check FBX file has been opened.
	if (!isOpen()) { throwFileClosedException(env); }

	// Check attribute index bounds for safety.
	if (!checkAttributeBounds(attributeIndex)) { throwArrayOutOfBoundsException(env); }

	// Check attribute type for safety.
	if (!isValidType(attributeIndex, FbxNodeAttribute::EType::eMesh)) { return NULL; }

	FbxMesh* mesh = (FbxMesh*)currentNode->GetNodeAttributeByIndex(attributeIndex);

	bool byPolygonVertex = false;
	bool index           = false;
	bool indexToDirect   = false;
	bool direct          = false;

	FbxLayerElementUV *firstLayer = mesh->GetElementUV(0);
	if (firstLayer!=NULL) {
		byPolygonVertex = firstLayer->GetMappingMode()==FbxLayerElement::EMappingMode::eByPolygonVertex;
		index           = firstLayer->GetReferenceMode()==FbxLayerElement::EReferenceMode::eIndex;
		indexToDirect   = firstLayer->GetReferenceMode()==FbxLayerElement::EReferenceMode::eIndexToDirect;
		direct          = firstLayer->GetReferenceMode()==FbxLayerElement::EReferenceMode::eDirect;
	}

	const int polygonCount = mesh->GetPolygonCount();

	jintArray faces = env->NewIntArray(6*polygonCount);

	// Check memory could be allocated.
	if (faces == NULL) { throwOutOfMemoryError(env); }

	for (int i=0; i<polygonCount; i++) {
		jint face[6];

		// Assume we are working with a triangle mesh.
		face[0] = mesh->GetPolygonVertex(i,0);
		face[2] = mesh->GetPolygonVertex(i,1);
		face[4] = mesh->GetPolygonVertex(i,2);

		if (byPolygonVertex && (index || indexToDirect)) {
			face[1] = mesh->GetTextureUVIndex(i, 0);
			face[3] = mesh->GetTextureUVIndex(i, 1);
			face[5] = mesh->GetTextureUVIndex(i, 2);
		}
		else if (direct) {
			face[1] = 3*i;
			face[3] = 3*i+1;
			face[5] = 3*i+2;
		}
		else {
			face[1] = 0;
			face[3] = 0;
			face[5] = 0;
		}

		env->SetIntArrayRegion(faces, 6*i, 6, face);
	}

	return faces;
}
Exemple #4
0
//===============================================================================================================================
void FBXLoader::LoadMesh(FbxNode* node)
{
	FBXSubsets* newSubset = new FBXSubsets();
	
	FbxMesh* mesh = node->GetMesh();
	
	newSubset->mPolygonCount = mesh->GetPolygonCount();
	
	int vertexCounter = 0;
	
	// http://stackoverflow.com/questions/30170521/how-to-read-in-fbx-2014-indices-properly-for-directx

	/*newSubset->mTriangles.reserve(newSubset->mPolygonCount);
	
	for (uint32 i = 0; i < newSubset->mPolygonCount; ++i)
	{
		XMFLOAT3 normal[3];
		XMFLOAT3 tangent[3];
		XMFLOAT3 binormal[3];
		XMFLOAT2 uv[3][2];
		
		ZShadeSandboxMesh::FBXTriangle triangle;
		
		newSubset->mTriangles.push_back(triangle);
		
		for (uint32 j = 0; j < 3; ++j)
		{
			int controlPointIndex = mesh->GetPolygonVertex(i, j);
			ZShadeSandboxMesh::PhysicalPoint* ctlPoint = mControlPoints[controlPointIndex];
			
			LoadVertexNormal(mesh, controlPointIndex, vertexCounter, 0, normal[j]);
			
			// Only have diffuse texture
			for (int k = 0; k < 1; ++k)
			{
				LoadVertexTexture(mesh, controlPointIndex, mesh->GetTextureUVIndex(i, j), k, uv[j][k]);
			}
			
			//LoadVertexTangent(mesh, controlPointIndex, vertexCounter, 0, tangent[j]);

			ZShadeSandboxMesh::VertexNormalTexBlend temp;
			temp.position = ctlPoint->position;
			temp.normal = normal[j];
			//temp.tangent = tangent[j];
			temp.texture = uv[j][0];
			
			// Copy the blending from each control point
			for (uint32 i = 0; i < ctlPoint->blendingInfo.size(); ++i)
			{
				ZShadeSandboxMesh::VertexBlendingInfo blendingInfo;
				
				blendingInfo.blendingIndex = ctlPoint->blendingInfo[i].blendingIndex;
				blendingInfo.blendingWeight = ctlPoint->blendingInfo[i].blendingWeight;
				
				temp.vertexBlendingInfos.push_back(blendingInfo);
			}
			
			// Sort blending info to remove duplicate vertices
			temp.SortBlendingInfoByWeight();
			
			newSubset->mVertices.push_back(temp);
			newSubset->mTriangles.back().indices.push_back(vertexCounter);
			
			++vertexCounter;
		}
	}*/
	
	/*int* indices = mesh->GetPolygonVertices();
	for (int ind = 0; ind < mesh->GetPolygonVertexCount(); ind++)
	{
		newSubset->mIndices.push_back(indices[ind]);

		string indice = ZShadeSandboxGlobal::Convert::ConvertToString<int>(indices[ind]);
		outIndiceFile << "indice: " << indice << "\n";
	}*/

	for (uint32 polygonID = 0; polygonID < newSubset->mPolygonCount; ++polygonID)
	{
		int polyVertCount = mesh->GetPolygonSize(polygonID);
		
		for (uint32 polygonVertexID = 0; polygonVertexID < polyVertCount; ++polygonVertexID)
		{
			ZShadeSandboxMesh::VertexNormalTexBlend temp;
			
			// Initialize the vertex data
			temp.position = XMFLOAT3(0, 0, 0);
			temp.normal = XMFLOAT3(0, 0, 0);
			temp.texture = XMFLOAT2(0, 0);
			temp.tangent = XMFLOAT3(0, 0, 0);
			
			int controlPointIndex = mesh->GetPolygonVertex(polygonID, polygonVertexID);
			
			ZShadeSandboxMesh::PhysicalPoint* ctlPoint = mControlPoints[controlPointIndex];
			
			//
			// Load vertex position
			//
			
			temp.position = ctlPoint->position;
			
			//
			// Load vertex normal
			//
			
			int normElementCount = mesh->GetElementNormalCount();
			
			for (int normElement = 0; normElement < normElementCount; normElement++)
			{
				XMFLOAT3 normal;
				
				if (LoadVertexNormal(mesh, controlPointIndex, vertexCounter, normElement, normal))
				{
					temp.normal = normal;
					
					break;
				}
			}
			
			//
			// Load vertex UV
			//
			
			int uvElementCount = mesh->GetElementUVCount();
			
			for (int uvElement = 0; uvElement < uvElementCount; uvElement++)
			{
				XMFLOAT2 uv;
				
				if (LoadVertexTexture(mesh, controlPointIndex, mesh->GetTextureUVIndex(polygonID, polygonVertexID), uvElement, uv))
				{
					temp.texture = uv;
					
					break;
				}
			}
			
			//
			// Load vertex tangent
			//
			
			int tangentElementCount = mesh->GetElementTangentCount();
			
			for (int tangentElement = 0; tangentElement < tangentElementCount; tangentElement++)
			{
				XMFLOAT3 tangent;
				
				if (LoadVertexTangent(mesh, controlPointIndex, vertexCounter, tangentElement, tangent))
				{
					temp.tangent = tangent;
					
					break;
				}
			}
			
			//
			// Load vertex blending information for skinning
			//
			
			// Copy the blending from each control point
			for (uint32 i = 0; i < ctlPoint->blendingInfo.size(); ++i)
			{
				ZShadeSandboxMesh::VertexBlendingInfo blendingInfo;
				
				blendingInfo.blendingIndex = ctlPoint->blendingInfo[i].blendingIndex;
				blendingInfo.blendingWeight = ctlPoint->blendingInfo[i].blendingWeight;
				
				temp.vertexBlendingInfos.push_back(blendingInfo);
			}
			
			// Sort blending info to remove duplicate vertices
			temp.SortBlendingInfoByWeight();
			
			//
			// Make sure the vertices are unique and get the index
			//
			
			vector<ZShadeSandboxMesh::VertexNormalTexBlend>& uniqueVerts = newSubset->mVertices;
			
			size_t size = uniqueVerts.size();
			uint32 indice;
			
			for (indice = 0; indice < size; indice++)
			{
				if (temp.EqualsPosNormTex(uniqueVerts[indice]))
				{
					break;
				}
			}
			
			if (indice == size)
			{
				uniqueVerts.push_back(temp);
				string pos = ZShadeSandboxGlobal::Convert::ConvertFloat3ToString(temp.position);
				outVertexFile << "vertex: " << pos << "\n";
			}
			
			newSubset->mIndices.push_back(indice);
			string indice_str = ZShadeSandboxGlobal::Convert::ConvertToString<uint32>(indice);
			outIndiceFile << "indice: " << indice_str << "\n";
			
			++vertexCounter;
		}
	}

	// Now mControlPoints has served its purpose so we can free its memory
	for(auto itr = mControlPoints.begin(); itr != mControlPoints.end(); ++itr)
	{
		delete itr->second;
	}
	
	mControlPoints.clear();
	
	// Adding a new subset to the mesh
	mSubsets.push_back(newSubset);
}
Exemple #5
0
	void importFBXNode(
		FbxNode *node, 
		vector<Vector3> &vertices, 
		vector<Color> &colors, 
		vector<Vector2> &uvs, 
		vector<Vector3> &normals,
		vector<uint32> &elements) {

		FbxNode *childNode = 0;
		int numKids = node->GetChildCount();
		for ( int i=0 ; i<numKids ; i++)
		{
			childNode = node->GetChild(i);
			FbxMesh *mesh = childNode->GetMesh();

			if ( mesh != NULL )
			{
				auto offset = node->GetGeometricTranslation(FbxNode::eSourcePivot);

				//================= Get Vertices ====================================
				int baseline = vertices.size();
				int numVerts = mesh->GetControlPointsCount();

				for ( int j=0; j<numVerts; j++)
				{
					FbxVector4 vert = mesh->GetControlPointAt(j);
					vertices.push_back(
						Vector3(vert.mData[0], vert.mData[1], vert.mData[2])
						/*+ Vector3(offset.mData[0], offset.mData[1], offset.mData[2])*/);
					colors.push_back(Vector3(1, 1, 1));
					uvs.push_back(Vector2(0, 0));
				}

				//================= Get Indices ====================================
				int numIndices=mesh->GetPolygonVertexCount();
				int *indicesRaw = mesh->GetPolygonVertices();
				for (int j = 0; j < numIndices; j++) {
					elements.push_back(indicesRaw[j] + baseline);
				}

				int cnt = 0;
				int polygonCount = mesh->GetPolygonCount();
				for (int j = 0; j < polygonCount; ++j) {

					FbxLayerElementArrayTemplate<FbxVector2>* uvVertices= 0;
					mesh->GetTextureUV(&uvVertices, FbxLayerElement::eTextureDiffuse);

					for (int k = 0; k < mesh->GetPolygonSize(j); ++k) {

						FbxVector2 uv = (*uvVertices)[mesh->GetTextureUVIndex(j, k)];

						uvs[indicesRaw[cnt] + baseline].x = uv[0];
						uvs[indicesRaw[cnt] + baseline].y = uv[1];
						cnt++;
					}
				}
			}

			importFBXNode(childNode, vertices, colors, uvs, normals, elements);
		}
	}
Exemple #6
0
//--------------------------------------------------------------------------
void SaveMesh(FbxNode* pNode, const VeDirectoryPtr& spDest) noexcept
{
	Mesh kMesh;
	FbxMesh* pMesh = (FbxMesh*)pNode->GetNodeAttribute();
	
	kMesh.m_kName = pNode->GetName();
	kMesh.m_stFaces = pMesh->GetPolygonCount();
	kMesh.m_stVerts = kMesh.m_stFaces * 3;

	kMesh.m_kIndices.resize(kMesh.m_stVerts);
	kMesh.m_kPosition.resize(kMesh.m_stVerts);

	kMesh.m_kNormals.resize(pMesh->GetElementNormalCount());
	for (auto& v : kMesh.m_kNormals)
	{
		v.resize(kMesh.m_stVerts);
	}
	kMesh.m_kTexcoords.resize(pMesh->GetElementUVCount());
	for (auto& v : kMesh.m_kTexcoords)
	{
		v.resize(kMesh.m_stVerts);
	}
	kMesh.m_kColors.resize(pMesh->GetElementVertexColorCount());
	for (auto& v : kMesh.m_kColors)
	{
		v.resize(kMesh.m_stVerts);
	}	

	int element_mat = -1;
	for (int i(0); i < pMesh->GetElementMaterialCount(); ++i)
	{
		FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial(i);
		if (lMaterialElement->GetMappingMode() == FbxGeometryElement::eByPolygon)
		{
			element_mat = i;
			break;
		}
	}
	if (element_mat >= 0)
	{
		kMesh.m_kAttributes.resize(kMesh.m_stFaces);
	}

	FbxVector4* lControlPoints = pMesh->GetControlPoints();
	for (int i(0); i < (int)(kMesh.m_stFaces); ++i)
	{
		int lPolygonSize = pMesh->GetPolygonSize(i);
		VE_ASSERT_ALWAYS(lPolygonSize == 3);
		for (int j(0); j < lPolygonSize; ++j)
		{
			uint32_t u32Index = i * 3 + j;
			kMesh.m_kIndices[u32Index] = u32Index;
			int lControlPointIndex = pMesh->GetPolygonVertex(i, j);
			auto& pos = kMesh.m_kPosition[u32Index];
			pos.x = (float)lControlPoints[lControlPointIndex][0];
			pos.y = (float)lControlPoints[lControlPointIndex][1];
			pos.z = (float)lControlPoints[lControlPointIndex][2];
			
			for (int k(0); k < (int)(kMesh.m_kColors.size()); ++k)
			{
				FbxColor c;
				FbxGeometryElementVertexColor* leVtxc = pMesh->GetElementVertexColor(k);
				switch (leVtxc->GetMappingMode())
				{
				default:
					break;
				case FbxGeometryElement::eByControlPoint:
					switch (leVtxc->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						c = leVtxc->GetDirectArray().GetAt(lControlPointIndex);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leVtxc->GetIndexArray().GetAt(lControlPointIndex);
						c = leVtxc->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
					break;

				case FbxGeometryElement::eByPolygonVertex:
				{
					switch (leVtxc->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						c = leVtxc->GetDirectArray().GetAt(u32Index);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leVtxc->GetIndexArray().GetAt(u32Index);
						c = leVtxc->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
				}
				break;
				case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs
				case FbxGeometryElement::eAllSame:   // doesn't make much sense for UVs
				case FbxGeometryElement::eNone:       // doesn't make much sense for UVs
					break;
				}
				auto& color = kMesh.m_kColors[k][u32Index];
				color.x = (float)c[0];
				color.y = (float)c[1];
				color.z = (float)c[2];
				color.w = (float)c[3];
			}

			for (int k(0); k < (int)(kMesh.m_kTexcoords.size()); ++k)
			{
				FbxVector2 uv;
				FbxGeometryElementUV* leUV = pMesh->GetElementUV(k);
				switch (leUV->GetMappingMode())
				{
				default:
					break;
				case FbxGeometryElement::eByControlPoint:
					switch (leUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						uv = leUV->GetDirectArray().GetAt(lControlPointIndex);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leUV->GetIndexArray().GetAt(lControlPointIndex);
						uv = leUV->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
					break;

				case FbxGeometryElement::eByPolygonVertex:
				{
					int lTextureUVIndex = pMesh->GetTextureUVIndex(i, j);
					switch (leUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					case FbxGeometryElement::eIndexToDirect:
					{
						uv = leUV->GetDirectArray().GetAt(lTextureUVIndex);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
				}
				break;

				case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs
				case FbxGeometryElement::eAllSame:   // doesn't make much sense for UVs
				case FbxGeometryElement::eNone:       // doesn't make much sense for UVs
					break;
				}

				auto& texcoord = kMesh.m_kTexcoords[k][u32Index];
				texcoord.x = (float)uv[0];
				texcoord.y = (float)uv[1];
			}
			
			for (int k(0); k < (int)(kMesh.m_kNormals.size()); ++k)
			{
				FbxVector4 n;
				FbxGeometryElementNormal* leNormal = pMesh->GetElementNormal(k);
				if (leNormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
				{
					switch (leNormal->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						n = leNormal->GetDirectArray().GetAt(u32Index);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leNormal->GetIndexArray().GetAt(u32Index);
						n = leNormal->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
				}

				auto& normal = kMesh.m_kNormals[k][u32Index];
				normal.x = (float)n[0];
				normal.y = (float)n[1];
				normal.z = (float)n[2];
			}

			if (element_mat >= 0)
			{
				FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial(element_mat);
				FbxSurfaceMaterial* lMaterial = NULL;
				int lMatId = -1;
				lMaterial = pMesh->GetNode()->GetMaterial(lMaterialElement->GetIndexArray().GetAt(i));
				lMatId = lMaterialElement->GetIndexArray().GetAt(i);
				kMesh.m_kAttributes[i] = lMatId;
			}
		}
	}
	kMesh.Process();
	kMesh.Save(spDest);
}
Exemple #7
0
void ProcessMesh( FbxNode* node , std::string& output)
{
	if(node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh)
	{
		FbxMesh* pMesh = node->GetMesh();  
		if(pMesh == NULL)  
		{  
			return;  
		}  

		vector<D3DXVECTOR3> m_ObjVerPosArr;
		vector<D3DXVECTOR3> m_ObjVerNorArr;
		vector<D3DXVECTOR2> m_ObjVerUVArr;
		std::string m_ObjVerIndex;

		D3DXVECTOR3 vertex[3];  
		D3DXVECTOR4 color[3];  
		D3DXVECTOR3 normal[3];  
		D3DXVECTOR3 tangent[3];  
		D3DXVECTOR2 uv[3][2];  

		int triangleCount = pMesh->GetPolygonCount();  
		int vertexCounter = 0;  

		int currentPosIndex = -1;
		int currentUVIndex  = -1;
		int currentNorIndex = -1;

		output.append("g submesh1\n");

		for(int i = 0 ; i < triangleCount ; ++i)  
		{  
			m_ObjVerIndex.append("f ");
			for(int j = 0 ; j < 3 ; j++)  
			{  
				int ctrlPointIndex = pMesh->GetPolygonVertex(i , j);  

				// Read the vertex  
				ReadVertex(pMesh , ctrlPointIndex , &vertex[j]);  

				int posFind = VectorFind<D3DXVECTOR3>(m_ObjVerPosArr,vertex[j]);
				if (posFind==-1)
				{
					m_ObjVerPosArr.push_back(vertex[j]);
					currentPosIndex+=1;

					char posIndex[128];
					Format(&posIndex[0],"%d",currentPosIndex+1);
					m_ObjVerIndex.append(posIndex);
					m_ObjVerIndex.append("/");
				}
				else
				{
					char posIndex[128];
					Format(&posIndex[0],"%d",posFind+1);
					m_ObjVerIndex.append(posIndex);
					m_ObjVerIndex.append("/");
				}

				// Read the color of each vertex  
				ReadColor(pMesh , ctrlPointIndex , vertexCounter , &color[j]);  

				// Read the UV of each vertex  
				for(int k = 0 ; k < 1 ; ++k)  
				{  
					ReadUV(pMesh , ctrlPointIndex , pMesh->GetTextureUVIndex(i, j) , k , &(uv[j][k]));  

					int uvFind = VectorFind<D3DXVECTOR2>(m_ObjVerUVArr,uv[j][k]);
					if (uvFind==-1)
					{
						m_ObjVerUVArr.push_back(uv[j][k]);
						currentUVIndex+=1;

						char uvIndex[128];
						Format(&uvIndex[0],"%d",currentUVIndex+1);
						m_ObjVerIndex.append(uvIndex);
						m_ObjVerIndex.append("/");
					}
					else
					{
						char uvIndex[128];
						Format(&uvIndex[0],"%d",uvFind+1);
						m_ObjVerIndex.append(uvIndex);
						m_ObjVerIndex.append("/");
					}
				}  

				// Read the normal of each vertex  
				ReadNormal(pMesh , ctrlPointIndex , vertexCounter , &normal[j]);  
				
				int norFind = VectorFind<D3DXVECTOR3>(m_ObjVerNorArr,normal[j]);
				if (norFind==-1)
				{
					m_ObjVerNorArr.push_back(vertex[j]);
					currentNorIndex+=1;

					char normalIndex[128];
					Format(&normalIndex[0],"%d",currentNorIndex+1);
					m_ObjVerIndex.append(normalIndex);
					m_ObjVerIndex.append(" ");
				}
				else
				{
					char normalIndex[128];
					Format(&normalIndex[0],"%d",norFind+1);
					m_ObjVerIndex.append(normalIndex);
					m_ObjVerIndex.append(" ");
				}
				// Read the tangent of each vertex  
				ReadTangent(pMesh , ctrlPointIndex , vertexCounter , &tangent[j]);  

				vertexCounter++;  
			}  
			m_ObjVerIndex.append("\n");
			// 根据读入的信息组装三角形,并以某种方式使用即可,比如存入到列表中、保存到文件等...  
		} 
		char posIndex[128];

		for (int i = 0 ;i<m_ObjVerPosArr.size() ;i++)
		{
			output.append("v ");
			Format(posIndex,128,"%.6f",m_ObjVerPosArr[i].x);
			output.append(posIndex);
			output.append(" ");
			
			Format(posIndex,128,"%.6f",m_ObjVerPosArr[i].y);
			output.append(posIndex);
			output.append(" ");
			
			Format(posIndex,128,"%.6f",m_ObjVerPosArr[i].z);
			output.append(posIndex);
			
			output.append("\n");
		}

		for (int i = 0 ;i<m_ObjVerUVArr.size() ;i++)
		{
			output.append("vt ");
			Format(posIndex,128,"%.6f",m_ObjVerUVArr[i].x);
			output.append(posIndex);
			output.append(" ");
			Format(posIndex,128,"%.6f",m_ObjVerUVArr[i].y);
			output.append(posIndex);
			output.append("\n");
		}

		for (int i = 0 ;i<m_ObjVerNorArr.size() ;i++)
		{
			output.append("vn ");
			Format(posIndex,128,"%.6f",m_ObjVerNorArr[i].x);
			output.append(posIndex);
			output.append(" ");
			Format(posIndex,128,"%.6f",m_ObjVerNorArr[i].y);
			output.append(posIndex);
			output.append(" ");
			Format(posIndex,128,"%.6f",m_ObjVerNorArr[i].z);
			output.append(posIndex);
			output.append("\n");
		}
		output.append(m_ObjVerIndex);
	}
}