bool hasUvTextures(FbxMesh* fbxMesh) {
	FbxStringList uvSetNames;
	fbxMesh->GetUVSetNames(uvSetNames);


	return (uvSetNames.GetCount() > 0);
}
// 頂点データ獲得
void GetFBXVertexData(FbxMesh* pMesh)
{
	// 頂点座標と法線ベクトル獲得
	std::vector<FbxVector4> positions, normals;
	FbxVector4 normal;

	// メモ:GetPolygonCount = 面数、GetPolygonSize = 頂点数
	for(int i = 0; i < pMesh->GetPolygonCount(); i++)
	{
		for(int j = 0; j < pMesh->GetPolygonSize(i); j++)
		{
			// 頂点座標
			positions.push_back(pMesh->GetControlPointAt(pMesh->GetPolygonVertex(i, j)));

			// 法線ベクトル
			pMesh->GetPolygonVertexNormal(i, j, normal);
			normals.push_back(normal);
		}
	}

	printf("頂点座標\n");
	for(unsigned int i = 0; i < positions.size(); ++i)
	{
		printf("[%d]:X = %f Y = %f Z = %f W = %f\n", i, positions[i].mData[0], positions[i].mData[1], positions[i].mData[2], positions[i].mData[2]);
	}
	puts("");

	printf("法線ベクトル\n");
	for(unsigned i = 0; i < normals.size(); ++i)
	{
		printf("[%d]:X = %f Y = %f Z = %f W = %f\n", i, normals[i].mData[0], normals[i].mData[1], normals[i].mData[2], normals[i].mData[2]);
	}
	puts("");

	// UVセットの名前配列獲得
	FbxStringList uvSetNames;
	pMesh->GetUVSetNames(uvSetNames);
	printf("UVSet数 = %d\n", uvSetNames.GetCount());

	bool unmapped = false;
	int UVCount = 0;

	for(int i = 0; i < uvSetNames.GetCount(); ++i)
	{
		printf("UVSet名[%d] = %s\n", i, uvSetNames.GetStringAt(i));

		for(int j = 0; j < pMesh->GetPolygonCount(); ++j)
		{
			for(int k = 0; k < pMesh->GetPolygonSize(j); ++k)
			{
				FbxVector2 UV;
				pMesh->GetPolygonVertexUV(j, k, uvSetNames.GetStringAt(i), UV, unmapped);
				printf("[%d]:U = %f V = %f\n", UVCount++, UV.mData[0], UV.mData[1]);
			}
		}

		puts("");
	}
}
void CFBXLoader::CopyVertexData(FbxMesh*	pMesh, FBX_MESH_NODE* meshNode)
{
	if(!pMesh)
		return ;

	int lPolygonCount = pMesh->GetPolygonCount();

	FbxVector4 pos, nor;
	
	meshNode->elements.numPosition = 1;
	meshNode->elements.numNormal = 1;

	unsigned int indx = 0;
	
	for(int i=0;i<lPolygonCount;i++)
	{
		// ポリゴン内の頂点数(一応、三角形化してるので3点のはずだがチェック)
		int lPolygonsize = pMesh->GetPolygonSize(i);

		for(int pol=0;pol<lPolygonsize;pol++)
		{
			int index = pMesh->GetPolygonVertex(i, pol);
			meshNode->indexArray.push_back(indx);

			pos = pMesh->GetControlPointAt(index);
			pMesh->GetPolygonVertexNormal(i,pol,nor);

			meshNode->m_positionArray.push_back( pos );
			meshNode->m_normalArray.push_back( nor );
	
			++indx;
		}
	}

	// UV処理(UVは2つ以上ある場合があるので別処理)
	FbxStringList	uvsetName;
	pMesh->GetUVSetNames(uvsetName);
	int numUVSet = uvsetName.GetCount();
	meshNode->elements.numUVSet = numUVSet;

	bool unmapped = false;

	for(int uv=0;uv<numUVSet;uv++)
	{
		meshNode->uvsetID[uvsetName.GetStringAt(uv)] = uv;
		for(int i=0;i<lPolygonCount;i++)
		{
			int lPolygonsize = pMesh->GetPolygonSize(i);

			for(int pol=0;pol<lPolygonsize;pol++)
			{
				FbxString name = uvsetName.GetStringAt(uv);
				FbxVector2 texCoord;
				pMesh->GetPolygonVertexUV( i, pol, name, texCoord, unmapped);
				meshNode->m_texcoordArray.push_back(texCoord);
			}
		}
	}
}
// 頂点データ獲得
void GetFBXVertexData(FbxMesh* pMesh, VertexDataArray& outVertexData)
{
	// 頂点座標と法線ベクトル獲得
	std::vector<FbxVector4> positions, normals;
	FbxVector4 normal;

	// メモ:GetPolygonCount = 面数、GetPolygonSize = 頂点数
	for(int i = 0; i < pMesh->GetPolygonCount(); i++)
	{
		for(int j = 0; j < pMesh->GetPolygonSize(i); j++)
		{
			// 頂点座標
			positions.push_back(pMesh->GetControlPointAt(pMesh->GetPolygonVertex(i, j)));

			// 法線ベクトル
			pMesh->GetPolygonVertexNormal(i, j, normal);
			normals.push_back(normal);
		}
	}

	// 配列初期化
	outVertexData.resize(positions.size());

	// 頂点座標と法線情報を格納
	for(size_t i = 0; i < outVertexData.size(); ++i)
	{
		fbxsdk::FbxVector4& pos		= positions[i];
		fbxsdk::FbxVector4& normal	= normals[i];

		outVertexData[i].pos	= DirectX::XMFLOAT3(pos.mData[0], pos.mData[1] , pos.mData[2]);
		outVertexData[i].normal = DirectX::XMFLOAT4(normal.mData[0], normal.mData[1], normal.mData[2], normal.mData[3]);
	}

	// UVセットの名前配列獲得
	FbxStringList uvSetNames;
	pMesh->GetUVSetNames(uvSetNames);

	bool unmapped = false;
	int UVCount = 0;

	for(int i = 0; i < uvSetNames.GetCount(); ++i)
	{
		for(int j = 0; j < pMesh->GetPolygonCount(); ++j)
		{
			for(int k = 0; k < pMesh->GetPolygonSize(j); ++k)
			{
				FbxVector2 UV;
				pMesh->GetPolygonVertexUV(j, k, uvSetNames.GetStringAt(i), UV, unmapped);

				if(outVertexData.size() > UVCount)
				{
					outVertexData[UVCount].uv = DirectX::XMFLOAT2(UV.mData[0], UV.mData[1]);
				}
				UVCount++;
			}
		}
	}
}
Example #5
0
BabylonMesh::BabylonMesh(BabylonNode* node) :
	BabylonAbstractMesh(node),
	_isEnabled(true),
	_isVisible(true),
	_billboardMode(0),
	_visibility(1),
	_skeletonId(-1),
	_pickable(true),
	_hasVertexAlpha(false),
	_checkCollision(false),
	_receiveShadows(false),
	_infiniteDistance(false),
	_autoAnimate(false),
	_autoAnimateFrom(0),
	_autoAnimateTo(0),
	_autoAnimateLoop(false),
	_showBoundingBox(false),
	_showSubMeshesBoundingBox(false),
	_applyFog(false),
	_alphaIndex(0)
{

	pivotMatrix.SetIdentity();
	auto fbxNode = node->fbxNode();
	
	std::string ansiName = fbxNode->GetName();
	name(std::wstring(ansiName.begin(), ansiName.end()));
	id(getNodeId(fbxNode));
	auto parent = fbxNode->GetParent();
	if (parent) {
		parentId(getNodeId(parent));
	}
	pivotMatrix = ConvertToBabylonCoordinateSystem( GetGeometryTransformation(fbxNode));

	auto animStack = fbxNode->GetScene()->GetSrcObject<FbxAnimStack>(0);
	FbxString animStackName = animStack->GetName();
	FbxTakeInfo* takeInfo = fbxNode->GetScene()->GetTakeInfo(animStackName);
	auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
	auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
	auto startFrame = takeInfo->mLocalTimeSpan.GetStart().GetFrameCount(animTimeMode);
	auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
	auto animLengthInFrame = endFrame - startFrame + 1;
	_visibility = static_cast<float>(node->fbxNode()->Visibility.Get());
	auto posAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"position", L"position", true, 0, static_cast<int>(animLengthInFrame), true);
	auto rotAnim = std::make_shared<BabylonAnimation<babylon_vector4>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"rotationQuaternion", L"rotationQuaternion", true, 0, static_cast<int>(animLengthInFrame), true);
	auto scaleAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"scaling", L"scaling", true, 0, static_cast<int>(animLengthInFrame), true);
	auto visibilityAnim = std::make_shared<BabylonAnimation<float>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"visibility", L"visibility", true, 0, static_cast<int>(animLengthInFrame), true);
	auto mesh = fbxNode->GetMesh();
	_isVisible = fbxNode->Show.Get();
	
	auto rotCurveNode = fbxNode->LclRotation.GetCurveNode();
	auto translateCurveNode = fbxNode->LclTranslation.GetCurveNode();
	auto scalingCurveNode = fbxNode->LclScaling.GetCurveNode();
	auto visibilityCurveNode = fbxNode->Visibility.GetCurveNode();
	if (rotCurveNode || translateCurveNode || scalingCurveNode) {
		for (auto ix = 0; ix < animLengthInFrame; ix++) {
			FbxTime currTime;
			currTime.SetFrame(startFrame + ix, animTimeMode);

			babylon_animation_key<babylon_vector3> poskey;
			babylon_animation_key<babylon_vector4> rotkey;
			babylon_animation_key<babylon_vector3> scalekey;
			poskey.frame = ix;
			rotkey.frame = ix;
			scalekey.frame = ix;
			auto currTransform = node->GetLocal(currTime);
			poskey.values = currTransform.translation();
			rotkey.values = currTransform.rotationQuaternion();
			scalekey.values = currTransform.scaling();
			posAnim->appendKey(poskey);
			rotAnim->appendKey(rotkey);
			scaleAnim->appendKey(scalekey);


		}
	}
	if (visibilityCurveNode) {
		for (auto ix = 0; ix < animLengthInFrame; ix++) {
			FbxTime currTime;
			currTime.SetFrame(startFrame + ix, animTimeMode);

			babylon_animation_key<float> visibilityKey;

			visibilityKey.frame = ix;

			visibilityKey.values = static_cast<float>(node->fbxNode()->Visibility.EvaluateValue(currTime));

			visibilityAnim->appendKey(visibilityKey);


		}
	}
	
	if (!posAnim->isConstant()){
		animations.push_back(posAnim);
	}
	if (!rotAnim->isConstant()){
		animations.push_back(rotAnim);
	}
	if (!scaleAnim->isConstant()){
		animations.push_back(scaleAnim);
	}
	if (!visibilityAnim->isConstant()) {
		animations.push_back(visibilityAnim);
	}
	if (!mesh) {
		return;
	}
	if (mesh->GetPolygonCount() == 0){
		return;
	}

	_receiveShadows =  mesh->ReceiveShadow.Get();
	FbxGeometryConverter conv(mesh->GetFbxManager());
	conv.ComputePolygonSmoothingFromEdgeSmoothing(mesh);
	if (!mesh->IsTriangleMesh()) {
		mesh = (FbxMesh*) conv.Triangulate(mesh, true);
	}


	mesh->RemoveBadPolygons();
	mesh->GenerateNormals();

	FbxStringList uvSetNameList;
	mesh->GetUVSetNames(uvSetNameList);
	std::vector<std::string> uniqueUVSets;

	int uvCount = uvSetNameList.GetCount();
	for (int i = 0; i < uvCount; ++i) {
		std::string value = uvSetNameList.GetStringAt(i);
		if (std::find(uniqueUVSets.begin(), uniqueUVSets.end(), value) == uniqueUVSets.end()) {
			uniqueUVSets.push_back(value);
		}
	}
	uvsets = uniqueUVSets;
	bool hasUv = uniqueUVSets.size() > 0;
	bool hasUv2 = uniqueUVSets.size() > 1;
	bool hasUv3 = uniqueUVSets.size() > 2;
	bool hasUv4 = uniqueUVSets.size() > 3;
	bool hasUv5 = uniqueUVSets.size() > 4;
	bool hasUv6 = uniqueUVSets.size() > 5;
	std::string uvSetName;
	std::string uv2SetName;
	std::string uv3SetName;
	std::string uv4SetName;
	std::string uv5SetName;
	std::string uv6SetName;
	if (hasUv) {
		uvSetName = uniqueUVSets[0];
	}
	if (hasUv2) {
		uv2SetName = uniqueUVSets[1];
	}
	if (hasUv3) {
		uv3SetName = uniqueUVSets[2];
	}
	if (hasUv4) {
		uv4SetName = uniqueUVSets[3];
	}
	if (hasUv5) {
		uv5SetName = uniqueUVSets[4];
	}
	if (hasUv6) {
		uv6SetName = uniqueUVSets[5];
	}
	auto colors = mesh->GetElementVertexColor();
	FbxLayerElement::EMappingMode colorMappingMode;
	FbxLayerElement::EReferenceMode colorReferenceMode;
	if (colors) {
		colorMappingMode = colors->GetMappingMode();
		colorReferenceMode = colors->GetReferenceMode();
	}
	auto normals = mesh->GetElementNormal();
	FbxGeometryElementUV* uvs = nullptr;
	FbxGeometryElementUV* uvs2 = nullptr;
	FbxGeometryElementUV* uvs3 = nullptr;
	FbxGeometryElementUV* uvs4 = nullptr;
	FbxGeometryElementUV* uvs5 = nullptr;
	FbxGeometryElementUV* uvs6 = nullptr;
	FbxLayerElement::EMappingMode uvsMappingMode;
	FbxLayerElement::EReferenceMode uvsReferenceMode;
	FbxLayerElement::EMappingMode uvs2MappingMode;
	FbxLayerElement::EReferenceMode uvs2ReferenceMode;
	FbxLayerElement::EMappingMode uvs3MappingMode;
	FbxLayerElement::EReferenceMode uvs3ReferenceMode;
	FbxLayerElement::EMappingMode uvs4MappingMode;
	FbxLayerElement::EReferenceMode uvs4ReferenceMode;
	FbxLayerElement::EMappingMode uvs5MappingMode;
	FbxLayerElement::EReferenceMode uvs5ReferenceMode;
	FbxLayerElement::EMappingMode uvs6MappingMode;
	FbxLayerElement::EReferenceMode uvs6ReferenceMode;
	if (hasUv) {
		uvs = mesh->GetElementUV(uvSetName.c_str());
		uvsMappingMode = uvs->GetMappingMode();
		uvsReferenceMode = uvs->GetReferenceMode();
	}
	if (hasUv2) {
		uvs2 = mesh->GetElementUV(uv2SetName.c_str());
		uvs2MappingMode = uvs2->GetMappingMode();
		uvs2ReferenceMode = uvs2->GetReferenceMode();
	}
	if (hasUv3) {
		uvs3 = mesh->GetElementUV(uv3SetName.c_str());
		uvs3MappingMode = uvs3->GetMappingMode();
		uvs3ReferenceMode = uvs3->GetReferenceMode();
	}
	if (hasUv4) {
		uvs4 = mesh->GetElementUV(uv4SetName.c_str());
		uvs4MappingMode = uvs4->GetMappingMode();
		uvs4ReferenceMode = uvs4->GetReferenceMode();
	}
	if (hasUv5) {
		uvs5 = mesh->GetElementUV(uv5SetName.c_str());
		uvs5MappingMode = uvs5->GetMappingMode();
		uvs5ReferenceMode = uvs5->GetReferenceMode();
	}
	if (hasUv6) {
		uvs6 = mesh->GetElementUV(uv6SetName.c_str());
		uvs6MappingMode = uvs6->GetMappingMode();
		uvs6ReferenceMode = uvs6->GetReferenceMode();
	}

	auto normalMappingMode = normals->GetMappingMode();
	auto normalReferenceMode = normals->GetReferenceMode();
	std::vector<SubmeshData> submeshes;

	auto materialCount = node->fbxNode()->GetMaterialCount();
	if (materialCount == 0) {
		materialCount = 1;
	}
	submeshes.resize(materialCount);
	auto baseLayer = mesh->GetLayer(0);
	auto materials = baseLayer->GetMaterials();
	FbxLayerElement::EMappingMode materialMappingMode = materials ?
		materials->GetMappingMode() : FbxLayerElement::eByPolygon;

	// extract deformers
	SkinInfo skinInfo(fbxNode);
	if (skinInfo.hasSkin()){
		associatedSkeleton = std::make_shared<BabylonSkeleton>();
		skinInfo.buildBabylonSkeleton(*associatedSkeleton);
	}

	auto triangleCount = mesh->GetPolygonCount();
	for (int triangleIndex = 0; triangleIndex < triangleCount; ++triangleIndex) {

		int materialIndex = 0;
		if (materialCount > 0 && materials) {
			switch (materialMappingMode) {
			case FbxLayerElement::eAllSame:
				materialIndex = materials->GetIndexArray().GetAt(0);
				break;
			case FbxLayerElement::eByPolygon:
				materialIndex = materials->GetIndexArray().GetAt(triangleIndex);
			}
		}

		auto& submesh = submeshes[materialIndex];
		triangle t;
		for (int cornerIndex = 0; cornerIndex < 3; ++cornerIndex) {
			auto controlPointIndex = mesh->GetPolygonVertex(triangleIndex, cornerIndex);
			auto vertexIndex = triangleIndex * 3 + cornerIndex;
			auto position = mesh->GetControlPoints()[controlPointIndex];
			position[2] = -position[2];

			BabylonVertex v;
			v.position = position;
			if (normals) {
				int normalMapIndex = (normalMappingMode == FbxLayerElement::eByControlPoint) ?
				controlPointIndex : vertexIndex;
				int normalValueIndex = (normalReferenceMode == FbxLayerElement::eDirect) ?
				normalMapIndex : normals->GetIndexArray().GetAt(normalMapIndex);
				v.normal = normals->GetDirectArray().GetAt(normalValueIndex);
				v.normal.z = -v.normal.z;
			}
			if (colors) {
				int mappingIndex = (colorMappingMode == FbxLayerElement::eByControlPoint) ?
				controlPointIndex : vertexIndex;
				int valueIndex = (colorReferenceMode == FbxLayerElement::eDirect) ?
				mappingIndex : colors->GetIndexArray().GetAt(mappingIndex);
				v.color = colors->GetDirectArray().GetAt(valueIndex);
			}
			if (uvs) {
				int mappingIndex = (uvsMappingMode == FbxLayerElement::eByControlPoint) ?
				controlPointIndex : vertexIndex;
				int valueIndex = (uvsReferenceMode == FbxLayerElement::eDirect) ?
				mappingIndex : uvs->GetIndexArray().GetAt(mappingIndex);
				v.uv = uvs->GetDirectArray().GetAt(valueIndex);
				//v.uv.y = 1 - v.uv.y;
			}

			if (uvs2) {
				int mappingIndex = (uvs2MappingMode == FbxLayerElement::eByControlPoint) ?
					controlPointIndex : vertexIndex;
				int valueIndex = (uvs2ReferenceMode == FbxLayerElement::eDirect) ?
					mappingIndex : uvs2->GetIndexArray().GetAt(mappingIndex);
				v.uv2 = uvs2->GetDirectArray().GetAt(valueIndex);
			}
			if (uvs3) {
				int mappingIndex = (uvs3MappingMode == FbxLayerElement::eByControlPoint) ?
					controlPointIndex : vertexIndex;
				int valueIndex = (uvs3ReferenceMode == FbxLayerElement::eDirect) ?
					mappingIndex : uvs3->GetIndexArray().GetAt(mappingIndex);
				v.uv3 = uvs3->GetDirectArray().GetAt(valueIndex);
			}
			if (uvs4) {
				int mappingIndex = (uvs4MappingMode == FbxLayerElement::eByControlPoint) ?
					controlPointIndex : vertexIndex;
				int valueIndex = (uvs4ReferenceMode == FbxLayerElement::eDirect) ?
					mappingIndex : uvs4->GetIndexArray().GetAt(mappingIndex);
				v.uv4 = uvs4->GetDirectArray().GetAt(valueIndex);
			}
			if (uvs5) {
				int mappingIndex = (uvs5MappingMode == FbxLayerElement::eByControlPoint) ?
					controlPointIndex : vertexIndex;
				int valueIndex = (uvs5ReferenceMode == FbxLayerElement::eDirect) ?
					mappingIndex : uvs5->GetIndexArray().GetAt(mappingIndex);
				v.uv5 = uvs5->GetDirectArray().GetAt(valueIndex);
			}
			if (uvs6) {
				int mappingIndex = (uvs6MappingMode == FbxLayerElement::eByControlPoint) ?
					controlPointIndex : vertexIndex;
				int valueIndex = (uvs6ReferenceMode == FbxLayerElement::eDirect) ?
					mappingIndex : uvs6->GetIndexArray().GetAt(mappingIndex);
				v.uv6 = uvs6->GetDirectArray().GetAt(valueIndex);
			}
			if (skinInfo.hasSkin()){
				auto& skinData = skinInfo.controlPointBoneIndicesAndWeights(controlPointIndex);
				for (auto boneix = 0; boneix < skinData.size()&&boneix<4; ++boneix){
					v.boneIndices[boneix] = skinData[boneix].index;
					v.boneWeights[boneix] = static_cast<float>(skinData[boneix].weight);
				}
				for (auto boneix = skinData.size(); boneix < 4; ++boneix){

					v.boneIndices[boneix] = skinInfo.bonesCount();
					v.boneWeights[boneix] = 0;
				}
			}
			auto foundVertex = submesh.knownVertices.find(v);
			if (foundVertex != submesh.knownVertices.end()) {
				//submesh.indices.push_back(foundVertex->second);
				t.indices[cornerIndex] = foundVertex->second;
			}
			else {
				auto index = static_cast<int>(submesh.vertices.size());
				submesh.vertices.push_back(v);
				//submesh.indices.push_back(index);
				submesh.knownVertices[v] = index;
				t.indices[cornerIndex] = index;
			}
		}
		if (submesh.knownTriangles.insert(t).second) {
			submesh.indices.push_back(t.indices[0]);
			submesh.indices.push_back(t.indices[1]);
			submesh.indices.push_back(t.indices[2]);
		}
		else {
			std::cout << "duplicate triangle found (and eliminated) in " << fbxNode->GetName() << std::endl;
		}

	}
	std::uint32_t vertexOffset = 0;

	for (auto matIndex = 0u; matIndex < submeshes.size(); ++matIndex) {
		auto& submesh = submeshes[matIndex];
		BabylonSubmesh babsubmesh;
		babsubmesh.indexCount = static_cast<int>(submesh.indices.size());
		babsubmesh.indexStart = static_cast<int>(_indices.size());
		babsubmesh.materialIndex = matIndex;
		babsubmesh.verticesCount = static_cast<int>(submesh.vertices.size());
		babsubmesh.verticesStart = static_cast<int>(_positions.size());
		for (auto& v : submesh.vertices) {
			_positions.push_back(v.position);
			if (normals) {
				_normals.push_back(v.normal);
			}
			if (colors) {
				_colors.push_back(v.color);
			}
			if (uvs) {
				_uvs.push_back(v.uv);
			}
			if (uvs2) {
				_uvs2.push_back(v.uv2);
			}
			if (uvs3) {
				_uvs3.push_back(v.uv3);
			}
			if (uvs4) {
				_uvs4.push_back(v.uv4);
			}
			if (uvs5) {
				_uvs5.push_back(v.uv5);
			}
			if (uvs6) {
				_uvs6.push_back(v.uv6);
			}
			if (skinInfo.hasSkin()){
				 float weight0 = v.boneWeights[0];
				 float weight1 = v.boneWeights[1];
				 float weight2 = v.boneWeights[2];
				 int bone0 = v.boneIndices[0];
				 int bone1 = v.boneIndices[1];
				 int bone2 = v.boneIndices[2];
				 int bone3 = v.boneIndices[3];
               
				_boneWeights.push_back(babylon_vector4( weight0, weight1, weight2, 1.0f - weight0 - weight1 - weight2));
                _boneIndices.push_back((bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0);
			}
		}
		for (auto i : submesh.indices) {
			_indices.push_back(i + vertexOffset);
		}

		vertexOffset = static_cast<int>(_positions.size());
		_submeshes.push_back(babsubmesh);
	}



}
void MeshImporter::LoadUV(FbxMesh* fbxMesh, Vertex* vertices, unsigned int* indices)
{
	//get all UV set names
	FbxStringList UVSetNameList;
	fbxMesh->GetUVSetNames(UVSetNameList);

	//iterating over all uv sets
	for (int lUVSetIndex = 0; lUVSetIndex < UVSetNameList.GetCount(); lUVSetIndex++)
	{
		//get lUVSetIndex-th uv set
		const char* UVSetName = UVSetNameList.GetStringAt(lUVSetIndex);
		const FbxGeometryElementUV* UVElement = fbxMesh->GetElementUV(UVSetName);

		if (!UVElement)
		{
			continue;
		}

		// only support mapping mode eByPolygonVertex and eByControlPoint
		if (UVElement->GetMappingMode() != FbxGeometryElement::eByPolygonVertex &&
			UVElement->GetMappingMode() != FbxGeometryElement::eByControlPoint)
		{
			return;
		}

		//index array, where holds the index referenced to the uv data
		const bool useIndex = UVElement->GetReferenceMode() != FbxGeometryElement::eDirect;
		const int indexCount = (useIndex) ? UVElement->GetIndexArray().GetCount() : 0;

		//iterating through the data by polygon
		const int polyCount = fbxMesh->GetPolygonCount();

		if (UVElement->GetMappingMode() == FbxGeometryElement::eByControlPoint)
		{
			for (int polyIndex = 0; polyIndex < polyCount; ++polyIndex)
			{
				// build the max index array that we need to pass into MakePoly
				const unsigned int polySize = fbxMesh->GetPolygonSize(polyIndex);

				for (unsigned int vertIndex = 0; vertIndex < polySize; ++vertIndex)
				{
					FbxVector2 UVValue;

					// get the index of the current vertex in control points array
					int polyVertIndex = fbxMesh->GetPolygonVertex(polyIndex, vertIndex);

					// the UV index depends on the reference mode
					int UVIndex = useIndex ? UVElement->GetIndexArray().GetAt(polyVertIndex) : polyVertIndex;

					UVValue = UVElement->GetDirectArray().GetAt(UVIndex);

					// Copy texture coordinates
					// For indexed drawing
					//unsigned int vertexIndex = indices[polyVertIndex];

					vertices[polyVertIndex].uv.x = (float)UVValue.mData[0];
					vertices[polyVertIndex].uv.y = 1.0f - (float)UVValue.mData[1];
				}
			}

			PrintTab("UV got eByControlPoint!!");
		}
		else if (UVElement->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
		{
			int polyIndexCounter = 0;

			for (int polyIndex = 0; polyIndex < polyCount; ++polyIndex)
			{
				// build the max index array that we need to pass into MakePoly
				const int polySize = fbxMesh->GetPolygonSize(polyIndex);

				for (int vertIndex = 0; vertIndex < polySize; ++vertIndex)
				{
					if (polyIndexCounter < indexCount)
					{
						FbxVector2 UVValue;

						// the UV index depends on the reference mode
						int UVIndex = useIndex ? UVElement->GetIndexArray().GetAt(polyIndexCounter) : polyIndexCounter;

						UVValue = UVElement->GetDirectArray().GetAt(UVIndex);

						// Copy texture coordinates
						// For indexed drawing
						//unsigned int vertexIndex = indices[polyIndexCounter];

						vertices[polyIndexCounter].uv.x = (float)UVValue.mData[0];
						vertices[polyIndexCounter].uv.y = 1.0f - (float)UVValue.mData[1];

						polyIndexCounter++;
					}
				}
			}

			PrintTab("UV got eByPolygonVertex!!");
		}
	}
}
Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
{
    // Check if this mesh has already been loaded.
    Mesh* mesh = getMesh(fbxMesh->GetUniqueID());
    if (mesh)
    {
        return mesh;
    }
    mesh = new Mesh();
    // GamePlay requires that a mesh have a unique ID but FbxMesh doesn't have a string ID.
    const char* name = fbxMesh->GetNode()->GetName();
    if (name)
    {
        string id(name);
        id.append("_Mesh");
        mesh->setId(id);
    }

    // The number of mesh parts is equal to the number of materials that affect this mesh.
    // There is always at least one mesh part.
    vector<MeshPart*> meshParts;
    const int materialCount = fbxMesh->GetNode()->GetMaterialCount();
    int meshPartSize = (materialCount > 0) ? materialCount : 1;
    for (int i = 0; i < meshPartSize; ++i)
    {
        meshParts.push_back(new MeshPart());
    }

    // Find the blend weights and blend indices if this mesh is skinned.
    vector<vector<Vector2> > weights;
    bool hasSkin = loadBlendWeights(fbxMesh, weights);
    
    // Get list of uv sets for mesh
    FbxStringList uvSetNameList;
    fbxMesh->GetUVSetNames(uvSetNameList);
    const int uvSetCount = uvSetNameList.GetCount();

    int vertexIndex = 0;
    FbxVector4* controlPoints = fbxMesh->GetControlPoints();
    const int polygonCount = fbxMesh->GetPolygonCount();
    for (int polyIndex = 0; polyIndex < polygonCount; ++polyIndex)
    {
        const int polygonSize = fbxMesh->GetPolygonSize(polyIndex);
        for (int posInPoly = 0; posInPoly < polygonSize; ++posInPoly)
        {
            int controlPointIndex = fbxMesh->GetPolygonVertex(polyIndex, posInPoly);
            Vertex vertex;

            FbxVector4& position = controlPoints[controlPointIndex];
            vertex.position.x = (float)position[0];
            vertex.position.y = (float)position[1];
            vertex.position.z = (float)position[2];

            // Load tex coords for all uv sets
            for (int uvSetIndex = 0; uvSetIndex < uvSetCount; ++uvSetIndex)
            {
                const FbxGeometryElementUV* uvElement = fbxMesh->GetElementUV(uvSetNameList.GetStringAt(uvSetIndex));
                if (uvElement)
                    loadTextureCoords(fbxMesh, uvElement, uvSetIndex, polyIndex, posInPoly, vertexIndex, &vertex);
            }

            // Load other data
            loadNormal(fbxMesh, vertexIndex, controlPointIndex, &vertex);
            loadTangent(fbxMesh, vertexIndex, controlPointIndex, &vertex);
            loadBinormal(fbxMesh, vertexIndex, controlPointIndex, &vertex);
            loadVertexColor(fbxMesh, vertexIndex, controlPointIndex, &vertex);

            if (hasSkin)
            {
                loadBlendData(weights[controlPointIndex], &vertex);
            }

            // Determine which mesh part this vertex index should be added to based on the material that affects it.
            int meshPartIndex = 0;
            const int elementMatrialCount = fbxMesh->GetElementMaterialCount();
            for (int k = 0; k < elementMatrialCount; ++k)
            {
                FbxGeometryElementMaterial* elementMaterial = fbxMesh->GetElementMaterial(k);
                meshPartIndex = elementMaterial->GetIndexArray().GetAt(polyIndex);
            }

            // Add the vertex to the mesh if it hasn't already been added and find the vertex index.
            unsigned int index;
            if (mesh->contains(vertex))
            {
                index = mesh->getVertexIndex(vertex);
            }
            else
            {
                index = mesh->addVertex(vertex);
            }
            meshParts[meshPartIndex]->addIndex(index);
            vertexIndex++;
        }
    }

    const size_t meshpartsSize = meshParts.size();
    for (size_t i = 0; i < meshpartsSize; ++i)
    {
        mesh->addMeshPart(meshParts[i]);
    }

    // The order that the vertex elements are add to the list matters.
    // It should be the same order as how the Vertex data is written.

    // Position
    mesh->addVetexAttribute(POSITION, Vertex::POSITION_COUNT);

    const Vertex& vertex = mesh->vertices[0];
    // Normals
    if (vertex.hasNormal)
    {
        mesh->addVetexAttribute(NORMAL, Vertex::NORMAL_COUNT);
    }
    // Tangents
    if (vertex.hasTangent)
    {
        mesh->addVetexAttribute(TANGENT, Vertex::TANGENT_COUNT);
    }
    // Binormals
    if (vertex.hasBinormal)
    {
        mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT);
    }
    // Texture Coordinates
    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
    {
        if (vertex.hasTexCoord[i])
        {
            mesh->addVetexAttribute(TEXCOORD0 + i, Vertex::TEXCOORD_COUNT);
        }
    }
    // Diffuse Color
    if (vertex.hasDiffuse)
    {
        mesh->addVetexAttribute(COLOR, Vertex::DIFFUSE_COUNT);
    }
    // Skinning BlendWeights BlendIndices
    if (vertex.hasWeights)
    {
        mesh->addVetexAttribute(BLENDWEIGHTS, Vertex::BLEND_WEIGHTS_COUNT);
        mesh->addVetexAttribute(BLENDINDICES, Vertex::BLEND_INDICES_COUNT);
    }

    _gamePlayFile.addMesh(mesh);
    saveMesh(fbxMesh->GetUniqueID(), mesh);
    return mesh;
}
Example #8
0
		void FbxLoader::ProcessMesh(FbxNode* node, Node& meshNode)
		{
			FbxMesh* currMesh = node->GetMesh();

			if(!currMesh)
				return;

			FbxLayerElementTangent* tangents = nullptr;

			if(useNormalMap) {
				if(currMesh->GetElementTangentCount() < 1) {
					currMesh->GenerateTangentsDataForAllUVSets();
					tangents = currMesh->GetElementTangent();
				}
			}

			std::map<int, std::vector<Vertex>> subMeshes;

			int vertCounter = 0;
			const int polygonCount = currMesh->GetPolygonCount();

			for(int i = 0; i < polygonCount; i++) {
				const int polySize = currMesh->GetPolygonSize(i);
				int nMaterials = node->GetMaterialCount();
				auto elementMaterial = currMesh->GetElementMaterial();
				int mi = 0;
				if(elementMaterial)
					mi = currMesh->GetElementMaterial()->GetIndexArray()[i];

				for(int j = 2; j >= 0; --j) {
					int ctrlIndex = currMesh->GetPolygonVertex(i, j);
					auto& currCtrlPoint = meshNode.controlPoints[ctrlIndex];
					FbxVector4 v4;

					auto& pos = currCtrlPoint.position * factor;
					currMesh->GetPolygonVertexNormal(i, j, v4);
					Vector3 normal = { (float)v4[0], (float)v4[1], (float)v4[2] };
					Vector3 tangent = { 0, 0, 0 };
					if(useNormalMap) {
						ReadTangent(tangents, ctrlIndex, vertCounter, v4);
						tangent = { (float)v4[0], (float)v4[1], (float)v4[2] };
					}
				
					Vector2 uv;
					FbxStringList uvSetNames;
					currMesh->GetUVSetNames(uvSetNames);
					bool unmapped = false;
					// supports one uv set only
					if(uvSetNames.GetCount() > 0) {
						FbxVector2 UV;
						currMesh->GetPolygonVertexUV(i, j, uvSetNames[0], UV, unmapped);
						uv = { (float)UV[0], (float)UV[1] };
					}
				
					if(axismode == eLeftHanded) {
						pos.x *= -1; uv.y = 1 - uv.y;
						normal.x *= -1; tangent.x *= -1;
					}

					Vector4 weights = { 0, 0, 0, 0 };
					Byte4 indices = { 0, 0, 0, 0 };

					int blendCount = (int)min(currCtrlPoint.blendWeigths.size(), 4);
					if(blendCount > 0) {
						meshNode.useSkinnedMesh = true;
						if(currCtrlPoint.blendWeigths.size() > 4)
							sort(currCtrlPoint.blendWeigths.begin(), currCtrlPoint.blendWeigths.end());
						for(int i = 0; i < blendCount; i++) {
							weights[i] = currCtrlPoint.blendWeigths[i].weight;
							indices.m[i] = currCtrlPoint.blendWeigths[i].boneIndex;
						}
					}
	
					Vertex temp = { pos, uv, normal, tangent, indices, weights };
					subMeshes[mi].push_back(temp);
				}
				++vertCounter;
			}

			if(subMeshes.size() > 0) {
				int index = 0;
				meshNode.meshes.reserve(vertCounter);
				meshNode.vertIndices.reserve(vertCounter);
				meshNode.vertexCountOfSubMesh.reserve(subMeshes.size());
				for(auto& pair : subMeshes) {
					auto& m = pair.second;
					for(int i = 0; i < m.size(); ++i)
						meshNode.vertIndices.emplace_back(index++);
					meshNode.vertexCountOfSubMesh.push_back((int)m.size());
					meshNode.meshes.insert(meshNode.meshes.end(), m.begin(), m.end());
				}
			}
			subMeshes.clear();
		}
Example #9
0
//ур╣╫ак
bool VBOMesh::Initialize(const FbxMesh *pMesh)
{
	if (!pMesh->GetNode())
		return false;

	const int lPolygonCount = pMesh->GetPolygonCount();

	// Count the polygon count of each material
	FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
	FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
	if (pMesh->GetElementMaterial())
	{
		lMaterialIndice = &pMesh->GetElementMaterial()->GetIndexArray();
		lMaterialMappingMode = pMesh->GetElementMaterial()->GetMappingMode();
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
			if (lMaterialIndice->GetCount() == lPolygonCount)
			{
				// Count the faces of each material
				for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
				{
					const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
					if (mSubMeshes.GetCount() < lMaterialIndex + 1)
					{
						mSubMeshes.Resize(lMaterialIndex + 1);
					}
					if (mSubMeshes[lMaterialIndex] == NULL)
					{
						mSubMeshes[lMaterialIndex] = new SubMesh;
					}
					mSubMeshes[lMaterialIndex]->TriangleCount += 1;
				}

				// Make sure we have no "holes" (NULL) in the mSubMeshes table. This can happen
				// if, in the loop above, we resized the mSubMeshes by more than one slot.
				for (int i = 0; i < mSubMeshes.GetCount(); i++)
				{
					if (mSubMeshes[i] == NULL)
						mSubMeshes[i] = new SubMesh;
				}

				// Record the offset (how many vertex)
				const int lMaterialCount = mSubMeshes.GetCount();
				int lOffset = 0;
				for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
				{
					mSubMeshes[lIndex]->IndexOffset = lOffset;
					lOffset += mSubMeshes[lIndex]->TriangleCount * 3;
					// This will be used as counter in the following procedures, reset to zero
					mSubMeshes[lIndex]->TriangleCount = 0;
				}
				FBX_ASSERT(lOffset == lPolygonCount * 3);
			}
		}
	}

	// All faces will use the same material.
	if (mSubMeshes.GetCount() == 0)
	{
		mSubMeshes.Resize(1);
		mSubMeshes[0] = new SubMesh();
	}

	// Congregate all the data of a mesh to be cached in VBOs.
	// If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.
	mHasNormal = pMesh->GetElementNormalCount() > 0;
	mHasUV = pMesh->GetElementUVCount() > 0;
	FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
	FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
	if (mHasNormal)
	{
		lNormalMappingMode = pMesh->GetElementNormal(0)->GetMappingMode();
		if (lNormalMappingMode == FbxGeometryElement::eNone)
		{
			mHasNormal = false;
		}
		if (mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint)
		{
			mAllByControlPoint = false;
		}
	}
	if (mHasUV)
	{
		lUVMappingMode = pMesh->GetElementUV(0)->GetMappingMode();
		if (lUVMappingMode == FbxGeometryElement::eNone)
		{
			mHasUV = false;
		}
		if (mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint)
		{
			mAllByControlPoint = false;
		}
	}

	// Allocate the array memory, by control point or by polygon vertex.
	int lPolygonVertexCount = pMesh->GetControlPointsCount();
	if (!mAllByControlPoint)
	{
		lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	}
	float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE];
	unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT];
	float * lNormals = NULL;
	if (mHasNormal)
	{
		lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE];
	}
	float * lUVs = NULL;
	FbxStringList lUVNames;
	pMesh->GetUVSetNames(lUVNames);
	const char * lUVName = NULL;
	if (mHasUV && lUVNames.GetCount())
	{
		lUVs = new float[lPolygonVertexCount * UV_STRIDE];
		lUVName = lUVNames[0];
	}

	// Populate the array with vertex attribute, if by control point.
	const FbxVector4 * lControlPoints = pMesh->GetControlPoints();
	FbxVector4 lCurrentVertex;
	FbxVector4 lCurrentNormal;
	FbxVector2 lCurrentUV;
	if (mAllByControlPoint)
	{
		const FbxGeometryElementNormal * lNormalElement = NULL;
		const FbxGeometryElementUV * lUVElement = NULL;
		if (mHasNormal)
		{
			lNormalElement = pMesh->GetElementNormal(0);
		}
		if (mHasUV)
		{
			lUVElement = pMesh->GetElementUV(0);
		}
		for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
		{
			// Save the vertex position.
			lCurrentVertex = lControlPoints[lIndex];
			lVertices[lIndex * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]);
			lVertices[lIndex * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]);
			lVertices[lIndex * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]);
			lVertices[lIndex * VERTEX_STRIDE + 3] = 1;

			// Save the normal.
			if (mHasNormal)
			{
				int lNormalIndex = lIndex;
				if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
				lNormals[lIndex * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]);
				lNormals[lIndex * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]);
				lNormals[lIndex * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]);
			}

			// Save the UV.
			if (mHasUV)
			{
				int lUVIndex = lIndex;
				if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);
				lUVs[lIndex * UV_STRIDE] = static_cast<float>(lCurrentUV[0]);
				lUVs[lIndex * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]);
			}
		}

	}

	int lVertexCount = 0;
	for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
	{
		// The material for current face.
		int lMaterialIndex = 0;
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
		}

		// Where should I save the vertex attribute index, according to the material
		const int lIndexOffset = mSubMeshes[lMaterialIndex]->IndexOffset +
			mSubMeshes[lMaterialIndex]->TriangleCount * 3;
		for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex)
		{
			const int lControlPointIndex = pMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);

			if (mAllByControlPoint)
			{
				lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
			}
			// Populate the array with vertex attribute, if by polygon vertex.
			else
			{
				lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);

				lCurrentVertex = lControlPoints[lControlPointIndex];
				lVertices[lVertexCount * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]);
				lVertices[lVertexCount * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]);
				lVertices[lVertexCount * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]);
				lVertices[lVertexCount * VERTEX_STRIDE + 3] = 1;

				if (mHasNormal)
				{
					pMesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
					lNormals[lVertexCount * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]);
					lNormals[lVertexCount * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]);
					lNormals[lVertexCount * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]);
				}

				if (mHasUV)
				{
					bool lUnmappedUV;
					pMesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
					lUVs[lVertexCount * UV_STRIDE] = static_cast<float>(lCurrentUV[0]);
					lUVs[lVertexCount * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]);
				}
			}
			++lVertexCount;
		}
		mSubMeshes[lMaterialIndex]->TriangleCount += 1;
	}

	// Create VBOs
	glGenBuffers(VBO_COUNT, mVBONames);

	// Save vertex attributes into GPU
	glBindBuffer(GL_ARRAY_BUFFER, mVBONames[VERTEX_VBO]);
	glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * VERTEX_STRIDE * sizeof(float), lVertices, GL_STATIC_DRAW);
	delete[] lVertices;

	if (mHasNormal)
	{
		glBindBuffer(GL_ARRAY_BUFFER, mVBONames[NORMAL_VBO]);
		glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * NORMAL_STRIDE * sizeof(float), lNormals, GL_STATIC_DRAW);
		delete[] lNormals;
	}

	if (mHasUV)
	{
		glBindBuffer(GL_ARRAY_BUFFER, mVBONames[UV_VBO]);
		glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * UV_STRIDE * sizeof(float), lUVs, GL_STATIC_DRAW);
		delete[] lUVs;
	}

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mVBONames[INDEX_VBO]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, lPolygonCount * TRIANGLE_VERTEX_COUNT * sizeof(unsigned int), lIndices, GL_STATIC_DRAW);
	delete[] lIndices;

	return true;
}
Example #10
0
//--------------------------------------------------------------
void ofxFBXMesh::setFBXMesh( FbxMesh* lMesh ) {
	fbxMesh = lMesh;
//	name = lMesh->GetName();
	mesh.clear();
    
    // from ViewScene Example included with the FBX SDK //
    if (!lMesh->GetNode()) {
        ofLogError("ofxFBXMesh") << " error setFBXMesh, lMesh->GetNode failed" << endl;
        return;
    }
    
    
    const int lPolygonCount = lMesh->GetPolygonCount();
    
    
    // Count the polygon count of each material
    FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
    FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
    if (lMesh->GetElementMaterial()) {
        lMaterialIndice = &lMesh->GetElementMaterial()->GetIndexArray();
        lMaterialMappingMode = lMesh->GetElementMaterial()->GetMappingMode();
        if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
            FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
            if (lMaterialIndice->GetCount() == lPolygonCount) {
                
                // make sure the vector is setup and we have the proper amount of materials ready //
                for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
                    const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
                    if(lMaterialIndex >= 0) {
                        if (subMeshes.size() < lMaterialIndex + 1) {
                            subMeshes.resize(lMaterialIndex + 1);
                        }
                    }
                }
                
                // Count the faces of each material
                for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
                    const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
//                    cout << "lMaterialIndex = " << lMaterialIndex << " submesh.size = " << subMeshes.size() << endl;
                    if(lMaterialIndex >= 0 ) {
                        subMeshes[lMaterialIndex].triangleCount += 1;
                    }
                }
                
                // Record the offset (how many vertex)
                const int lMaterialCount = subMeshes.size();
                int lOffset = 0;
                for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex) {
                    subMeshes[lIndex].indexOffset = lOffset;
                    lOffset += subMeshes[lIndex].triangleCount * 3;
//                    subMeshes[lIndex].totalIndices = subMeshes[lIndex].triangleCount * 3;
//                    cout << "polygon: " << lIndex << " totalIndices = " << subMeshes[lIndex].totalIndices << endl;
                    // This will be used as counter in the following procedures, reset to zero
                    subMeshes[lIndex].triangleCount = 0;
                }
                FBX_ASSERT(lOffset == lPolygonCount * 3); // what?
            }
        }
    }
    
    if(subMeshes.size() == 0) {
        subMeshes.resize(1);
    }
    
    // TODO: Account for if all mapping modes are not by control point //
    
    bool bHasNormals = lMesh->GetElementNormalCount() > 0;
    bool bMapNormalsByControlPoint = true;
    bool bHasUvs = lMesh->GetElementUVCount() > 0;
    bool bMapUvsByControlPoint = true;
    
    // are the normals mapped by control point or by polygon?
    FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
    if(bHasNormals) {
        lNormalMappingMode = lMesh->GetElementNormal(0)->GetMappingMode();
        if (lNormalMappingMode == FbxGeometryElement::eNone) {
            bHasNormals = false;
        }
        if (bHasNormals && lNormalMappingMode != FbxGeometryElement::eByControlPoint) {
            bMapNormalsByControlPoint = false;
        }
    }
    
    FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
    if (bHasUvs) {
        lUVMappingMode = lMesh->GetElementUV(0)->GetMappingMode();
        if (lUVMappingMode == FbxGeometryElement::eNone) {
            bHasUvs = false;
        }
        if (bHasUvs && lUVMappingMode != FbxGeometryElement::eByControlPoint) {
            bMapUvsByControlPoint = false;
        }
    }
    
    bAllMappedByControlPoint = (bMapNormalsByControlPoint && bMapUvsByControlPoint);
    
//    if(lMaterialMappingMode == FbxGeometryElement::eAllSame) {
//        
//    }
    
    int lPolygonVertexCount = lMesh->GetControlPointsCount();
    
    if( bAllMappedByControlPoint ) {
        const FbxVector4 * lControlPoints = lMesh->GetControlPoints();
        for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) {
            mesh.addVertex( ofVec3f( lControlPoints[i][0], lControlPoints[i][1], lControlPoints[i][2] ) );
        }
        
        for(int i = 0; i < lMesh->GetPolygonCount(); i++ ) {
            for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) {
                const int lControlPointIndex = lMesh->GetPolygonVertex(i, lVerticeIndex);
                mesh.addIndex( lControlPointIndex );
            }
        }
        
        if(subMeshes.size() == 1) {
            subMeshes[0].totalIndices = mesh.getNumIndices();
        }
        
        // normals
        if(bHasNormals) {
            ofMesh normalsMesh;
            //cout << "ofxFBXMesh :: we have normals for " << getName() << endl;
            if(bMapNormalsByControlPoint) {
                //cout << "ofxFBXMesh :: normals by control point for " << getName() << endl;
                const FbxGeometryElementNormal * lNormalElement = lMesh->GetElementNormal(0);
                for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) {
                    int lNormalIndex = i;
                    if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
                        lNormalIndex = lNormalElement->GetIndexArray().GetAt(i);
                    }
                    FbxVector4 lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
                    normalsMesh.addNormal( ofVec3f(lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2]) );
                }
                mesh.addNormals( normalsMesh.getNormals() );
            }
        }
        
        // textures //
        if(bHasUvs) {
            //cout << "ofxFBXMesh :: we have tex coords for " << getName() << endl;
            if(bMapUvsByControlPoint) {
                //cout << "ofxFBXMesh :: tex coords by control point " << getName() << endl;
                const FbxGeometryElementUV * lUVElement = lMesh->GetElementUV(0);
                for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) {
                    int lUVIndex = i;
                    if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
                        lUVIndex = lUVElement->GetIndexArray().GetAt(i);
                    }
                    FbxVector2 lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);
                    mesh.addTexCoord( ofVec2f(lCurrentUV[0], lCurrentUV[1]) );
                }
            }
        }
    } else {
        
//        cout << "--- " << getName() << " mapped by polygons ---------------" << endl;
//        cout << "numSubMeshes = " << subMeshes.size() << " polygon count = " << lPolygonCount << " control points = " << fbxMesh->GetControlPointsCount() << endl;
        
//        if(lMaterialMappingMode == FbxGeometryElement::eNone) {
//            cout << "Material mapping mode = none" << endl;
//        } else if (lMaterialMappingMode == FbxGeometryElement::eByControlPoint) {
//            cout << "Material mapping mode = eByControlPoint" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eByPolygonVertex) {
//            cout << "Material mapping mode = eByPolygonVertex" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
//            cout << "Material mapping mode = eByPolygon" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eByEdge) {
//            cout << "Material mapping mode = eByEdge" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eAllSame) {
//            cout << "Material mapping mode = eAllSame" << endl;
//        }
//        
//        if(lMaterialIndice) {
//            cout << "lMaterialIndice size = " << lMaterialIndice->GetCount() << endl;
//        } else {
//            cout << "did not get the lMaterialIndice" << endl;
//        }
        
        const FbxVector4 * lControlPoints = fbxMesh->GetControlPoints();
        mesh.getVertices().resize( lPolygonCount * 3 );
        mesh.getIndices().resize( lPolygonCount * 3 );
        if(bHasNormals) {
            mesh.getNormals().resize( lPolygonCount * 3 );
        }
        
//        cout << "Polygon vertex count = " << fbxMesh->GetPolygonVertexCount() << endl;
        
        const char * lUVName = NULL;
        FbxStringList lUVNames;
        fbxMesh->GetUVSetNames(lUVNames);
        if(bHasUvs && lUVNames.GetCount() ) {
            mesh.getTexCoords().resize( lPolygonCount * 3 );
            lUVName = lUVNames[0];
        }
        for(int i = 0; i < lUVNames.GetCount(); i++ ) {
//            cout << "lUVName = " << lUVNames[0] << endl;
        }
        
        
        
        FbxVector4 lCurrentVertex;
        FbxVector4 lCurrentNormal;
        FbxVector2 lCurrentUV;
        
        const FbxGeometryElementUV * lUVElement = lMesh->GetElementUV(0);
        
        int lVertexCount = 0;
        for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
            // The material for current face.
            int lMaterialIndex = 0;
            if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
                lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
                if(lMaterialIndex < 0) {
                    lMaterialIndex = 0;
                }
            }
            
            // Where should I save the vertex attribute index, according to the material
            const int lIndexOffset = subMeshes[lMaterialIndex].indexOffset + subMeshes[lMaterialIndex].triangleCount * 3;
//            const int lIndexOffset = fbxMesh->GetPolygonVertexIndex(lPolygonIndex);
            for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) {
                const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
                
                // Populate the array with vertex attribute, if by polygon vertex.
                mesh.getIndices()[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);
                
                lCurrentVertex = lControlPoints[ lControlPointIndex ];
                mesh.getVertices()[lVertexCount].set( lCurrentVertex[0], lCurrentVertex[1], lCurrentVertex[2] );
                
                if (bHasNormals) {
                    if(fbxMesh->GetPolygonVertexNormal( lPolygonIndex, lVerticeIndex, lCurrentNormal )) {
                        int normalIndex = lVertexCount;
                        mesh.getNormals()[normalIndex].set( lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2] );
                    }
                }
                
                if (bHasUvs) {
                    bool lUnmappedUV;
                    fbxMesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
                    int tcoordIndex = lVertexCount;
                    mesh.getTexCoords()[ tcoordIndex ].set( lCurrentUV[0], lCurrentUV[1] );
                }
                ++lVertexCount;
            }
            
            subMeshes[lMaterialIndex].triangleCount += 1;
            subMeshes[lMaterialIndex].totalIndices += 3;
            
//            cout << "materialIndex = " << lMaterialIndex << endl;
        }
        
    }
    
    // All faces will use the same material.
//    if ( subMeshes.size() == 1) {
//        //        meshMaterials.resize(1);
////        subMeshes[0].totalIndices = mesh.getNumIndices();
//    }
    for(int i = 0; i < subMeshes.size(); i++ ) {
//        cout << i << " submesh totalindicies = " << subMeshes[i].totalIndices << " total verts = " << mesh.getNumVertices() << " polygonos = " << lPolygonCount << endl;
    }
    
//    cout << "--------------------------------------- " << endl << endl;
    veebs.setMesh( mesh, GL_STREAM_DRAW );
    original = mesh;
    
}
Example #11
0
bool FillData(ModelData* someData,FbxNode* aNode, AnimationData* aAnimation)
{
	FbxMesh* mesh = aNode->GetMesh();
	if (mesh == nullptr || !aNode)
		return false;

	const int lPolygonCount = mesh->GetPolygonCount();

	// Count the polygon count of each material
	FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
	FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
	if (mesh->GetElementMaterial())
	{
		lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray();
		lMaterialMappingMode = mesh->GetElementMaterial()->GetMappingMode();
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
			if (lMaterialIndice->GetCount() == lPolygonCount)
			{
				// Count the faces of each material
				for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
				{
					const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
					lMaterialIndex;
					/*if (someData->mSubMeshes[lMaterialIndex] == NULL)
					{
						someData->mSubMeshes[lMaterialIndex] = new ModelData::SubMesh;
					}
					someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1;*/
				}

				// Make sure we have no "holes" (NULL) in the mSubMeshes table. This can happen
				// if, in the loop above, we resized the mSubMeshes by more than one slot.
					
				/*for (int i = 0; i < someData->mSubMeshes.Count(); i++)
				{
					if (someData->mSubMeshes[i] == NULL)
						someData->mSubMeshes[i] = new ModelData::SubMesh;
				}*/

				// Record the offset (how many vertex)
				const int lMaterialCount = someData->mSubMeshes.Size();
				lMaterialCount;
				int lOffset = 0;
				/*for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
				{
					someData->mSubMeshes[lIndex]->IndexOffset = lOffset;
					lOffset += someData->mSubMeshes[lIndex]->TriangleCount * 3;
					// This will be used as counter in the following procedures, reset to zero
					someData->mSubMeshes[lIndex]->TriangleCount = 0;
				}*/
				FBX_ASSERT(lOffset == lPolygonCount * 3);
			}
		}
	}

	// All faces will use the same material.
	if (someData->mSubMeshes.Size() == 0)
	{
		if (someData->mSubMeshes.GetCapacity() == 0)
		{
			someData->mSubMeshes.Init(1);
		}
		someData->mSubMeshes.RemoveAll();
		someData->mSubMeshes.AddEmptyObject();
		someData->mSubMeshes[0] = new ModelData::SubMesh();
	}

		

	bool hasNormalMap = false;

	const int lMaterialCount = aNode->GetMaterialCount();
	for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex)
	{
		FbxSurfaceMaterial * lMaterial = aNode->GetMaterial(lMaterialIndex);
		if (lMaterial && !lMaterial->GetUserDataPtr())
		{
			TextureInfo diffuseInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sDiffuse,FbxSurfaceMaterial::sDiffuseFactor,diffuseInfo.myFileName);
			diffuseInfo.myType = DIFFUSE;
			if(diffuseInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(diffuseInfo);
			}

			TextureInfo normalInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sNormalMap,FbxSurfaceMaterial::sBumpFactor,normalInfo.myFileName);
			hasNormalMap = normalInfo.myFileName.empty() == false;
			normalInfo.myType = NORMALMAP;
			if(normalInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(normalInfo);
				hasNormalMap = true;
			}

			TextureInfo roughnessInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sSpecular,FbxSurfaceMaterial::sSpecularFactor,roughnessInfo.myFileName);
			roughnessInfo.myType = ROUGHNESS;
			if(roughnessInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(roughnessInfo);
			}

			TextureInfo substanceInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sReflection,FbxSurfaceMaterial::sReflectionFactor,substanceInfo.myFileName);
			substanceInfo.myType = SUBSTANCE;
			if(substanceInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(substanceInfo);
			}

			TextureInfo ambientInfo;
			GetMaterialProperty(lMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, ambientInfo.myFileName);
			ambientInfo.myType = AO;
			if (substanceInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(ambientInfo);
			}
		}
	}

	// Congregate all the data of a mesh to be cached in VBOs.
	// If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.'
		
	someData->mHasNormal = mesh->GetElementNormalCount() > 0;
	someData->mHasUV = mesh->GetElementUVCount() > 0;
	someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0;

	FbxSkin * lSkinDeformer = (FbxSkin *)mesh->GetDeformer(0, FbxDeformer::eSkin);
	someData->myHasSkinweights = lSkinDeformer != nullptr;

	if(hasNormalMap && someData->myHasBiNormal == false)
	{
		mesh->GenerateTangentsDataForAllUVSets();
		someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0;
	}
	someData->myHasTangents = mesh->GetElementTangentCount() > 0;
		
	FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
	FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
	if (someData->mHasNormal)
	{
		lNormalMappingMode = mesh->GetElementNormal(0)->GetMappingMode();
		if (lNormalMappingMode == FbxGeometryElement::eNone)
		{
			someData->mHasNormal = false;
		}
		if (someData->mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint)
		{
			someData->mAllByControlPoint = false;
		}
	}
	if (someData->mHasUV)
	{
		lUVMappingMode = mesh->GetElementUV(0)->GetMappingMode();
		if (lUVMappingMode == FbxGeometryElement::eNone)
		{
			someData->mHasUV = false;
		}
		if (someData->mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint)
		{
			someData->mAllByControlPoint = false;
		}
	}

	// Allocate the array memory, by control point or by polygon vertex.
	int lPolygonVertexCount = mesh->GetControlPointsCount();
	//if (!someData->my)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_POS;
		newLayout.mySize = VERTEX_STRIDE;
		newLayout.myOffset = 0;
		someData->myLayout.Add(newLayout);
		lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	}
	int stride = VERTEX_STRIDE;
	size_t size = lPolygonVertexCount * VERTEX_STRIDE;
	//float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE];
	unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT];
	someData->myIndexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	//float * lNormals = NULL;
	if (someData->mHasNormal)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_NORMAL;
		newLayout.mySize = NORMAL_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += NORMAL_STRIDE;
		size += lPolygonVertexCount * NORMAL_STRIDE;
		//lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE];
	}
	//float * lUVs = NULL;
	FbxStringList lUVNames;
	mesh->GetUVSetNames(lUVNames);
	const char * lUVName = NULL;
	if (someData->mHasUV && lUVNames.GetCount())
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_UV;
		newLayout.mySize = UV_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += UV_STRIDE;
		size += lPolygonVertexCount * UV_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
		lUVName = lUVNames[0];
	}

	if (someData->myHasBiNormal)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_BINORMAL;
		newLayout.mySize = BINORMAL_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += BINORMAL_STRIDE;
		size += lPolygonVertexCount * BINORMAL_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
	}

	if (someData->myHasTangents)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_TANGENT;
		newLayout.mySize = TANGENT_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += TANGENT_STRIDE;
		size += lPolygonVertexCount * TANGENT_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
	}

	if (someData->myHasSkinweights)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_SKINWEIGHTS;
		newLayout.mySize = SKINWEIGHT_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += SKINWEIGHT_STRIDE;
		size += lPolygonVertexCount * SKINWEIGHT_STRIDE;

		newLayout.myType = ModelData::VERTEX_BONEID;
		newLayout.mySize = BONEID_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += BONEID_STRIDE;
		size += lPolygonVertexCount * BONEID_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
	}

	float * lVertices = new float[size];

	FbxAMatrix globalPos;
	FbxVector4* weights = nullptr;
	FbxVectorTemplate4<int>* bones = nullptr;
	FbxTime time = static_cast<FbxTime>(0.0f);
	if(someData->myHasSkinweights)
	{
		weights = new FbxVector4[mesh->GetControlPointsCount()];
		bones = new FbxVectorTemplate4<int>[mesh->GetControlPointsCount()];
		ComputeLinearDeformation(globalPos,mesh,weights,bones,aAnimation);
	}

	const FbxGeometryElementBinormal * lBiNormalElement = NULL;
	const FbxGeometryElementTangent * lTangentElement = NULL;

	if (someData->myHasBiNormal)
	{
		lBiNormalElement = mesh->GetElementBinormal(0);
	}
	if (someData->myHasTangents)
	{
		lTangentElement = mesh->GetElementTangent(0);
	}

	// Populate the array with vertex attribute, if by control point.
	const FbxVector4 * lControlPoints = mesh->GetControlPoints();
	FbxVector4 lCurrentVertex;
	FbxVector4 lCurrentNormal;
	FbxVector4 lCurrentBiNormal;
	FbxVector4 lCurrentTangent;
	FbxVector2 lCurrentUV;
	if (someData->mAllByControlPoint)
	{
		const FbxGeometryElementNormal * lNormalElement = NULL;
		const FbxGeometryElementUV * lUVElement = NULL;
		if (someData->mHasNormal)
		{
			lNormalElement = mesh->GetElementNormal(0);
		}
		if (someData->mHasUV)
		{
			lUVElement = mesh->GetElementUV(0);
		}

		for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
		{
			int currentIndex = lIndex * stride;
			int addedSize = VERTEX_STRIDE;
			// Save the vertex position.
			lCurrentVertex = lControlPoints[lIndex];
				
			CU::Vector4f position(static_cast<float>(lCurrentVertex[0]),
					static_cast<float>(lCurrentVertex[1]),
					static_cast<float>(lCurrentVertex[2]),
					1);

			CU::Matrix44f fixMatrix;
			fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1,0,0));
			position = position*fixMatrix;

			lVertices[currentIndex] = position.x;
			lVertices[currentIndex + 1] = position.y;
			lVertices[currentIndex + 2] = position.z;
			lVertices[currentIndex + 3] = 1;


			// Save the normal.
			if (someData->mHasNormal)
			{
				int lNormalIndex = lIndex;
				if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);

				CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2]));
				normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));

				lVertices[currentIndex + addedSize] = normal.x;
				lVertices[currentIndex + addedSize + 1] = normal.y;
				lVertices[currentIndex + addedSize + 2] = normal.z;
				lVertices[currentIndex + addedSize + 3] = 0;
				addedSize += NORMAL_STRIDE;
			}

			// Save the UV.
			if (someData->mHasUV)
			{
				int lUVIndex = lIndex;
				if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);
				lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]);
				lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f;
				addedSize += 2;
			}

			if (someData->myHasBiNormal)
				{
					int lBinormIndexIndex = lIndex;
					if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lIndex);
					}

					lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex);
					//mesh->GetElementBinormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
					//lCurrentNormal = lCurrentNormal
					CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += BINORMAL_STRIDE;
				}

				if (someData->myHasTangents)
				{
					int lBinormIndexIndex = lIndex;
					if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lIndex);
					}

					lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex);

					//lCurrentNormal = lCurrentNormal
					CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += TANGENT_STRIDE;
				}

				if(someData->myHasSkinweights)
				{
					FbxVector4 currentWeights = weights[lIndex];
					//currentWeights.Normalize();

					lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]);
					lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]);
					lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]);
					addedSize += SKINWEIGHT_STRIDE;

					FbxVectorTemplate4<int> currentBones = bones[lIndex];

					lVertices[currentIndex + addedSize] = static_cast<float>(currentBones[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentBones[1]);
					lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentBones[2]);
					lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentBones[3]);
					addedSize += BONEID_STRIDE;
				}
		}

	}

	int lVertexCount = 0;
	for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
	{
		// The material for current face.
		int lMaterialIndex = 0;
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
		}

		// Where should I save the vertex attribute index, according to the material
		const int lIndexOffset = someData->mSubMeshes[lMaterialIndex]->IndexOffset +
			someData->mSubMeshes[lMaterialIndex]->TriangleCount * 3;
		for (int lVerticeIndex = TRIANGLE_VERTEX_COUNT-1; lVerticeIndex > -1; --lVerticeIndex)
		{
			const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
				
			int vertexIndex = lIndexOffset + (TRIANGLE_VERTEX_COUNT-1) - lVerticeIndex;
			if (someData->mAllByControlPoint)
			{
				lIndices[vertexIndex] = static_cast<unsigned int>(lControlPointIndex);
			}
			// Populate the array with vertex attribute, if by polygon vertex.
			else
			{
				lIndices[vertexIndex] = static_cast<unsigned int>(lVertexCount);

				lCurrentVertex = lControlPoints[lControlPointIndex];
				int addedSize = VERTEX_STRIDE;
				int currentIndex = lVertexCount * stride;

				CU::Vector4f position(static_cast<float>(lCurrentVertex[0]),
					static_cast<float>(lCurrentVertex[1]),
					static_cast<float>(lCurrentVertex[2]),
					1);

				//fixMatrix
				CU::Matrix44f fixMatrix;
				fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
				position = position*fixMatrix;

				lVertices[currentIndex] = position.x;
				lVertices[currentIndex + 1] = position.y;
				lVertices[currentIndex + 2] = position.z;
				lVertices[currentIndex + 3] = 0;

				if (someData->mHasNormal)
				{
					mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
					CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);

					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += NORMAL_STRIDE;
				}

				if (someData->mHasUV)
				{
					bool lUnmappedUV;
					mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
					lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f;
					addedSize += UV_STRIDE;
				}
					
				if (someData->myHasBiNormal)
				{
					int lBinormIndexIndex = lVerticeIndex;
					if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lVerticeIndex);
					}

					lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex);

					CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += BINORMAL_STRIDE;
				}

				if (someData->myHasTangents)
				{
					int lBinormIndexIndex = lVerticeIndex;
					if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lVerticeIndex);
					}

					lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex);

					mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);

					CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += TANGENT_STRIDE;
				}

				if(someData->myHasSkinweights)
				{
					FbxVector4 currentWeights = weights[lControlPointIndex];
					FbxVectorTemplate4<int> currentBones = bones[lControlPointIndex];
					for(int l = 0;l < 4;++l)
					{
						if(currentBones[l] == -1)
						{
							currentWeights[l] = 0.0f;
						}
					}
					currentWeights.Normalize();

					lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]);
					lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]);
					lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]);
					addedSize += SKINWEIGHT_STRIDE;

						

					lVertices[currentIndex + addedSize] = *(float*)&currentBones[0];
					lVertices[currentIndex + addedSize + 1] = *(float*)&currentBones[1];
					lVertices[currentIndex + addedSize + 2] = *(float*)&currentBones[2];
					lVertices[currentIndex + addedSize + 3] = *(float*)&currentBones[3];
					addedSize += BONEID_STRIDE;
				}
			}
			++lVertexCount;
		}
		someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1;
	}

	someData->myVertexCount = lVertexCount;
	someData->myVertexStride = stride;

	someData->myVertexBuffer = lVertices;
	someData->myIndicies = lIndices;

	if(weights)
	{
		delete [] weights;
		delete [] bones;
	}

	return true;
}
Example #12
0
FBXMesh::Builder::MeshMetaData::MeshMetaData(FbxMesh const* mesh, unsigned int vaoOffset) 
	: mesh(mesh),
	vaoOffset(vaoOffset),
	hasNormals(false),
	hasUvs(false)
{
	
	if (!mesh->GetNode())
		return;

	const int lPolygonCount = mesh->GetPolygonCount();

	// Count the polygon count of each material -> split up in submeshes
	FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
	FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
	if (mesh->GetElementMaterial())
	{
		lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray();
		lMaterialMappingMode = mesh->GetElementMaterial()->GetMappingMode();
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
			if (lMaterialIndice->GetCount() == lPolygonCount)
			{
				// Count the faces of each material
				for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
				{
					const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
					if (subMeshMetaData.size() < lMaterialIndex + 1)
					{
						subMeshMetaData.resize(lMaterialIndex + 1);
					}

					subMeshMetaData[lMaterialIndex].triangleCount += 1;
				}

				// Make sure we have no "holes" (NULL) in the mSubMeshes table. This can happen
				// if, in the loop above, we resized the mSubMeshes by more than one slot.
				//for (int i = 0; i < subMeshMetaData.size(); i++)
				//{
				//    if (subMeshMetaData[i] == NULL)
				//        mSubMeshes[i] = new SubMesh;
				//}

				// Record the offset (how many vertex)
				const int lMaterialCount = (int)subMeshMetaData.size();
				int lOffset = 0;
				for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
				{
					subMeshMetaData[lIndex].indexOffset = lOffset;
					lOffset += subMeshMetaData[lIndex].triangleCount * 3;
					// This will be used as counter in the following procedures, reset to zero
					subMeshMetaData[lIndex].triangleCount = 0;
				}
				FBX_ASSERT(lOffset == lPolygonCount * 3);
			}
		}
	}

	// All faces will use the same material.
	if (subMeshMetaData.size() == 0)
	{
		subMeshMetaData.resize(1);
	}
	
	hasNormals = mesh->GetElementNormalCount() > 0;
	hasUvs = mesh->GetElementUVCount() > 0;

	allByControlPoint = true;
	
	// Congregate all the data of a mesh to be cached.
	// If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.
	FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
	FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
	if (hasNormals)
	{
		lNormalMappingMode = mesh->GetElementNormal(0)->GetMappingMode();
		if (lNormalMappingMode == FbxGeometryElement::eNone)
		{
			hasNormals = false;
		}
		if (hasNormals && lNormalMappingMode != FbxGeometryElement::eByControlPoint)
		{
			allByControlPoint = false;
		}
	}
	if (hasUvs)
	{
		lUVMappingMode = mesh->GetElementUV(0)->GetMappingMode();
		if (lUVMappingMode == FbxGeometryElement::eNone)
		{
			hasUvs = false;
		}
		if (hasUvs && lUVMappingMode != FbxGeometryElement::eByControlPoint)
		{
			allByControlPoint = false;
		}
	}
	// Allocate the array memory, by control point or by polygon vertex.
	int lPolygonVertexCount = mesh->GetControlPointsCount();
	if (!allByControlPoint)
	{
		lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	}
	vertices.resize(lPolygonVertexCount);
	indices.resize(lPolygonCount * TRIANGLE_VERTEX_COUNT);


	float * lNormals = NULL;
	if (hasNormals)
	{
		normals.resize(lPolygonVertexCount);
	}
	float * lUVs = NULL;
	FbxStringList lUVNames;
	mesh->GetUVSetNames(lUVNames);
	const char * lUVName = NULL;
	if (hasUvs && lUVNames.GetCount())
	{
		uvs.resize(lPolygonVertexCount);
		lUVName = lUVNames[0];
	}


	// Populate the array with vertex attribute, if by control point.
	const FbxVector4 * lControlPoints = mesh->GetControlPoints();
	FbxVector4 lCurrentVertex;
	FbxVector4 lCurrentNormal;
	FbxVector2 lCurrentUV;
	if (allByControlPoint)
	{
		const FbxGeometryElementNormal * lNormalElement = NULL;
		const FbxGeometryElementUV * lUVElement = NULL;
		if (hasNormals)
		{
			lNormalElement = mesh->GetElementNormal(0);
		}
		if (hasUvs)
		{
			lUVElement = mesh->GetElementUV(0);
		}
		for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
		{
			// Save the vertex position.
			lCurrentVertex = lControlPoints[lIndex];

			vertices[lIndex] = glm::vec3(static_cast<float>(lCurrentVertex[0]),
										 static_cast<float>(lCurrentVertex[1]),
										 static_cast<float>(lCurrentVertex[2]));
			modelSpaceAABB.merge(vertices[lIndex]);

			// Save the normal.
			if (hasNormals)
			{
				int lNormalIndex = lIndex;
				if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
				
				normals[lIndex] = glm::vec3(static_cast<float>(lCurrentNormal[0]),
											 static_cast<float>(lCurrentNormal[1]),
											 static_cast<float>(lCurrentNormal[2]));
			}

			// Save the UV.
			if (hasUvs)
			{
				int lUVIndex = lIndex;
				if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);

				uvs[lIndex] = glm::vec2(static_cast<float>(lCurrentUV[0]),
										static_cast<float>(lCurrentUV[1]));
			}
		}
	}


	int lVertexCount = 0;
	for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
	{
		// The material for current face.
		int lMaterialIndex = 0;
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
		}

		// Where should I save the vertex attribute index, according to the material
		const int lIndexOffset = subMeshMetaData[lMaterialIndex].indexOffset +
			subMeshMetaData[lMaterialIndex].triangleCount * 3;
		for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex)
		{
			const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);

			if (allByControlPoint)
			{
				indices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
			}
			// Populate the array with vertex attribute, if by polygon vertex.
			else
			{
				indices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);

				lCurrentVertex = lControlPoints[lControlPointIndex];

				vertices[lVertexCount] = glm::vec3(static_cast<float>(lCurrentVertex[0]),
												   static_cast<float>(lCurrentVertex[1]),
												   static_cast<float>(lCurrentVertex[2]));
				modelSpaceAABB.merge(vertices[lVertexCount]);

				if (hasNormals)
				{
					mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);

					normals[lVertexCount] = glm::vec3(static_cast<float>(lCurrentNormal[0]),
													   static_cast<float>(lCurrentNormal[1]),
													   static_cast<float>(lCurrentNormal[2]));
				}

				if (hasUvs)
				{
					bool lUnmappedUV;
					mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
					
					uvs[lVertexCount] = glm::vec2(static_cast<float>(lCurrentUV[0]),
												  static_cast<float>(lCurrentUV[1]));
				}
			}
			++lVertexCount;
		}
		subMeshMetaData[lMaterialIndex].triangleCount += 1;
	}
}