Mesh GetOrCreateInstance(FbxMesh fbxMesh) { Mesh mesh; if (m_meshInstances.TryGetValue(fbxMesh, out mesh)) { return(mesh); } // create the unity mesh vertices var nVertices = fbxMesh.GetControlPointsCount(); var unityVertices = new Vector3[nVertices]; for (int i = 0; i < nVertices; ++i) { unityVertices[i] = V3(fbxMesh.GetControlPointAt(i)); } // create the unity mesh triangles. TODO: maybe handle non-triangular faces more intelligently var nPoly = fbxMesh.GetPolygonCount(); var unityTriangles = new List <int>(); for (int polyIndex = 0; polyIndex < nPoly; ++polyIndex) { var polySize = fbxMesh.GetPolygonSize(polyIndex); if (polySize < 3) { // ignore lines and points continue; } // Add the first triangle unityTriangles.Add(fbxMesh.GetPolygonVertex(polyIndex, 0)); unityTriangles.Add(fbxMesh.GetPolygonVertex(polyIndex, 1)); unityTriangles.Add(fbxMesh.GetPolygonVertex(polyIndex, 2)); // If there's more triangles, assume they're a fan around the first vertex. // Not necessarily true, but them's the breaks. for (int i = 3; i < polySize; ++i) { unityTriangles.Add(fbxMesh.GetPolygonVertex(polyIndex, 0)); unityTriangles.Add(fbxMesh.GetPolygonVertex(polyIndex, i - 1)); unityTriangles.Add(fbxMesh.GetPolygonVertex(polyIndex, i)); } } mesh = new Mesh { name = fbxMesh.GetName(), vertices = unityVertices, triangles = unityTriangles.ToArray() }; mesh.RecalculateNormals(); m_meshInstances[fbxMesh] = mesh; return(mesh); }
/// <summary> /// Process mesh data and setup MeshFilter component /// </summary> private void ProcessMesh(FbxNode fbxNode, GameObject unityGo) { FbxMesh fbxMesh = fbxNode.GetMesh(); if (fbxMesh == null) { return; } var unityMesh = new Mesh(); // create mesh var unityVertices = new List <Vector3> (); var unityTriangleIndices = new List <int> (); // transfer vertices for (int i = 0; i < fbxMesh.GetControlPointsCount(); ++i) { FbxVector4 fbxVector4 = fbxMesh.GetControlPointAt(i); Debug.Assert(fbxVector4.X <= float.MaxValue && fbxVector4.X >= float.MinValue); Debug.Assert(fbxVector4.Y <= float.MaxValue && fbxVector4.Y >= float.MinValue); Debug.Assert(fbxVector4.Z <= float.MaxValue && fbxVector4.Z >= float.MinValue); unityVertices.Add(new Vector3((float)fbxVector4.X, (float)fbxVector4.Y, (float)fbxVector4.Z)); } // transfer triangles for (int polyIndex = 0; polyIndex < fbxMesh.GetPolygonCount(); ++polyIndex) { int polySize = fbxMesh.GetPolygonSize(polyIndex); // only support triangles Debug.Assert(polySize == 3); for (int polyVertexIndex = 0; polyVertexIndex < polySize; ++polyVertexIndex) { int vertexIndex = fbxMesh.GetPolygonVertex(polyIndex, polyVertexIndex); unityTriangleIndices.Add(vertexIndex); } } unityMesh.vertices = unityVertices.ToArray(); // TODO: // - support Mesh.SetTriangles - multiple materials per mesh // - support Mesh.SetIndices - other topologies e.g. quads unityMesh.triangles = unityTriangleIndices.ToArray(); unityMesh.RecalculateNormals(); var unityMeshFilter = unityGo.AddComponent <MeshFilter> (); unityMeshFilter.sharedMesh = unityMesh; var unityRenderer = unityGo.AddComponent <MeshRenderer> (); { // Assign the default material (hack!) var unityPrimitive = GameObject.CreatePrimitive(PrimitiveType.Quad); var unityMat = unityPrimitive.GetComponent <MeshRenderer> ().sharedMaterial; unityRenderer.sharedMaterial = unityMat; UnityEngine.Object.DestroyImmediate(unityPrimitive); } }
/// <summary> /// Process UV data and configure the Mesh's UV attributes /// </summary> private void ProcessUVs(FbxMesh fbxMesh, Mesh unityMesh, int maxUVs = 4) { // Import UV sets (maximum defined by maxUVs) int uvsetIndex = 0; // First just try importing diffuse UVs from separate layers // (Maya exports that way) FbxLayerElementUV fbxFirstUVSet = null; FbxLayer fbxFirstUVLayer = null; // NOTE: assuming triangles int polygonIndexCount = fbxMesh.GetPolygonVertexCount(); int vertexCount = fbxMesh.GetControlPointsCount(); int [] polygonVertexIndices = new int [polygonIndexCount]; int j = 0; for (int polyIndex = 0; polyIndex < fbxMesh.GetPolygonCount(); ++polyIndex) { for (int positionInPolygon = 0; positionInPolygon < fbxMesh.GetPolygonSize(polyIndex); ++positionInPolygon) { polygonVertexIndices [j++] = fbxMesh.GetPolygonVertex(polyIndex, positionInPolygon); } } for (int i = 0; i < fbxMesh.GetLayerCount(); i++) { FbxLayer fbxLayer = fbxMesh.GetLayer(i); if (fbxLayer == null) { continue; } FbxLayerElementUV fbxUVSet = fbxLayer.GetUVs(); if (fbxUVSet == null) { continue; } if (fbxFirstUVSet != null) { fbxFirstUVSet = fbxUVSet; fbxFirstUVLayer = fbxLayer; } switch (uvsetIndex) { case 0: unityMesh.uv = ProcessUVSet(fbxUVSet, polygonVertexIndices, vertexCount); break; case 1: unityMesh.uv2 = ProcessUVSet(fbxUVSet, polygonVertexIndices, vertexCount); break; case 2: unityMesh.uv3 = ProcessUVSet(fbxUVSet, polygonVertexIndices, vertexCount); break; case 3: unityMesh.uv4 = ProcessUVSet(fbxUVSet, polygonVertexIndices, vertexCount); break; } uvsetIndex++; if (uvsetIndex == maxUVs) { break; } } // If we have received one UV set, check whether the same layer contains an emissive UV set // that is different from diffuse UV set. // 3dsmax FBX exporters doesn't export UV sets as different layers, instead for lightmapping usually // a material is set up to have lightmap (2nd UV set) as self-illumination slot, and main texture // (1st UV set) as diffuse slot. if (uvsetIndex == 1 && fbxFirstUVSet != null) { FbxLayerElementUV fbxSecondaryUVSet = null; // TODO: check if we've already passed eTextureEmissive layer for (int i = (int)FbxLayerElement.EType.eTextureEmissive; i < (int)FbxLayerElement.EType.eTypeCount; i++) { fbxSecondaryUVSet = fbxFirstUVLayer.GetUVs((FbxLayerElement.EType)i); if (fbxSecondaryUVSet != null) { break; } if (fbxSecondaryUVSet != null) { unityMesh.uv2 = ProcessUVSet(fbxSecondaryUVSet, polygonVertexIndices, vertexCount); uvsetIndex++; } } } }
void PrintAttribute(FbxManager manager, FbxNodeAttribute attri) { FbxLayerElementVertexColor pp; Log.Info("attri " + attri.GetName()); Log.Info("attri type " + Enum.GetName(typeof(FbxNodeAttribute.EType), attri.GetAttributeType())); //attri.is if (attri.GetAttributeType() == FbxNodeAttribute.EType.eMesh) { Type t = attri.GetType(); Log.Info("type name " + t.Name); FbxMesh mesh = attri.GetNode().GetMesh(); //FbxMesh mesh = attri as FbxMesh; if (mesh == null) { Log.Error("convert mesh failed!"); return; } Console.WriteLine($"mesh.GetMeshEdgeCount() = {mesh.GetMeshEdgeCount()}; mesh.GetPolygonCount() = {mesh.GetPolygonCount()}; mesh.GetPolygonVertexCount()={mesh.GetPolygonVertexCount()}; " + $"mesh.GetTextureUVCount() {mesh.GetTextureUVCount()}; mesh.GetControlPointsCount()={mesh.GetControlPointsCount()}; mesh.GetElementTangentCount()={mesh.GetElementTangentCount()};" + $" mesh.GetElementNormalCount()={mesh.GetElementNormalCount()}; mesh.GetElementVertexColorCount()={mesh.GetElementVertexColorCount()};" + $"mesh.GetUVLayerCount() = {mesh.GetUVLayerCount()}; mesh.GetLayerCount() = {mesh.GetLayerCount()}"); var pts = mesh.GetControlPoints(); var ar = FbxVector4Array.frompointer(pts); for (int i = 0; i < mesh.GetLayerCount(); i++) { var layer = mesh.GetLayer(i); } try { var v2 = new FbxVector2(); IntPtr mem = Marshal.AllocHGlobal(4); FbxStringList lst = new FbxStringList(); //int nameCount = lst.GetCount(); mesh.GetUVSetNames(lst); //ToDo : что за List, расширяется ли он сам? var name = lst.GetItemAt(0).mString.Buffer(); //var myBool = new _MyBool(mem); //var res = mesh.GetPolygonVertexUV(0, 0, name, v2, myBool); // var c0 = v2.at(0); // var c2 = v2.at(1); var fbxArV2 = new FbxArrayFbxVector2(); var fbxArI = new FbxArrayInt(); var res = mesh.GetPolygonVertexUVs(name, fbxArV2, fbxArI); var ptr = fbxArV2.GetAt(2).mData; double coord1 = FbxWrapperNative.DoubleArrayFunc_getitem(ptr, 0); double coord2 = FbxWrapperNative.DoubleArrayFunc_getitem(ptr, 1); var param = FbxWrapperNative.new_FbxLayerElementArrayTemplateIntPtrFunc(); res = mesh.GetMaterialIndices(param); var param2 = FbxWrapperNative.FbxLayerElementArrayTemplateIntPtrFunc_value(param); int count = param2.GetCount(); List <int> mind = new List <int>(); for (int i = 0; i < count; i++) { mind.Add(param2.GetAt(i)); } //var vec = new FbxVector4Array(5); //var res2 = mesh.GetPolygonVertexUVs("", , null); bool res1 = mesh.GenerateTangentsData(0); //bool res2 = mesh.GenerateTangentsDataForAllUVSets( ); var tCount = mesh.GetElementTangentCount(); var tang = mesh.GetElementTangent( ); var tangAr = tang.GetDirectArray(); int tC = tangAr.GetCount(); //int binCount = mesh.GetElementBinormalCount(); //var bin = mesh.GetElementBinormal().GetDirectArray().GetCount(); } catch (Exception ex) { } //var vertices = mesh.GetPolygonVertices(); //FbxMesh mesh; //FbxLayerElementUV uv = mesh.GetElementUV(); //uv.GetDirectArray() FbxLayerElementNormal normal = mesh.GetElementNormal(); //ToDo //DirectArrayFbxVector4 array = normal.GetDirectArray(); var array = normal.GetDirectArray(); Log.Info("normal count " + array.GetCount()); //for (int i = 0; i < array.GetCount(); i++) //{ // FbxVector4 v = array.GetAt(i); // SWIGTYPE_p_double data = v.mData; // DoubleArray d = DoubleArray.frompointer(data); // PrintDoubleArray(d, 4); //} } }