예제 #1
0
void Mesh::GetNormals(FbxMesh* pMesh, MeshInfo& pMeshInfo)
{
	FbxGeometryElementNormal* lNormalElement = pMesh->GetElementNormal();

	if (lNormalElement)
	{


		if (lNormalElement->GetReferenceMode() == FbxGeometryElement::eDirect)
		{
			for (int lVertexIndex = 0; lVertexIndex < pMesh->GetLayer(0)->GetNormals()->GetDirectArray().GetCount(); lVertexIndex++)
			{
				int lNormalIndex = 0;

				lNormalIndex = lVertexIndex;

				pMeshInfo.normals.push_back(lNormalElement->GetDirectArray().GetAt(lNormalIndex));
			}
		}

		if (lNormalElement->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
		{
			for (int lVertexIndex = 0; lVertexIndex < pMesh->GetLayer(0)->GetNormals()->GetIndexArray().GetCount(); lVertexIndex++)
			{
				int lNormalIndex = 0;

				lNormalIndex = lNormalElement->GetIndexArray().GetAt(lVertexIndex);

				pMeshInfo.normals.push_back(lNormalElement->GetDirectArray().GetAt(lNormalIndex));
			}
		}
	}
}
예제 #2
0
reVec3 reFBXAsset::getNormal(FbxMesh* fmesh, int vi)
{
	FbxVector4 normal;
	for(int l = 0; l < fmesh->GetElementNormalCount(); ++l)
	{
		FbxGeometryElementNormal* leNormal = fmesh->GetElementNormal(l);
		if(leNormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
		{
			switch (leNormal->GetReferenceMode())
			{
			case FbxGeometryElement::eDirect:
				normal = leNormal->GetDirectArray().GetAt(vi);
				return reVec3(normal[0], normal[1], normal[2]);
			case FbxGeometryElement::eIndexToDirect:
				int id = leNormal->GetIndexArray().GetAt(vi);
				normal = leNormal->GetDirectArray().GetAt(id);
				return reVec3(normal[0], normal[1], normal[2]);
			}
		}
	}
	return reVec3(0,0,0);
}
예제 #3
0
void FBXSceneImporter::read_mesh(FbxNode *pNode, FbxMesh* pMesh)
{
	std::vector<Mesh::Vertex> vertices;
	std::vector<int> indices;
	
	//pMesh->GenerateTangentsDataForAllUVSets();

	Mesh *new_mesh = new Mesh();
	
	new_mesh->set_name(pNode->GetName());

	int polygonCount = pMesh->GetPolygonCount();
	FbxVector4* controlPoints = pMesh->GetControlPoints();
	int controlPointCount = pMesh->GetControlPointsCount();

	int vertexID = 0;

	for (int polygon = polygonCount - 1; polygon > -1; polygon--)
	{
		int polyVertCount = pMesh->GetPolygonSize(polygon);
		assert(polyVertCount == 3);

		for (int polyVert = 0; polyVert < polyVertCount; polyVert++)
		{
			Mesh::Vertex vertex;

			int cpIndex = pMesh->GetPolygonVertex(polygon, polyVert);

			// Grab our CP index as well our position information
			//uniqueVert.m_nControlPointIndex = cpIndex;
			vertex.position[0] = controlPoints[cpIndex].mData[0];
			vertex.position[1] = controlPoints[cpIndex].mData[1];
			vertex.position[2] = controlPoints[cpIndex].mData[2];
			vertex.position[3] = 1;

			// Grab UVs
			int uvElementCount = pMesh->GetElementUVCount();
			int ctrlPointIndex = pMesh->GetPolygonVertex(polygon, polyVert);

			for (int uvElement = 0; uvElement < uvElementCount; uvElement++)
			{
				FbxGeometryElementUV* geomElementUV = pMesh->GetElementUV(uvElement);

				FbxLayerElement::EMappingMode mapMode = geomElementUV->GetMappingMode();
				FbxLayerElement::EReferenceMode refMode = geomElementUV->GetReferenceMode();

				if (FbxGeometryElement::eByControlPoint == mapMode)
				{
					switch (geomElementUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vertex.texture_coord.x = static_cast<float>(geomElementUV->GetDirectArray().GetAt(ctrlPointIndex).mData[0]);
						vertex.texture_coord.y = static_cast<float>(geomElementUV->GetDirectArray().GetAt(ctrlPointIndex).mData[1]);
					}
					break;

					case FbxGeometryElement::eIndexToDirect:
					{
						int index = geomElementUV->GetIndexArray().GetAt(ctrlPointIndex);
						vertex.texture_coord.x = static_cast<float>(geomElementUV->GetDirectArray().GetAt(index).mData[0]);
						vertex.texture_coord.y = static_cast<float>(geomElementUV->GetDirectArray().GetAt(index).mData[1]);
					}
					break;

					default:
						throw std::exception("Invalid Reference");
					}
				}
				if (FbxGeometryElement::eByPolygonVertex == mapMode)
				{
					int directIndex = -1;
					if (FbxGeometryElement::eDirect == refMode)
					{
						directIndex = vertexID;
					}
					else if (FbxGeometryElement::eIndexToDirect == refMode)
					{
						directIndex = geomElementUV->GetIndexArray().GetAt(vertexID);
					}

					// If we got an index
					if (directIndex != -1)
					{
						FbxVector4 texture_coord = geomElementUV->GetDirectArray().GetAt(directIndex);

						vertex.texture_coord = D3DXVECTOR4((float)texture_coord.mData[0], (float)texture_coord.mData[1], 0, 0);
					}
				}
			}

			// Grab normals
			int normElementCount = pMesh->GetElementNormalCount();

			for (int normalElement = 0; normalElement < normElementCount; normalElement++)
			{
				FbxGeometryElementNormal* geomElementNormal = pMesh->GetElementNormal(normalElement);

				FbxLayerElement::EMappingMode mapMode = geomElementNormal->GetMappingMode();
				FbxLayerElement::EReferenceMode refMode = geomElementNormal->GetReferenceMode();

				FbxVector4 fbxNormal;
				pMesh->GetPolygonVertexNormal(polygon, polyVert, fbxNormal);
				fbxNormal.Normalize();

				vertex.normal = D3DXVECTOR4(fbxNormal.mData[0], fbxNormal.mData[1], fbxNormal.mData[2], 0);

				//if (FbxGeometryElement::eByControlPoint == mapMode)
				//{ 
				//	switch (geomElementNormal->GetReferenceMode())
				//	{
				//	case FbxGeometryElement::eDirect:
				//	{
				//		vertex.normal.x = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(ctrlPointIndex).mData[0]);
				//		vertex.normal.y = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(ctrlPointIndex).mData[1]);
				//		vertex.normal.z = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(ctrlPointIndex).mData[2]);
				//		D3DXVec4Normalize(&vertex.normal, &vertex.normal);
				//	}
				//	break;
				//
				//	case FbxGeometryElement::eIndexToDirect:
				//	{
				//		int index = geomElementNormal->GetIndexArray().GetAt(ctrlPointIndex);
				//		vertex.normal.x = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(index).mData[0]);
				//		vertex.normal.y = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(index).mData[1]);
				//		vertex.normal.z = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(index).mData[2]);
				//		D3DXVec4Normalize(&vertex.normal, &vertex.normal);
				//	}
				//	break;
				//
				//	default:
				//		throw std::exception("Invalid Reference");
				//	}
				//}
				//if (FbxGeometryElement::eByPolygonVertex == mapMode)
				//{
				//	int directIndex = -1;
				//	if (FbxGeometryElement::eDirect == refMode)
				//	{
				//		directIndex = vertexID;
				//	}
				//	else if (FbxGeometryElement::eIndexToDirect == refMode)
				//	{
				//		directIndex = geomElementNormal->GetIndexArray().GetAt(vertexID);
				//	}
				//
				//	// If we got an index
				//	if (directIndex != -1)
				//	{
				//		FbxVector4 norm = geomElementNormal->GetDirectArray().GetAt(directIndex);
				//
				//		D3DXVECTOR4 normal_final((float)norm.mData[0], (float)norm.mData[1], (float)norm.mData[2], 0);
				//		D3DXVec4Normalize(&vertex.normal, &normal_final);
				//	}
				//}


			}

			// grab tangents
			int tangentElementCount = pMesh->GetElementTangentCount();

			for (int normalElement = 0; normalElement < tangentElementCount; normalElement++)
			{
				FbxGeometryElementTangent* geomElementTangent = pMesh->GetElementTangent(normalElement);

				FbxLayerElement::EMappingMode mapMode = geomElementTangent->GetMappingMode();
				FbxLayerElement::EReferenceMode refMode = geomElementTangent->GetReferenceMode();

				int directIndex = -1;

				if (FbxGeometryElement::eByPolygonVertex == mapMode)
				{
					if (FbxGeometryElement::eDirect == refMode)
					{
						directIndex = vertexID;
					}
					else if (FbxGeometryElement::eIndexToDirect == refMode)
					{
						directIndex = geomElementTangent->GetIndexArray().GetAt(vertexID);
					}
				}

				// If we got an index
				if (directIndex != 1)
				{
					FbxVector4 tangent = geomElementTangent->GetDirectArray().GetAt(directIndex);

					vertex.tangent = D3DXVECTOR4((float)tangent.mData[0], (float)tangent.mData[1], (float)tangent.mData[2], 0);
				}

			}

			size_t size = vertices.size();
			size_t i = size;

			//for (i = 0; i < size; i++)
			//{
			//	if (vertex == vertices[i])
			//	{
			//		break;
			//	}
			//}
			//
			if (i == size)
			{
				vertices.push_back(vertex);
			}

			indices.push_back(i);
			++vertexID;
		}

		//int cur_size = indices.size();
		//int temp = indices[cur_size - 3];
		//indices[cur_size - 3] = indices[cur_size - 1];
		//indices[cur_size - 1] = temp;
	}

	int materialCount = pNode->GetSrcObjectCount<FbxSurfaceMaterial>();

	new_mesh->create_from_buffers(vertices, indices);
	scene_to_fill->add_mesh(new_mesh);

	if (materialCount > 0)
	{
		FbxSurfaceMaterial* material = (FbxSurfaceMaterial*)pNode->GetSrcObject<FbxSurfaceMaterial>(0);
		new_mesh->set_material(read_material(pNode, material));
	}

	get_transformation_matrix(pNode, new_mesh);
	cout << "Read mesh : " << new_mesh->get_name() << "\n";

}
예제 #4
0
	std::shared_ptr<Mesh> FbxUtil::CreateMesh(FbxMesh *fbxMesh)
	{
		Mesh::Ptr mesh = Mesh::Create(fbxMesh->GetName());

		// read physical data.

		int polygonCount = fbxMesh->GetPolygonCount();
		int indicesCount = polygonCount * 3;

		mesh->Positions.Data.reserve(indicesCount * 3);
		mesh->Indices.Data.reserve(indicesCount);

		if ((m_Options & Options::UV) && fbxMesh->GetElementUVCount() > 0)
			mesh->UVs.Data.reserve(indicesCount * 2);

		if ((m_Options & Options::NORMAL) && fbxMesh->GetElementNormalCount() > 0)
			mesh->Normals.Data.reserve(indicesCount * 3);

		if ((m_Options & Options::TANGENT) && fbxMesh->GetElementTangent() > 0)
			mesh->Tangents.Data.reserve(indicesCount * 3);

		int normalCounter = 0, uvCounter = 0, tangentCounter = 0;

		for (int i = 0; i < polygonCount; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				int ctrPtrIndex = fbxMesh->GetPolygonVertex(i, j);

				auto position = fbxMesh->GetControlPointAt(ctrPtrIndex);
				mesh->Positions.Data.push_back((float)position.mData[0]);
				mesh->Positions.Data.push_back((float)position.mData[1]);
				mesh->Positions.Data.push_back((float)position.mData[2]);

				// uv
				if ((m_Options & Options::UV) && fbxMesh->GetElementUVCount() > 0)
				{
					int uvIndex = 0;
					FbxGeometryElementUV* vertexUV = fbxMesh->GetElementUV();

					if (vertexUV->GetMappingMode() == FbxGeometryElement::eByControlPoint)
					{
						if (vertexUV->GetReferenceMode() == FbxGeometryElement::eDirect)
							uvIndex = ctrPtrIndex;
						else if (vertexUV->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
							uvIndex = vertexUV->GetIndexArray().GetAt(ctrPtrIndex);
						else
							ASSERT_MSG(false, "Error: Invalid Reference Mode!");
					}
					else if (vertexUV->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
					{
						if (vertexUV->GetReferenceMode() == FbxGeometryElement::eDirect)
							uvIndex = uvCounter;
						else if (vertexUV->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
							uvIndex = vertexUV->GetIndexArray().GetAt(uvCounter);
						else
							ASSERT_MSG(false, "Error: Invalid Reference Mode!");

						uvCounter++;
					}

					auto uv = vertexUV->GetDirectArray().GetAt(uvIndex);
					mesh->UVs.Data.push_back((float)uv.mData[0]);
					mesh->UVs.Data.push_back(1.0f - (float)uv.mData[1]);
				}

				// normal
				if ((m_Options & Options::NORMAL) && fbxMesh->GetElementNormalCount() > 0)
				{
					int normalIndex = 0;
					FbxGeometryElementNormal* vertexNormal = fbxMesh->GetElementNormal();

					if (vertexNormal->GetMappingMode() == FbxGeometryElement::eByControlPoint)
					{
						if (vertexNormal->GetReferenceMode() == FbxGeometryElement::eDirect)
							normalIndex = ctrPtrIndex;
						else if (vertexNormal->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
							normalIndex = vertexNormal->GetIndexArray().GetAt(ctrPtrIndex);
						else
							ASSERT_MSG(false, "Error: Invalid Reference Mode!");
					}
					else if (vertexNormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
					{
						if (vertexNormal->GetReferenceMode() == FbxGeometryElement::eDirect)
							normalIndex = normalCounter;
						else if (vertexNormal->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
							normalIndex = vertexNormal->GetIndexArray().GetAt(normalCounter);
						else
							ASSERT_MSG(false, "Error: Invalid Reference Mode!");

						normalCounter++;
					}

					auto normal = vertexNormal->GetDirectArray().GetAt(normalIndex);
					mesh->Normals.Data.push_back((float)normal.mData[0]);
					mesh->Normals.Data.push_back((float)normal.mData[1]);
					mesh->Normals.Data.push_back((float)normal.mData[2]);
				}

				// tangent
				if ((m_Options & Options::TANGENT) && fbxMesh->GetElementNormalCount() > 0)
				{
					int tangentIndex = 0;
					FbxGeometryElementTangent* vertexTangent = fbxMesh->GetElementTangent();

					if (vertexTangent->GetMappingMode() == FbxGeometryElement::eByControlPoint)
					{
						if (vertexTangent->GetReferenceMode() == FbxGeometryElement::eDirect)
							tangentIndex = ctrPtrIndex;
						else if (vertexTangent->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
							tangentIndex = vertexTangent->GetIndexArray().GetAt(ctrPtrIndex);
						else
							ASSERT_MSG(false, "Error: Invalid Reference Mode!");
					}
					else if (vertexTangent->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
					{
						if (vertexTangent->GetReferenceMode() == FbxGeometryElement::eDirect)
							tangentIndex = tangentCounter;
						else if (vertexTangent->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
							tangentIndex = vertexTangent->GetIndexArray().GetAt(tangentCounter);
						else
							ASSERT_MSG(false, "Error: Invalid Reference Mode!");

						tangentCounter++;
					}

					auto tangent = vertexTangent->GetDirectArray().GetAt(tangentIndex);
					mesh->Tangents.Data.push_back((float)tangent.mData[0]);
					mesh->Tangents.Data.push_back((float)tangent.mData[1]);
					mesh->Tangents.Data.push_back((float)tangent.mData[2]);
				}

				mesh->Indices.Data.push_back(i * 3 + j);
			}
		}

		LOGD << mesh->GetName() << " [vtx: " << mesh->Positions.Data.size() / 3 << " tris: " << mesh->Indices.Data.size() / 3 << "]";

		if(m_Options & Options::OPTIMIZE_MESH)
			MeshUtil::Instance()->OptimizeMesh(mesh);

		mesh->CalculateAABB();

		return mesh;
	}
예제 #5
0
void FbxParser::ReadNormal(FbxMesh* pMesh, int ctrlPointIndex , int vertexCounter , GS::double3& normal)  
{  
    if(pMesh->GetElementNormalCount() < 1)  
    {  
        return;  
    }  

    FbxGeometryElementNormal* leNormal = pMesh->GetElementNormal( 0);
    switch(leNormal->GetMappingMode())  
    {  
    case FbxGeometryElement::eByControlPoint:  
        {  
            switch(leNormal->GetReferenceMode())  
            {  
            case  FbxGeometryElement::eDirect:  
                {  
                    normal.x = leNormal->GetDirectArray().GetAt(ctrlPointIndex)[0];  
                    normal.y = leNormal->GetDirectArray().GetAt(ctrlPointIndex)[1];  
                    normal.z = leNormal->GetDirectArray().GetAt(ctrlPointIndex)[2];  
                }  
                break;  
  
            case FbxGeometryElement::eIndexToDirect:  
                {  
                    int id = leNormal->GetIndexArray().GetAt(ctrlPointIndex);  
                    normal.x = leNormal->GetDirectArray().GetAt(id)[0];  
                    normal.y = leNormal->GetDirectArray().GetAt(id)[1];  
                    normal.z = leNormal->GetDirectArray().GetAt(id)[2];  
                }  
                break;  
  
            default:  
                break;  
            }  
        }  
        break;  
  
    case FbxGeometryElement::eByPolygonVertex:  
        {  
            switch(leNormal->GetReferenceMode())  
            {  
            case FbxGeometryElement::eDirect:   
                {  
                    normal.x = leNormal->GetDirectArray().GetAt(vertexCounter)[0];  
                    normal.y = leNormal->GetDirectArray().GetAt(vertexCounter)[1];  
                    normal.z = leNormal->GetDirectArray().GetAt(vertexCounter)[2];  
                }  
                break;  
  
            case FbxGeometryElement::eIndexToDirect:  
                {  
                    int id = leNormal->GetIndexArray().GetAt(vertexCounter);  
                    normal.x = leNormal->GetDirectArray().GetAt(id)[0];  
                    normal.y = leNormal->GetDirectArray().GetAt(id)[1];  
                    normal.z = leNormal->GetDirectArray().GetAt(id)[2];  
                }  
                break;  
  
            default:  
                break;  
            }  
        }  
        break;  
    }  
}  
예제 #6
0
void FBXImporter::ReadNormals(FBXMeshData* fbxMeshData, int contorlPointIndex, int normalIndex)
{
	FbxMesh* mesh = fbxMeshData->mMesh;
	vector<XMFLOAT3>& normals = fbxMeshData->mNormals;

	if (mesh->GetElementNormalCount() < 1)
	{
		return;
	}

	FbxGeometryElementNormal* normalElement = mesh->GetElementNormal(0);
	switch (normalElement->GetMappingMode())
	{
	case FbxGeometryElement::eByControlPoint:
		switch (normalElement->GetReferenceMode())
		{
		case FbxGeometryElement::eDirect:
		{
			FbxVector4 fbxNormal = normalElement->GetDirectArray().GetAt(contorlPointIndex);
			XMFLOAT3 normal;
			normal.x = static_cast<float>(fbxNormal[0]);
			normal.y = static_cast<float>(fbxNormal[1]);
			normal.z = static_cast<float>(fbxNormal[2]);
			normals.push_back(normal);
		}
			break;

		case FbxGeometryElement::eIndexToDirect:
		{
			int id = normalElement->GetIndexArray().GetAt(contorlPointIndex);
			FbxVector4 fbxNormal = normalElement->GetDirectArray().GetAt(id);
			XMFLOAT3 normal;
			normal.x = static_cast<float>(fbxNormal[0]);
			normal.y = static_cast<float>(fbxNormal[1]);
			normal.z = static_cast<float>(fbxNormal[2]);
			normals.push_back(normal);
		}
		default:
			break;
		}

		break;

	case FbxGeometryElement::eByPolygonVertex:
		switch (normalElement->GetReferenceMode())
		{
		case FbxGeometryElement::eDirect:
		{
			FbxVector4 fbxNormal = normalElement->GetDirectArray().GetAt(normalIndex);
			XMFLOAT3 normal;
			normal.x = static_cast<float>(fbxNormal[0]);
			normal.y = static_cast<float>(fbxNormal[1]);
			normal.z = static_cast<float>(fbxNormal[2]);
			normals.push_back(normal);
		}
			break;

		case FbxGeometryElement::eIndexToDirect:
		{
			int id = normalElement->GetIndexArray().GetAt(normalIndex);
			FbxVector4 fbxNormal = normalElement->GetDirectArray().GetAt(id);
			XMFLOAT3 normal;
			normal.x = static_cast<float>(fbxNormal[0]);
			normal.y = static_cast<float>(fbxNormal[1]);
			normal.z = static_cast<float>(fbxNormal[2]);
			normals.push_back(normal);
		}
		default:
			break;
		}
		break;

	default:
		break;
	}
}
예제 #7
0
파일: FBXFilter.cpp 프로젝트: imight/trunk
//converts a FBX mesh to a CC mesh
static ccMesh* FromFbxMesh(FbxMesh* fbxMesh, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, CCVector3d* coordinatesShift/*=0*/)
{
	if (!fbxMesh)
		return 0;

	int polyCount = fbxMesh->GetPolygonCount();
	//fbxMesh->GetLayer(
	unsigned triCount = 0;
	unsigned polyVertCount = 0; //different from vertCount (vertices can be counted multiple times here!)
	//as we can't load all polygons (yet ;) we already look if we can load any!
	{
		unsigned skipped = 0;
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize == 3)
			{
				++triCount;
				polyVertCount += 3;
			}
			else if (pSize == 4)
			{
				triCount += 2;
				polyVertCount += 4;
			}
			else
			{
				++skipped;
			}
		}

		if (triCount == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle or quad found in mesh '%1'! (polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()));
			return 0;
		}
		else if (skipped != 0)
		{
			ccLog::Warning(QString("[FBX] Some polygons in mesh '%1' were ignored (%2): polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()).arg(skipped));
			return 0;
		}
	}

	int vertCount = fbxMesh->GetControlPointsCount();
	if (vertCount <= 0)
	{
		ccLog::Warning(QString("[FBX] Mesh '%1' has no vetex or no polygon?!").arg(fbxMesh->GetName()));
		return 0;
	}

	ccPointCloud* vertices = new ccPointCloud("vertices");
	ccMesh* mesh = new ccMesh(vertices);
	mesh->setName(fbxMesh->GetName());
	mesh->addChild(vertices);
	vertices->setEnabled(false);
	
	if (!mesh->reserve(static_cast<unsigned>(triCount)) || !vertices->reserve(vertCount))
	{
		ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1'!").arg(fbxMesh->GetName()));
		delete mesh;
		return 0;
	}

	//colors
	{
		for (int l=0; l<fbxMesh->GetElementVertexColorCount(); l++)
		{
			FbxGeometryElementVertexColor* vertColor = fbxMesh->GetElementVertexColor(l);
			//CC can only handle per-vertex colors
			if (vertColor->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				if (vertColor->GetReferenceMode() == FbxGeometryElement::eDirect
					|| vertColor->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
				{
					if (vertices->reserveTheRGBTable())
					{
						switch (vertColor->GetReferenceMode())
						{
						case FbxGeometryElement::eDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									FbxColor c = vertColor->GetDirectArray().GetAt(i);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mGreen	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mBlue	* MAX_COLOR_COMP) );
								}
							}
							break;
						case FbxGeometryElement::eIndexToDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									int id = vertColor->GetIndexArray().GetAt(i);
									FbxColor c = vertColor->GetDirectArray().GetAt(id);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mGreen	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mBlue	* MAX_COLOR_COMP) );
								}
							}
							break;
						default:
							assert(false);
							break;
						}

						vertices->showColors(true);
						mesh->showColors(true);
						break; //no need to look for other color fields (we won't be able to handle them!
					}
					else
					{
						ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' colors!").arg(fbxMesh->GetName()));
					}
				}
				else
				{
					ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
				}
			}
			else
			{
				ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
			}
		}
	}


	//normals can be per vertices or per-triangle
	int perPointNormals = -1;
	int perVertexNormals = -1;
	int perPolygonNormals = -1;
	{
        for (int j=0; j<fbxMesh->GetElementNormalCount(); j++)
        {
			FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(j);
			switch(leNormals->GetMappingMode())
			{
			case FbxGeometryElement::eByControlPoint:
				perPointNormals = j;
				break;
			case FbxGeometryElement::eByPolygonVertex:
				perVertexNormals = j;
				break;
			case FbxGeometryElement::eByPolygon:
				perPolygonNormals = j;
				break;
			default:
				//not handled
				break;
			}
		}
	}

	//per-point normals
	if (perPointNormals >= 0)
	{
		FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(perPointNormals);
		FbxLayerElement::EReferenceMode refMode = leNormals->GetReferenceMode();
		const FbxLayerElementArrayTemplate<FbxVector4>& normals = leNormals->GetDirectArray();
		assert(normals.GetCount() == vertCount);
		if (normals.GetCount() != vertCount)
		{
			ccLog::Warning(QString("[FBX] Wrong number of normals on mesh '%1'!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else if (!vertices->reserveTheNormsTable())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else
		{
			//import normals
			for (int i=0; i<vertCount; ++i)
			{
				int id = refMode != FbxGeometryElement::eDirect ? leNormals->GetIndexArray().GetAt(i) : i;
				FbxVector4 N = normals.GetAt(id);
				//convert to CC-structure
				CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
								static_cast<PointCoordinateType>(N.Buffer()[1]),
								static_cast<PointCoordinateType>(N.Buffer()[2]) );
				vertices->addNorm(Npc.u);
			}
			vertices->showNormals(true);
			mesh->showNormals(true);
			//no need to import the other normals (if any)
			perVertexNormals = -1;
			perPolygonNormals = -1;
		}
	}

	//per-triangle normals
	NormsIndexesTableType* normsTable = 0;
	if (perVertexNormals >= 0 || perPolygonNormals >= 0)
	{
		normsTable = new NormsIndexesTableType();
		if (!normsTable->reserve(polyVertCount) || !mesh->reservePerTriangleNormalIndexes())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			normsTable->release();
			normsTable = 0;
		}
		else
		{
			mesh->setTriNormsTable(normsTable);
			mesh->addChild(normsTable);
			vertices->showNormals(true);
			mesh->showNormals(true);
		}
	}

	//import textures UV
	int perVertexUV = -1;
	bool hasTexUV = false;
	{
		for (int l=0; l<fbxMesh->GetElementUVCount(); ++l)
		{
			FbxGeometryElementUV* leUV = fbxMesh->GetElementUV(l);
			//per-point UV coordinates
			if (leUV->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				TextureCoordsContainer* vertTexUVTable = new TextureCoordsContainer();
				if (!vertTexUVTable->reserve(vertCount) || !mesh->reservePerTriangleTexCoordIndexes())
				{
					vertTexUVTable->release();
					ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' UV coordinates!").arg(fbxMesh->GetName()));
				}
				else
				{
					FbxLayerElement::EReferenceMode refMode = leUV->GetReferenceMode();
					for (int i=0; i<vertCount; ++i)
					{
						int id = refMode != FbxGeometryElement::eDirect ? leUV->GetIndexArray().GetAt(i) : i;
						FbxVector2 uv = leUV->GetDirectArray().GetAt(id);
						//convert to CC-structure
						float uvf[2] = {static_cast<float>(uv.Buffer()[0]),
										static_cast<float>(uv.Buffer()[1])};
						vertTexUVTable->addElement(uvf);
					}
					mesh->addChild(vertTexUVTable);
					hasTexUV = true;
				}
				perVertexUV = -1;
				break; //no need to look to the other UV fields (can't handle them!)
			}
			else if (leUV->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
			{
				//per-vertex UV coordinates
				perVertexUV = l;
			}
		}
	}

	//per-vertex UV coordinates
	TextureCoordsContainer* texUVTable = 0;
	if (perVertexUV >= 0)
	{
		texUVTable = new TextureCoordsContainer();
		if (!texUVTable->reserve(polyVertCount) || !mesh->reservePerTriangleTexCoordIndexes())
		{
			texUVTable->release();
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' UV coordinates!").arg(fbxMesh->GetName()));
		}
		else
		{
			mesh->addChild(texUVTable);
			hasTexUV = true;
		}
	}

	//import polygons
	{
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize > 4)
			{
				//not handled for the moment
				continue;
			}
			//we split quads into two triangles

			//vertex indices
			int i1 = fbxMesh->GetPolygonVertex(i, 0);
			int i2 = fbxMesh->GetPolygonVertex(i, 1);
			int i3 = fbxMesh->GetPolygonVertex(i, 2);
			mesh->addTriangle(i1,i2,i3);

			int i4 = -1;
			if (pSize == 4)
			{
				i4 = fbxMesh->GetPolygonVertex(i, 3);
				mesh->addTriangle(i1,i3,i4);
			}

			if (hasTexUV)
			{
				if (texUVTable)
				{
					assert(perVertexUV >= 0);

					int uvIndex = static_cast<int>(texUVTable->currentSize());
					for (int j=0; j<pSize; ++j)
					{
						int lTextureUVIndex = fbxMesh->GetTextureUVIndex(i, j);
						FbxGeometryElementUV* leUV = fbxMesh->GetElementUV(perVertexUV);
						FbxVector2 uv = leUV->GetDirectArray().GetAt(lTextureUVIndex);
						//convert to CC-structure
						float uvf[2] = {static_cast<float>(uv.Buffer()[0]),
										static_cast<float>(uv.Buffer()[1])};
						texUVTable->addElement(uvf);
					}
					mesh->addTriangleTexCoordIndexes(uvIndex,uvIndex+1,uvIndex+2);
					if (pSize == 4)
						mesh->addTriangleTexCoordIndexes(uvIndex,uvIndex+2,uvIndex+3);
				}
				else
				{
					mesh->addTriangleTexCoordIndexes(i1,i2,i3);
					if (pSize == 4)
						mesh->addTriangleTexCoordIndexes(i1,i3,i4);
				}
			}

			//per-triangle normals
			if (normsTable)
			{
				int nIndex = static_cast<int>(normsTable->currentSize());
				for (int j=0; j<pSize; ++j)
				{
					FbxVector4 N;
					fbxMesh->GetPolygonVertexNormal(i, j, N);
					CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
									static_cast<PointCoordinateType>(N.Buffer()[1]),
									static_cast<PointCoordinateType>(N.Buffer()[2]) );
					normsTable->addElement(ccNormalVectors::GetNormIndex(Npc.u));
				}

				mesh->addTriangleNormalIndexes(nIndex,nIndex+1,nIndex+2);
				if (pSize == 4)
					mesh->addTriangleNormalIndexes(nIndex,nIndex+2,nIndex+3);
			}
		}
		
		if (mesh->size() == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle found in mesh '%1'! (only triangles are supported for the moment)").arg(fbxMesh->GetName()));
			delete mesh;
			return 0;
		}
	}

	//import vertices
	{
		const FbxVector4* fbxVertices = fbxMesh->GetControlPoints();
		assert(vertices && fbxVertices);
		CCVector3d Pshift(0,0,0);
		for (int i=0; i<vertCount; ++i, ++fbxVertices)
		{
			const double* P = fbxVertices->Buffer();
			assert(P[3] == 0);

			//coordinate shift management
			if (i == 0)
			{
				bool shiftAlreadyEnabled = (coordinatesShiftEnabled && *coordinatesShiftEnabled && coordinatesShift);
				if (shiftAlreadyEnabled)
					Pshift = *coordinatesShift;
				bool applyAll = false;
				if (	sizeof(PointCoordinateType) < 8
					&&	ccCoordinatesShiftManager::Handle(P,0,alwaysDisplayLoadDialog,shiftAlreadyEnabled,Pshift,0,applyAll))
				{
					vertices->setGlobalShift(Pshift);
					ccLog::Warning("[FBX] Mesh has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z);

					//we save coordinates shift information
					if (applyAll && coordinatesShiftEnabled && coordinatesShift)
					{
						*coordinatesShiftEnabled = true;
						*coordinatesShift = Pshift;
					}
				}
			}

			CCVector3 PV(	static_cast<PointCoordinateType>(P[0] + Pshift.x),
							static_cast<PointCoordinateType>(P[1] + Pshift.y),
							static_cast<PointCoordinateType>(P[2] + Pshift.z) );

			vertices->addPoint(PV);
		}
	}

	//import textures
	{
		//TODO
	}

	return mesh;
}
예제 #8
0
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;
}
예제 #9
0
void loadNormal(FbxMesh* fbxMesh, int vertexIndex, int controlPointIndex, Vertex* vertex)
{
    if (fbxMesh->GetElementNormalCount() > 0)
    {
        // Get only the first
        FbxGeometryElementNormal* normal = fbxMesh->GetElementNormal(0);
        FbxGeometryElement::EMappingMode mappingMode = normal->GetMappingMode();
        if (mappingMode == FbxGeometryElement::eByControlPoint)
        {
            switch (normal->GetReferenceMode())
            {
            case FbxGeometryElement::eDirect:
                {
                    FbxVector4 vec4 = normal->GetDirectArray().GetAt(controlPointIndex);
                    vertex->hasNormal = true;
                    vertex->normal.x = (float)vec4[0];
                    vertex->normal.y = (float)vec4[1];
                    vertex->normal.z = (float)vec4[2];
                }
                break;
            case FbxGeometryElement::eIndexToDirect:
                {
                    int id = normal->GetIndexArray().GetAt(controlPointIndex);
                    FbxVector4 vec4 = normal->GetDirectArray().GetAt(id);
                    vertex->hasNormal = true;
                    vertex->normal.x = (float)vec4[0];
                    vertex->normal.y = (float)vec4[1];
                    vertex->normal.z = (float)vec4[2];
                }
                break;
            default:
                break;
            }
        }
        else if (mappingMode == FbxGeometryElement::eByPolygonVertex)
        {
            switch (normal->GetReferenceMode())
            {
            case FbxGeometryElement::eDirect:
                {
                    FbxVector4 vec4 = normal->GetDirectArray().GetAt(vertexIndex);
                    vertex->hasNormal = true;
                    vertex->normal.x = (float)vec4[0];
                    vertex->normal.y = (float)vec4[1];
                    vertex->normal.z = (float)vec4[2];
                }
                break;
            case FbxGeometryElement::eIndexToDirect:
                {
                    int id = normal->GetIndexArray().GetAt(vertexIndex);
                    FbxVector4 vec4 = normal->GetDirectArray().GetAt(id);
                    vertex->hasNormal = true;
                    vertex->normal.x = (float)vec4[0];
                    vertex->normal.y = (float)vec4[1];
                    vertex->normal.z = (float)vec4[2];
                }
                break;
            default:
                break;
            }
        }
    }
}
예제 #10
0
void fbxLoader2::readNormal(FbxMesh* mesh, int controlPointIndex, D3DXVECTOR3* normal)
{
	if (mesh->GetElementNormalCount()<1)
	{
		return;
	}

	FbxGeometryElementNormal* normalEl = mesh->GetElementNormal(0);

	switch(normalEl->GetMappingMode())
	{
	case FbxGeometryElement::eDirect:
		{
			switch(normalEl->GetReferenceMode())
			{
			case FbxGeometryElement::eDirect:
				{
					normal->x = (float)normalEl->GetDirectArray().GetAt(controlPointIndex).mData[0];
					normal->y = (float)normalEl->GetDirectArray().GetAt(controlPointIndex).mData[1];
					normal->z = (float)normalEl->GetDirectArray().GetAt(controlPointIndex).mData[2];
				}
				break;

			case FbxGeometryElement::eIndexToDirect:
				{
					int id = normalEl->GetIndexArray().GetAt(controlPointIndex);
					normal->x = (float)normalEl->GetDirectArray().GetAt(id).mData[0];
					normal->y = (float)normalEl->GetDirectArray().GetAt(id).mData[1];
					normal->z = (float)normalEl->GetDirectArray().GetAt(id).mData[2];
				}
				break;
			}
		}
		break;

	case FbxGeometryElement::eByPolygonVertex:
		{
			switch(normalEl->GetReferenceMode())
			{
			case FbxGeometryElement::eDirect:
				{
					normal->x = (float)normalEl->GetDirectArray().GetAt(controlPointIndex).mData[0];
					normal->y = (float)normalEl->GetDirectArray().GetAt(controlPointIndex).mData[1];
					normal->z = (float)normalEl->GetDirectArray().GetAt(controlPointIndex).mData[2];
				}
				break;

			case FbxGeometryElement::eIndexToDirect:
				{
					int id = normalEl->GetIndexArray().GetAt(controlPointIndex);
					normal->x = (float)normalEl->GetDirectArray().GetAt(id).mData[0];
					normal->y = (float)normalEl->GetDirectArray().GetAt(id).mData[1];
					normal->z = (float)normalEl->GetDirectArray().GetAt(id).mData[2];
				}
				break;
			}
		}
		break;
	default:
		int id = normalEl->GetIndexArray().GetAt(controlPointIndex);
		normal->x = (float)normalEl->GetDirectArray().GetAt(id).mData[0];
		normal->y = (float)normalEl->GetDirectArray().GetAt(id).mData[1];
		normal->z = (float)normalEl->GetDirectArray().GetAt(id).mData[2];
	}
}
예제 #11
0
//converts a FBX mesh to a CC mesh
static ccMesh* FromFbxMesh(FbxMesh* fbxMesh, FileIOFilter::LoadParameters& parameters)
{
	if (!fbxMesh)
		return 0;

	int polyCount = fbxMesh->GetPolygonCount();
	//fbxMesh->GetLayer(
	unsigned triCount = 0;
	unsigned polyVertCount = 0; //different from vertCount (vertices can be counted multiple times here!)
	//as we can't load all polygons (yet ;) we already look if we can load any!
	{
		unsigned skipped = 0;
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize == 3)
			{
				++triCount;
				polyVertCount += 3;
			}
			else if (pSize == 4)
			{
				triCount += 2;
				polyVertCount += 4;
			}
			else
			{
				++skipped;
			}
		}

		if (triCount == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle or quad found in mesh '%1'! (polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()));
			return 0;
		}
		else if (skipped != 0)
		{
			ccLog::Warning(QString("[FBX] Some polygons in mesh '%1' were ignored (%2): polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()).arg(skipped));
			return 0;
		}
	}

	int vertCount = fbxMesh->GetControlPointsCount();
	if (vertCount <= 0)
	{
		ccLog::Warning(QString("[FBX] Mesh '%1' has no vetex or no polygon?!").arg(fbxMesh->GetName()));
		return 0;
	}

	ccPointCloud* vertices = new ccPointCloud("vertices");
	ccMesh* mesh = new ccMesh(vertices);
	mesh->setName(fbxMesh->GetName());
	mesh->addChild(vertices);
	vertices->setEnabled(false);
	
	if (!mesh->reserve(static_cast<unsigned>(triCount)) || !vertices->reserve(vertCount))
	{
		ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1'!").arg(fbxMesh->GetName()));
		delete mesh;
		return 0;
	}

	//colors
	{
		for (int l=0; l<fbxMesh->GetElementVertexColorCount(); l++)
		{
			FbxGeometryElementVertexColor* vertColor = fbxMesh->GetElementVertexColor(l);
			//CC can only handle per-vertex colors
			if (vertColor->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				if (vertColor->GetReferenceMode() == FbxGeometryElement::eDirect
					|| vertColor->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
				{
					if (vertices->reserveTheRGBTable())
					{
						switch (vertColor->GetReferenceMode())
						{
						case FbxGeometryElement::eDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									FbxColor c = vertColor->GetDirectArray().GetAt(i);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* ccColor::MAX),
															static_cast<colorType>(c.mGreen	* ccColor::MAX),
															static_cast<colorType>(c.mBlue	* ccColor::MAX) );
								}
							}
							break;
						case FbxGeometryElement::eIndexToDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									int id = vertColor->GetIndexArray().GetAt(i);
									FbxColor c = vertColor->GetDirectArray().GetAt(id);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* ccColor::MAX),
															static_cast<colorType>(c.mGreen	* ccColor::MAX),
															static_cast<colorType>(c.mBlue	* ccColor::MAX) );
								}
							}
							break;
						default:
							assert(false);
							break;
						}

						vertices->showColors(true);
						mesh->showColors(true);
						break; //no need to look for other color fields (we won't be able to handle them!
					}
					else
					{
						ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' colors!").arg(fbxMesh->GetName()));
					}
				}
				else
				{
					ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
				}
			}
			else
			{
				ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
			}
		}
	}

	//normals can be per vertices or per-triangle
	int perPointNormals = -1;
	int perVertexNormals = -1;
	int perPolygonNormals = -1;
	{
		for (int j=0; j<fbxMesh->GetElementNormalCount(); j++)
		{
			FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(j);
			switch(leNormals->GetMappingMode())
			{
			case FbxGeometryElement::eByControlPoint:
				perPointNormals = j;
				break;
			case FbxGeometryElement::eByPolygonVertex:
				perVertexNormals = j;
				break;
			case FbxGeometryElement::eByPolygon:
				perPolygonNormals = j;
				break;
			default:
				//not handled
				break;
			}
		}
	}

	//per-point normals
	if (perPointNormals >= 0)
	{
		FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(perPointNormals);
		FbxLayerElement::EReferenceMode refMode = leNormals->GetReferenceMode();
		const FbxLayerElementArrayTemplate<FbxVector4>& normals = leNormals->GetDirectArray();
		assert(normals.GetCount() == vertCount);
		if (normals.GetCount() != vertCount)
		{
			ccLog::Warning(QString("[FBX] Wrong number of normals on mesh '%1'!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else if (!vertices->reserveTheNormsTable())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else
		{
			//import normals
			for (int i=0; i<vertCount; ++i)
			{
				int id = refMode != FbxGeometryElement::eDirect ? leNormals->GetIndexArray().GetAt(i) : i;
				FbxVector4 N = normals.GetAt(id);
				//convert to CC-structure
				CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
								static_cast<PointCoordinateType>(N.Buffer()[1]),
								static_cast<PointCoordinateType>(N.Buffer()[2]) );
				vertices->addNorm(Npc);
			}
			vertices->showNormals(true);
			mesh->showNormals(true);
			//no need to import the other normals (if any)
			perVertexNormals = -1;
			perPolygonNormals = -1;
		}
	}

	//per-triangle normals
	NormsIndexesTableType* normsTable = 0;
	if (perVertexNormals >= 0 || perPolygonNormals >= 0)
	{
		normsTable = new NormsIndexesTableType();
		if (!normsTable->reserve(polyVertCount) || !mesh->reservePerTriangleNormalIndexes())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			normsTable->release();
			normsTable = 0;
		}
		else
		{
			mesh->setTriNormsTable(normsTable);
			vertices->showNormals(true);
			mesh->showNormals(true);
		}
	}

	//materials
	ccMaterialSet* materials = 0;
	{
		FbxNode* lNode = fbxMesh->GetNode();
		int lMaterialCount = lNode ? lNode->GetMaterialCount() : 0;
		for (int i=0; i<lMaterialCount; i++)
		{
			FbxSurfaceMaterial *lBaseMaterial = lNode->GetMaterial(i);

			bool isLambert = lBaseMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId);
			bool isPhong = lBaseMaterial->GetClassId().Is(FbxSurfacePhong::ClassId);
			if (isLambert || isPhong)
			{
				ccMaterial::Shared mat(new ccMaterial(lBaseMaterial->GetName()));

				FbxSurfaceLambert* lLambertMat = static_cast<FbxSurfaceLambert*>(lBaseMaterial);
			
				float ambient[4];
				float diffuse[4];
				float emission[4];
				float specular[4];

				FbxSurfacePhong* lPhongMat = isPhong ? static_cast<FbxSurfacePhong*>(lBaseMaterial) : 0;

				for (int k=0; k<3; ++k)
				{
					ambient[k]  = static_cast<float>(lLambertMat->Ambient.Get()[k]);
					diffuse[k]  = static_cast<float>(lLambertMat->Diffuse.Get()[k]);
					emission[k] = static_cast<float>(lLambertMat->Emissive.Get()[k]);

					if (lPhongMat)
					{
						specular[k]		= static_cast<float>(lPhongMat->Specular.Get()[k]);
					}
				}

				mat->setAmbient(ambient);
				mat->setDiffuse(diffuse);
				mat->setEmission(emission);
				if (isPhong)
				{
					mat->setSpecular(specular);
					assert(lPhongMat);
					mat->setShininess(static_cast<float>(lPhongMat->Shininess));
				}

				//import associated texture (if any)
				{
					int lTextureIndex;
					FBXSDK_FOR_EACH_TEXTURE(lTextureIndex)
					{
						FbxProperty lProperty = lBaseMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[lTextureIndex]);
						if( lProperty.IsValid() )
						{
							int lTextureCount = lProperty.GetSrcObjectCount<FbxTexture>();
							FbxTexture* texture = 0; //we can handle only one texture per material! We'll take the non layered one by default (if any)
							for (int j = 0; j < lTextureCount; ++j)
							{
								//Here we have to check if it's layeredtextures, or just textures:
								FbxLayeredTexture *lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(j);
								if (lLayeredTexture)
								{
									//we don't handle layered textures!
									/*int lNbTextures = lLayeredTexture->GetSrcObjectCount<FbxTexture>();
									for (int k=0; k<lNbTextures; ++k)
									{
										FbxTexture* lTexture = lLayeredTexture->GetSrcObject<FbxTexture>(k);
										if(lTexture)
										{
										}
									}
									//*/
								}
								else
								{
									//non-layered texture
									FbxTexture* lTexture = lProperty.GetSrcObject<FbxTexture>(j);
									if(lTexture)
									{
										//we take the first non layered texture by default
										texture = lTexture;
										break;
									}
								}
							}

							if (texture)
							{
								FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(texture);
								if (lFileTexture)
								{
									const char* texAbsoluteFilename = lFileTexture->GetFileName();
									ccLog::PrintDebug(QString("[FBX] Texture absolue filename: %1").arg(texAbsoluteFilename));
									if (texAbsoluteFilename != 0 && texAbsoluteFilename[0] != 0)
									{
										if (!mat->loadAndSetTexture(texAbsoluteFilename))
										{
											ccLog::Warning(QString("[FBX] Failed to load texture file: %1").arg(texAbsoluteFilename));
										}
									}
								}
							}
						}
					}
				}

				if (!materials)
				{
					materials = new ccMaterialSet("materials");
					mesh->addChild(materials);
				}
				materials->addMaterial(mat);
			}
			else
			{
				ccLog::Warning(QString("[FBX] Material '%1' has an unhandled type").arg(lBaseMaterial->GetName()));
			}
		}
예제 #12
0
//===============================================================================================================================
bool FBXLoader::LoadVertexNormal(FbxMesh* mesh, int inCtrlPointIndex, int inVertexCounter, int normalElement, XMFLOAT3& outNormal)
{
	if (mesh->GetElementNormalCount() < 1)
	{
		throw std::exception("Invalid Normal Number");
	}
	
	int directIndex = -1;
	
	FbxGeometryElementNormal* vertexNormal = mesh->GetElementNormal(normalElement);
	
	switch (vertexNormal->GetMappingMode())
	{
		case FbxGeometryElement::eByControlPoint:
		{
			switch (vertexNormal->GetReferenceMode())
			{
				case FbxGeometryElement::eDirect:
				{
					directIndex = inCtrlPointIndex;
					//outNormal.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(inCtrlPointIndex).mData[0]);
					//outNormal.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(inCtrlPointIndex).mData[1]);
					//outNormal.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(inCtrlPointIndex).mData[2]);
				}
				break;
				case FbxGeometryElement::eIndexToDirect:
				{
					directIndex = vertexNormal->GetIndexArray().GetAt(inCtrlPointIndex);
					//int index = vertexNormal->GetIndexArray().GetAt(inCtrlPointIndex);
					//outNormal.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[0]);
					//outNormal.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[1]);
					//outNormal.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[2]);
				}
				break;
				default: throw std::exception("Invalid Reference");
			}
			break;
		}
		break;
		case FbxGeometryElement::eByPolygonVertex:
		{
			switch (vertexNormal->GetReferenceMode())
			{
				case FbxGeometryElement::eDirect:
				{
					directIndex = inVertexCounter;
					//outNormal.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(inVertexCounter).mData[0]);
					//outNormal.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(inVertexCounter).mData[1]);
					//outNormal.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(inVertexCounter).mData[2]);
				}
				break;
				case FbxGeometryElement::eIndexToDirect:
				{
					directIndex = vertexNormal->GetIndexArray().GetAt(inVertexCounter);
					//int index = vertexNormal->GetIndexArray().GetAt(inVertexCounter);
					//outNormal.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[0]);
					//outNormal.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[1]);
					//outNormal.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[2]);
				}
				break;
				default: throw std::exception("Invalid Reference");
			}
		}
		break;
	}
	
	if (directIndex != -1)
	{
		FbxVector4 norm = vertexNormal->GetDirectArray().GetAt(directIndex);
		
		outNormal = XMFLOAT3((float)norm.mData[0], (float)norm.mData[1], (float)norm.mData[2]);
		
		return true;
	}
	
	return false;
}
예제 #13
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);
}