public void GeometryBase_InitControlPoints_InitsControlPoints() { // given: var gb = new FbxMesh(""); // require: Assert.AreEqual(0, gb.GetControlPointsCount()); // when: gb.InitControlPoints(4); // then: Assert.AreEqual(4, gb.GetControlPointsCount()); // when: gb.InitControlPoints(20); // then: Assert.AreEqual(20, gb.GetControlPointsCount()); // when: gb.InitControlPoints(3); // then: Assert.AreEqual(3, gb.GetControlPointsCount()); }
protected override void CheckScene(FbxScene scene) { FbxScene origScene = CreateScene(FbxManager); Assert.IsNotNull(origScene); Assert.IsNotNull(scene); // Retrieve the mesh from each scene FbxMesh origMesh = origScene.GetRootNode().GetChild(0).GetMesh(); FbxMesh importMesh = scene.GetRootNode().GetChild(0).GetMesh(); Assert.IsNotNull(origMesh); Assert.IsNotNull(importMesh); // check that the control points match Assert.AreEqual(origMesh.GetControlPointsCount(), importMesh.GetControlPointsCount()); for (int i = 0; i < origMesh.GetControlPointsCount(); i++) { FbxVector4 origControlPoint = origMesh.GetControlPointAt(i); FbxVector4 importControlPoint = importMesh.GetControlPointAt(i); // Note: Ignoring W as no matter what it is set to it always imports as 0 Assert.AreEqual(origControlPoint.X, importControlPoint.X); Assert.AreEqual(origControlPoint.Y, importControlPoint.Y); Assert.AreEqual(origControlPoint.Z, importControlPoint.Z); } }
public void Mesh_Create() { // given: var mesh = new FbxMesh("Mesh"); // then: Assert.AreEqual(0, mesh.GetControlPointsCount()); }
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> /// Convert scene's system units but leave scaling unchanged /// </summary> public void ConvertScene(FbxScene fbxScene, FbxSystemUnit toUnits) { // Get scale factor. float scaleFactor = 1.0f; scaleFactor = (float)fbxScene.GetGlobalSettings().GetSystemUnit().GetConversionFactorTo(toUnits); if (scaleFactor.Equals(1.0f)) { return; } // Get root node. FbxNode fbxRootNode = fbxScene.GetRootNode(); // For all the nodes to convert the translations Queue <FbxNode> fbxNodes = new Queue <FbxNode> (); fbxNodes.Enqueue(fbxRootNode); while (fbxNodes.Count > 0) { FbxNode fbxNode = fbxNodes.Dequeue(); // Convert node's translation. FbxDouble3 lclTrs = fbxNode.LclTranslation.Get(); #if UNI_18844 lclTrs *= scaleFactor; lclTrs *= scaleFactor; lclTrs *= scaleFactor; #endif fbxNode.LclTranslation.Set(lclTrs); FbxMesh fbxMesh = fbxNode.GetMesh(); if (fbxMesh != null) { for (int i = 0; i < fbxMesh.GetControlPointsCount(); ++i) { FbxVector4 fbxVector4 = fbxMesh.GetControlPointAt(i); #if UNI_18844 fbxVector4 *= scaleFactor; #endif fbxMesh.SetControlPointAt(fbxVector4, i); } } for (int i = 0; i < fbxNode.GetChildCount(); ++i) { fbxNodes.Enqueue(fbxNode.GetChild(i)); } } }
protected override FbxScene CreateScene(FbxManager manager) { // Create a cube as a static mesh FbxScene scene = FbxScene.Create(manager, "myScene"); FbxNode meshNode = FbxNode.Create(scene, "MeshNode"); FbxMesh cubeMesh = FbxMesh.Create(scene, "cube"); meshNode.SetNodeAttribute(cubeMesh); scene.GetRootNode().AddChild(meshNode); cubeMesh.InitControlPoints(24); for (int i = 0; i < cubeMesh.GetControlPointsCount(); i++) { cubeMesh.SetControlPointAt(m_controlPoints [i], i); } // A cube: 6 polygons with 4 vertices each int[] vertices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; for (int i = 0; i < 6; i++) { cubeMesh.BeginPolygon(pGroup: -1); for (int j = 0; j < 4; j++) { cubeMesh.AddPolygon(vertices[i * 4 + j]); } cubeMesh.EndPolygon(); } return(scene); }
protected override FbxScene CreateScene(FbxManager manager) { // Create a cube as a static mesh FbxScene scene = FbxScene.Create(manager, "myScene"); FbxNode meshNode = FbxNode.Create(scene, "MeshNode"); FbxMesh cubeMesh = FbxMesh.Create(scene, "cube"); meshNode.SetNodeAttribute(cubeMesh); scene.GetRootNode().AddChild(meshNode); cubeMesh.InitControlPoints(24); for (int i = 0; i < cubeMesh.GetControlPointsCount(); i++) { cubeMesh.SetControlPointAt(m_controlPoints [i], i); } return(scene); }
private static long GetTotalVerts(FbxNode node) { FbxNodeAttribute a = node.GetNodeAttribute(); int nChildren = node.GetChildCount(); long vertCount = 0; if (a != null) { var attrType = a.GetAttributeType(); if (attrType == FbxNodeAttribute.EType.eMesh) { FbxMesh fbxMesh = node.GetMesh(); fbxMesh.SplitPoints(); vertCount = fbxMesh.GetControlPointsCount(); } } for (int i = 0; i < nChildren; i++) { vertCount += GetTotalVerts(node.GetChild(i)); } return(vertCount); }
public void GeometryBase_SetControlPointAt_SetsControlPoint() { // given: var gb = new FbxMesh(""); gb.InitControlPoints(4); // require: Assert.AreEqual(4, gb.GetControlPointsCount()); Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(0)); Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(1)); Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(2)); Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(3)); // when: gb.SetControlPointAt(new FbxVector4(1.2, 3.4, 5.6, 7.8), 2); // then: Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(0)); Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(1)); Assert.AreEqual(new FbxVector4(1.2, 3.4, 5.6, 7.8), gb.GetControlPointAt(2)); Assert.AreEqual(new FbxVector4(0, 0, 0, 0), gb.GetControlPointAt(3)); }
/// <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); } }
protected override FbxScene CreateScene(FbxManager manager) { FbxScene scene = base.CreateScene(manager); // Add normals, binormals, UVs, tangents and vertex colors to the cube FbxMesh cubeMesh = scene.GetRootNode().GetChild(0).GetMesh(); // Add normals /// Set the Normals on Layer 0. FbxLayer fbxLayer = cubeMesh.GetLayer(0 /* default layer */); if (fbxLayer == null) { cubeMesh.CreateLayer(); fbxLayer = cubeMesh.GetLayer(0 /* default layer */); } using (var fbxLayerElement = FbxLayerElementNormal.Create(cubeMesh, "Normals")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); fbxLayerElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); // Add one normal per each vertex face index (3 per triangle) FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray(); // Assign the normal vectors in the same order the control points were defined FbxVector4[] normals = { normalZPos, normalXPos, normalZNeg, normalXNeg, normalYPos, normalYNeg }; for (int n = 0; n < normals.Length; n++) { for (int i = 0; i < 4; i++) { fbxElementArray.Add(normals [n]); } } fbxLayer.SetNormals(fbxLayerElement); } /// Set the binormals on Layer 0. using (var fbxLayerElement = FbxLayerElementBinormal.Create(cubeMesh, "Binormals")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); fbxLayerElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); // Add one normal per each vertex face index (3 per triangle) FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray(); for (int n = 0; n < cubeMesh.GetControlPointsCount(); n++) { fbxElementArray.Add(new FbxVector4(-1, 0, 1)); // TODO: set to correct values } fbxLayer.SetBinormals(fbxLayerElement); } /// Set the tangents on Layer 0. using (var fbxLayerElement = FbxLayerElementTangent.Create(cubeMesh, "Tangents")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); fbxLayerElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); // Add one normal per each vertex face index (3 per triangle) FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray(); for (int n = 0; n < cubeMesh.GetControlPointsCount(); n++) { fbxElementArray.Add(new FbxVector4(0, -1, 1)); // TODO: set to correct values } fbxLayer.SetTangents(fbxLayerElement); } // set the vertex colors using (var fbxLayerElement = FbxLayerElementVertexColor.Create(cubeMesh, "VertexColors")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); fbxLayerElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); // Add one normal per each vertex face index (3 per triangle) FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray(); // make each vertex either black or white for (int n = 0; n < cubeMesh.GetControlPointsCount(); n++) { fbxElementArray.Add(new FbxColor(n % 2, n % 2, n % 2)); } fbxLayer.SetVertexColors(fbxLayerElement); } // set the UVs using (var fbxLayerElement = FbxLayerElementUV.Create(cubeMesh, "UVSet")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByPolygonVertex); fbxLayerElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eIndexToDirect); // set texture coordinates per vertex FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray(); for (int n = 0; n < 8; n++) { fbxElementArray.Add(new FbxVector2(n % 2, 1)); // TODO: switch to correct values } // For each face index, point to a texture uv FbxLayerElementArray fbxIndexArray = fbxLayerElement.GetIndexArray(); fbxIndexArray.SetCount(24); for (int vertIndex = 0; vertIndex < 24; vertIndex++) { fbxIndexArray.SetAt(vertIndex, vertIndex % 8); // TODO: switch to correct values } fbxLayer.SetUVs(fbxLayerElement, FbxLayerElement.EType.eTextureDiffuse); } return(scene); }
/// <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); //} } }