Exemplo n.º 1
0
Scene::Scene()
	: m_pTerrainMesh(new Framework::Mesh("Ground.xml"))
	, m_pCubeMesh(new Framework::Mesh("UnitCube.xml"))
	, m_pTetraMesh(new Framework::Mesh("UnitTetrahedron.xml"))
	, m_pCylMesh(new Framework::Mesh("UnitCylinder.xml"))
	, m_pSphereMesh(new Framework::Mesh("UnitSphere.xml"))
{
	//Align the size of each MaterialBlock to the uniform buffer alignment.
	int uniformBufferAlignSize = 0;
	glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniformBufferAlignSize);

	m_sizeMaterialBlock = sizeof(MaterialBlock);
	m_sizeMaterialBlock += uniformBufferAlignSize -
		(m_sizeMaterialBlock % uniformBufferAlignSize);

	int sizeMaterialUniformBuffer = m_sizeMaterialBlock * MATERIAL_COUNT;

	std::vector<MaterialBlock> materials;
	GetMaterials(materials);
	assert(materials.size() == MATERIAL_COUNT);

	std::vector<GLubyte> mtlBuffer;
	mtlBuffer.resize(sizeMaterialUniformBuffer, 0);

	GLubyte *bufferPtr = &mtlBuffer[0];

	for(size_t mtl = 0; mtl < materials.size(); ++mtl)
		memcpy(bufferPtr + (mtl * m_sizeMaterialBlock), &materials[mtl], sizeof(MaterialBlock));

	glGenBuffers(1, &m_materialUniformBuffer);
	glBindBuffer(GL_UNIFORM_BUFFER, m_materialUniformBuffer);
	glBufferData(GL_UNIFORM_BUFFER, sizeMaterialUniformBuffer, bufferPtr, GL_STATIC_DRAW);
	glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
Exemplo n.º 2
0
std::shared_ptr<Scene> SceneFactory::CreateFromFile(const std::string& filename) {
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(filename,
		aiProcess_Triangulate |
		aiProcess_GenNormals |
		aiProcess_ImproveCacheLocality |
		aiProcess_JoinIdenticalVertices |
		aiProcess_PreTransformVertices);

	if (scene == NULL) {
		std::printf("\nImport failed:\n\t");
		auto errorString = importer.GetErrorString();
		std::printf(errorString);
		std::printf("\n");
		return nullptr;
	}
	Scene::vertexList vertices = GetVertices(scene);
	Scene::triangleList faces = GetFaces(scene);
	Scene::materialList materials = GetMaterials(scene);
	return std::shared_ptr<Scene>(new Scene(vertices, faces, materials));
}
Exemplo n.º 3
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);
	}



}
Exemplo n.º 4
0
	void ResourceModel::AddTMFObject(FILE* fp) 
	{
		TMFObject* pObject = new TMFObject();
		pObject->Initialise( fp,  GetMaterials() );
		mObjectList.push_back( pObject );
	}
	std::shared_ptr<Mesh> FBXConverter::LoadMesh(FbxMesh* fbxMesh)
	{
		assert(fbxMesh->GetLayerCount() > 0);

		auto node = fbxMesh->GetNode();
		auto layer = fbxMesh->GetLayer(0);

		if (layer->GetNormals() == nullptr)
		{
			fbxMesh->GenerateNormals(true);
		}

		auto uvs = layer->GetUVs();
		auto vcolors = layer->GetVertexColors();
		auto normals = layer->GetNormals();
		auto binormals = layer->GetBinormals();
		auto materials = layer->GetMaterials();

		auto controlPoints = fbxMesh->GetControlPoints();
		auto controlPointsCount = fbxMesh->GetControlPointsCount();

		auto polygonCount = fbxMesh->GetPolygonCount();

		std::vector<FbxFace> faces;

		// Load weights
		std::vector<BoneConnector> bcs_temp;
		std::vector<Vertex> vs_temp;
		LoadSkin(fbxMesh, bcs_temp, vs_temp);

		// generate face vertex
		int32_t vertexID = 0;
		for (int32_t polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++)
		{
			int polygonPointCount = fbxMesh->GetPolygonSize(polygonIndex);

			FbxFace face;

			for (int32_t polygonPointIndex = 0; polygonPointIndex < polygonPointCount; polygonPointIndex++)
			{
				auto ctrlPointIndex = fbxMesh->GetPolygonVertex(polygonIndex, polygonPointIndex);

				Vertex v;

				v.Position = LoadPosition(fbxMesh, ctrlPointIndex);
				
				v.Weights = vs_temp[ctrlPointIndex].Weights;

				if (normals != nullptr)
				{
					v.Normal = LoadNormal(normals, vertexID, ctrlPointIndex);
				}
		
				if (uvs != nullptr)
				{
					v.UV = LoadUV(fbxMesh, uvs, vertexID, ctrlPointIndex, polygonIndex, polygonPointIndex);
				}
				else
				{
					// Auto generated
					v.UV[0] = v.Position[0] + v.Position[2];
					v.UV[1] = v.Position[1];
				}

				if (vcolors != nullptr)
				{
					v.VertexColor = LoadVertexColor(fbxMesh, vcolors, vertexID, ctrlPointIndex, polygonIndex, polygonPointIndex);
				}

				face.Vertecies.push_back(v);
				vertexID++;
			}

			faces.push_back(face);
		}



		// 面の表裏入れ替え
		for (auto& face : faces)
		{
			std::reverse(face.Vertecies.begin(), face.Vertecies.end());
		}

		// メッシュで使用可能な形式に変換
	
		// 頂点変換テーブル作成
		int32_t vInd = 0;
		std::map<Vertex, int32_t> v2ind;
		std::map<int32_t, Vertex> ind2v;

		for (auto& face : faces)
		{
			for (int32_t vi = 0; vi < (int32_t)face.Vertecies.size(); vi++)
			{
				auto vertex = face.Vertecies[vi];

				auto it = v2ind.find(vertex);
				if (it == v2ind.end())
				{
					v2ind[vertex] = vInd;
					ind2v[vInd] = vertex;
					vInd++;
				}
			}
		}

		// 設定
		auto mesh = std::make_shared<Mesh>();
		mesh->Name = node->GetName();
		mesh->BoneConnectors = bcs_temp;

		mesh->Vertexes.resize(vInd);
		for (auto& iv : ind2v)
		{
			mesh->Vertexes[iv.first] = iv.second;
		}

		for (auto& face : faces)
		{
			if (face.Vertecies.size() < 3) continue;

			if (face.Vertecies.size() == 3)
			{
				Face f;
				f.Index[0] = v2ind[face.Vertecies[0]];
				f.Index[1] = v2ind[face.Vertecies[1]];
				f.Index[2] = v2ind[face.Vertecies[2]];
				mesh->Faces.push_back(f);
			}
			
			if (face.Vertecies.size() == 4)
			{
				Face f0;
				f0.Index[0] = v2ind[face.Vertecies[0]];
				f0.Index[1] = v2ind[face.Vertecies[1]];
				f0.Index[2] = v2ind[face.Vertecies[2]];
				mesh->Faces.push_back(f0);

				Face f1;
				f1.Index[0] = v2ind[face.Vertecies[0]];
				f1.Index[1] = v2ind[face.Vertecies[2]];
				f1.Index[2] = v2ind[face.Vertecies[3]];
				mesh->Faces.push_back(f1);
			}
		}

		// Binormal,Tangent計算
		std::map<int32_t, VertexNormals> vInd2Normals;

		for (const auto& face : mesh->Faces)
		{
			FbxVector4 binormal, tangent;
			CalcTangentSpace(
				mesh->Vertexes[face.Index[0]],
				mesh->Vertexes[face.Index[1]],
				mesh->Vertexes[face.Index[2]],
				binormal,
				tangent);

			for (auto i = 0; i < 3; i++)
			{
				vInd2Normals[face.Index[i]].Binormal += binormal;
				vInd2Normals[face.Index[i]].Tangent += tangent;
				vInd2Normals[face.Index[i]].Count += 1;
			}
		}

		for (auto& vn : vInd2Normals)
		{
			vn.second.Binormal /= vn.second.Count;
			vn.second.Tangent /= vn.second.Count;
		}

		for (auto& vn : vInd2Normals)
		{
			mesh->Vertexes[vn.first].Binormal = vn.second.Binormal;
			mesh->Vertexes[vn.first].Tangent = vn.second.Tangent;

			// 適当な値を代入する
			if (mesh->Vertexes[vn.first].Binormal.Length() == 0.0f)
			{
				if (mesh->Vertexes[vn.first].Normal != FbxVector4(1, 0, 0))
				{
					mesh->Vertexes[vn.first].Binormal = FbxVector4(1, 0, 0);
					mesh->Vertexes[vn.first].Tangent = FbxVector4(0, 1, 0);
				}
				else
				{
					mesh->Vertexes[vn.first].Binormal = FbxVector4(0, 1, 0);
					mesh->Vertexes[vn.first].Tangent = FbxVector4(1, 0, 0);
				}
			}
		}

		return mesh;
	}