/// <summary> /// Export the mesh's vertex color using layer 0. /// </summary> /// public void ExportVertexColors(MeshInfo mesh, FbxMesh fbxMesh) { // Set the normals on Layer 0. FbxLayer fbxLayer = fbxMesh.GetLayer(0 /* default layer */); if (fbxLayer == null) { fbxMesh.CreateLayer(); fbxLayer = fbxMesh.GetLayer(0 /* default layer */); } using (var fbxLayerElement = FbxLayerElementVertexColor.Create(fbxMesh, "VertexColors")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); // TODO: normals for each triangle vertex instead of averaged per control point //fbxNormalLayer.SetMappingMode (FbxLayerElement.eByPolygonVertex); 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 < mesh.VertexColors.Length; n++) { // Converting to Color from Color32, as Color32 stores the colors // as ints between 0-255, while FbxColor and Color // use doubles between 0-1 Color color = mesh.VertexColors [n]; fbxElementArray.Add(new FbxColor(color.r, color.g, color.b, color.a)); } fbxLayer.SetVertexColors(fbxLayerElement); } }
public FbxLayer GetLayer(int pIndex) { global::System.IntPtr cPtr = FbxWrapperNativePINVOKE.FbxLayerContainer_GetLayer__SWIG_0(swigCPtr, pIndex); FbxLayer ret = (cPtr == global::System.IntPtr.Zero) ? null : new FbxLayer(cPtr, false); return(ret); }
public FbxLayer GetLayer(int pIndex, FbxLayerElement.EType pType, bool pIsUV) { global::System.IntPtr cPtr = FbxWrapperNativePINVOKE.FbxLayerContainer_GetLayer__SWIG_2(swigCPtr, pIndex, (int)pType, pIsUV); FbxLayer ret = (cPtr == global::System.IntPtr.Zero) ? null : new FbxLayer(cPtr, false); return(ret); }
public FbxLayer GetLayer(int pIndex, FbxLayerElement.EType pType) { global::System.IntPtr cPtr = fbx_wrapperPINVOKE.FbxLayerContainer_GetLayer__SWIG_3(swigCPtr, pIndex, (int)pType); FbxLayer ret = (cPtr == global::System.IntPtr.Zero) ? null : new FbxLayer(cPtr, false); return(ret); }
public void Clone(FbxLayer pSrcLayer) { FbxWrapperNativePINVOKE.FbxLayer_Clone(swigCPtr, FbxLayer.getCPtr(pSrcLayer)); if (FbxWrapperNativePINVOKE.SWIGPendingException.Pending) { throw FbxWrapperNativePINVOKE.SWIGPendingException.Retrieve(); } }
public void Clone(FbxLayer pSrcLayer) { fbx_wrapperPINVOKE.FbxLayer_Clone(swigCPtr, FbxLayer.getCPtr(pSrcLayer)); if (fbx_wrapperPINVOKE.SWIGPendingException.Pending) { throw fbx_wrapperPINVOKE.SWIGPendingException.Retrieve(); } }
public bool Equals(FbxLayer other) { if (object.ReferenceEquals(other, null)) { return(false); } return(this.swigCPtr.Handle.Equals(other.swigCPtr.Handle)); }
/// <summary> /// return base layer for mesh /// </summary> /// private FbxLayer GetBaseLayer(FbxMesh fbxMesh) { FbxLayer fbxLayer = fbxMesh.GetLayer(0 /* default layer */); if (fbxLayer == null) { fbxMesh.CreateLayer(); fbxLayer = fbxMesh.GetLayer(0 /* default layer */); } return(fbxLayer); }
public FbxLayer GetLayer(int pIndex) { global::System.IntPtr cPtr = NativeMethods.FbxLayerContainer_GetLayer(swigCPtr, pIndex); FbxLayer ret = (cPtr == global::System.IntPtr.Zero) ? null : new FbxLayer(cPtr, false); if (NativeMethods.SWIGPendingException.Pending) { throw NativeMethods.SWIGPendingException.Retrieve(); } return(ret); }
/// <summary> /// Export the mesh's UVs using layer 0. /// </summary> public void ExportUVs(MeshInfo mesh, FbxMesh fbxMesh) { // Set the normals on Layer 0. FbxLayer fbxLayer = fbxMesh.GetLayer(0 /* default layer */); if (fbxLayer == null) { fbxMesh.CreateLayer(); fbxLayer = fbxMesh.GetLayer(0 /* default layer */); } using (var fbxLayerElement = FbxLayerElementUV.Create(fbxMesh, "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 < mesh.UV.Length; n++) { fbxElementArray.Add(new FbxVector2(mesh.UV [n] [0], mesh.UV [n] [1])); } // For each face index, point to a texture uv var unityTriangles = mesh.Triangles; FbxLayerElementArray fbxIndexArray = fbxLayerElement.GetIndexArray(); fbxIndexArray.SetCount(unityTriangles.Length); for (int i = 0, n = unityTriangles.Length; i < n; ++i) { fbxIndexArray.SetAt(i, unityTriangles[i]); } fbxLayer.SetUVs(fbxLayerElement, FbxLayerElement.EType.eTextureDiffuse); } }
/// <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++; } } } }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FbxLayer obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
protected override FbxMesh GenerateFbx() { string meshName = (Souls.meshRoot != null ? Souls.meshRoot.Name : "") + "_Mesh"; FbxMesh mesh = FbxMesh.Create(Scene, meshName); mesh.InitControlPoints(Souls.mesh.Vertices.Count); int layerIndex = mesh.CreateLayer(); FbxLayer layer = mesh.GetLayer(layerIndex); FbxLayerContainer layerContainer = FbxLayerContainer.Create(Scene, meshName + "_LayerContainer"); FbxLayerElementUV uv = FbxLayerElementUV.Create(layerContainer, "Diffuse"); layer.SetUVs(uv); FbxLayerElementNormal normal = FbxLayerElementNormal.Create(layerContainer, "Normal"); layer.SetNormals(normal); normal.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); normal.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); FbxLayerElementBinormal binormal = FbxLayerElementBinormal.Create(layerContainer, "Binormal"); layer.SetBinormals(binormal); FbxLayerElementTangent tangent = FbxLayerElementTangent.Create(layerContainer, "Tangent"); layer.SetTangents(tangent); tangent.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); tangent.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); for (int vertexIndex = 0; vertexIndex < Souls.mesh.Vertices.Count; ++vertexIndex) { FLVER.Vertex vertex = Souls.mesh.Vertices[vertexIndex]; Vector3 position = vertex.Position; // this fixes vertex positions since otherwise the model is turned inside out // and it appears like it holds weapons in the left hand position.Z = -position.Z; normal.GetDirectArray().Add(vertex.Normal.ToFbxVector4()); tangent.GetDirectArray().Add(new FbxVector4(vertex.Tangents[0].X, vertex.Tangents[0].Y, vertex.Tangents[0].Z)); Vector2 uvValue = new Vector2(0); if (vertex.UVs.Count > 0) { uvValue.X = vertex.UVs[0].X; uvValue.Y = vertex.UVs[0].Y; } uv.GetDirectArray().Add(uvValue.ToFbxVector2()); mesh.SetControlPointAt(position.ToFbxVector4(), vertexIndex); } for (int faceSetIndex = 0; faceSetIndex < Souls.mesh.FaceSets.Count; ++faceSetIndex) { FLVER2.FaceSet faceSet = Souls.mesh.FaceSets[faceSetIndex]; if (faceSet.Flags != FLVER2.FaceSet.FSFlags.None) { continue; } for (int faceStartIndex = 0; faceStartIndex < faceSet.Indices.Count; faceStartIndex += 3) { mesh.AddCompletePolygon( faceSet.Indices[faceStartIndex], faceSet.Indices[faceStartIndex + 1], faceSet.Indices[faceStartIndex + 2] ); //mesh.AddCompletePolygon( // faceSet.Indices[faceStartIndex + 2], // faceSet.Indices[faceStartIndex + 1], // faceSet.Indices[faceStartIndex] //); } } mesh.BuildMeshEdgeArray(); FbxGeometryConverter converter = new FbxGeometryConverter(Scene.GetFbxManager()); converter.ComputeEdgeSmoothingFromNormals(mesh); converter.ComputePolygonSmoothingFromEdgeSmoothing(mesh); return(mesh); }
protected override void CheckScene(FbxScene scene) { base.CheckScene(scene); FbxScene origScene = CreateScene(FbxManager); Assert.IsNotNull(origScene); // Retrieve the mesh from each scene FbxMesh origMesh = origScene.GetRootNode().GetChild(0).GetMesh(); FbxMesh importMesh = scene.GetRootNode().GetChild(0).GetMesh(); // get the layers FbxLayer origLayer = origMesh.GetLayer(0 /* default layer */); FbxLayer importLayer = importMesh.GetLayer(0 /* default layer */); // Check UVs var origUVElement = origLayer.GetUVs(); var importUVElement = importLayer.GetUVs(); Assert.AreEqual(origUVElement.GetMappingMode(), importUVElement.GetMappingMode()); Assert.AreEqual(origUVElement.GetReferenceMode(), importUVElement.GetReferenceMode()); var origUVElementArray = origUVElement.GetDirectArray(); var importUVElementArray = importUVElement.GetDirectArray(); Assert.AreEqual(origUVElementArray.GetCount(), importUVElementArray.GetCount()); for (int i = 0; i < origUVElementArray.GetCount(); i++) { Assert.AreEqual(origUVElementArray.GetAt(i), importUVElementArray.GetAt(i)); } var origUVElementIndex = origUVElement.GetIndexArray(); var importUVElementIndex = origUVElement.GetIndexArray(); Assert.AreEqual(origUVElementIndex.GetCount(), importUVElementIndex.GetCount()); for (int i = 0; i < origUVElementIndex.GetCount(); i++) { Assert.AreEqual(origUVElementIndex.GetAt(i), importUVElementIndex.GetAt(i)); } // Check material and texture var origNode = origScene.GetRootNode().GetChild(0); int origMatIndex = origNode.GetMaterialIndex(m_materialName); Assert.GreaterOrEqual(origMatIndex, 0); var origMaterial = origNode.GetMaterial(origMatIndex); Assert.IsNotNull(origMaterial); var importNode = scene.GetRootNode().GetChild(0); int importMatIndex = importNode.GetMaterialIndex(m_materialName); Assert.GreaterOrEqual(importMatIndex, 0); var importMaterial = importNode.GetMaterial(importMatIndex); Assert.IsNotNull(importMaterial); // TODO: Add ability to Downcast the material to an FbxSurfacePhong. Property[] materialProperties = { new Property(FbxSurfaceMaterial.sDiffuse, PropertyType.Color), new Property(FbxSurfaceMaterial.sEmissive, PropertyType.Color), new Property(FbxSurfaceMaterial.sAmbient, PropertyType.Double3), new Property(FbxSurfaceMaterial.sSpecular, PropertyType.Double3), new Property(FbxSurfaceMaterial.sBumpFactor, PropertyType.Double) }; FbxProperty origMaterialDiffuseProperty = null; FbxProperty importMaterialDiffuseProperty = null; foreach (var prop in materialProperties) { FbxProperty origProp = origMaterial.FindProperty(prop.name); Assert.IsNotNull(origProp); Assert.IsTrue(origProp.IsValid()); FbxProperty importProp = importMaterial.FindProperty(prop.name); Assert.IsNotNull(importProp); Assert.IsTrue(importProp.IsValid()); switch (prop.type) { case PropertyType.Color: Assert.AreEqual(origProp.GetFbxColor(), importProp.GetFbxColor()); break; case PropertyType.Double3: Assert.AreEqual(origProp.GetFbxDouble3(), importProp.GetFbxDouble3()); break; case PropertyType.Double: Assert.AreEqual(origProp.GetDouble(), importProp.GetDouble()); break; default: break; } if (prop.name.Equals(FbxSurfaceMaterial.sDiffuse)) { origMaterialDiffuseProperty = origProp; importMaterialDiffuseProperty = importProp; } } Assert.IsNotNull(origMaterialDiffuseProperty); Assert.IsNotNull(importMaterialDiffuseProperty); var origTexture = origMaterialDiffuseProperty.FindSrcObject(FbxSurfaceMaterial.sDiffuse + "_Texture"); Assert.IsNotNull(origTexture); var importTexture = importMaterialDiffuseProperty.FindSrcObject(FbxSurfaceMaterial.sDiffuse + "_Texture"); Assert.IsNotNull(importTexture); // TODO: Trying to Downcast the texture to an FbxFileTexture returns a null value, // need to figure out how to fix this so we can access the texture properties. /*Assert.AreEqual (origTexture.GetFileName (), importTexture.GetFileName ()); * Assert.AreEqual (origTexture.GetTextureUse (), importTexture.GetTextureUse ()); * Assert.AreEqual (origTexture.GetMappingType (), importTexture.GetMappingType ());*/ }
protected override FbxScene CreateScene(FbxManager manager) { FbxScene scene = base.CreateScene(manager); // Set the UVs FbxMesh cubeMesh = scene.GetRootNode().GetChild(0).GetMesh(); FbxLayer fbxLayer = cubeMesh.GetLayer(0 /* default layer */); if (fbxLayer == null) { cubeMesh.CreateLayer(); fbxLayer = cubeMesh.GetLayer(0 /* default layer */); } 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); } // Create the material var fbxMaterial = FbxSurfacePhong.Create(scene, m_materialName); fbxMaterial.Diffuse.Set(new FbxColor(1, 1, 1)); fbxMaterial.Emissive.Set(new FbxColor(0.5, 0.1, 0.2)); fbxMaterial.Ambient.Set(new FbxDouble3(0.3, 0.4, 0)); fbxMaterial.BumpFactor.Set(0.6); fbxMaterial.Specular.Set(new FbxDouble3(0.8, 0.7, 0.9)); // Create and add the texture var fbxMaterialProperty = fbxMaterial.FindProperty(FbxSurfaceMaterial.sDiffuse); Assert.IsNotNull(fbxMaterialProperty); Assert.IsTrue(fbxMaterialProperty.IsValid()); var fbxTexture = FbxFileTexture.Create(fbxMaterial, FbxSurfaceMaterial.sDiffuse + "_Texture"); fbxTexture.SetFileName("/path/to/some/texture.jpg"); fbxTexture.SetTextureUse(FbxTexture.ETextureUse.eStandard); fbxTexture.SetMappingType(FbxTexture.EMappingType.eUV); fbxTexture.ConnectDstProperty(fbxMaterialProperty); scene.GetRootNode().GetChild(0).AddMaterial(fbxMaterial); return(scene); }
protected override void CheckScene(FbxScene scene) { base.CheckScene(scene); FbxScene origScene = CreateScene(FbxManager); Assert.IsNotNull(origScene); // Retrieve the mesh from each scene FbxMesh origMesh = origScene.GetRootNode().GetChild(0).GetMesh(); FbxMesh importMesh = scene.GetRootNode().GetChild(0).GetMesh(); // get the layers FbxLayer origLayer = origMesh.GetLayer(0 /* default layer */); FbxLayer importLayer = importMesh.GetLayer(0 /* default layer */); // Check normals CheckFbxElementVector4(origLayer.GetNormals(), importLayer.GetNormals()); // Check binormals CheckFbxElementVector4(origLayer.GetBinormals(), importLayer.GetBinormals()); // Check tangents CheckFbxElementVector4(origLayer.GetTangents(), importLayer.GetTangents()); // Check vertex colors var origVertexColorElement = origLayer.GetVertexColors(); var importVertexColorElement = importLayer.GetVertexColors(); Assert.AreEqual(origVertexColorElement.GetMappingMode(), importVertexColorElement.GetMappingMode()); Assert.AreEqual(origVertexColorElement.GetReferenceMode(), importVertexColorElement.GetReferenceMode()); var origVertexColorElementArray = origVertexColorElement.GetDirectArray(); var importVertexColorElementArray = importVertexColorElement.GetDirectArray(); Assert.AreEqual(origVertexColorElementArray.GetCount(), importVertexColorElementArray.GetCount()); for (int i = 0; i < origVertexColorElementArray.GetCount(); i++) { Assert.AreEqual(origVertexColorElementArray.GetAt(i), importVertexColorElementArray.GetAt(i)); } // Check UVs var origUVElement = origLayer.GetUVs(); var importUVElement = importLayer.GetUVs(); Assert.AreEqual(origUVElement.GetMappingMode(), importUVElement.GetMappingMode()); Assert.AreEqual(origUVElement.GetReferenceMode(), importUVElement.GetReferenceMode()); var origUVElementArray = origUVElement.GetDirectArray(); var importUVElementArray = importUVElement.GetDirectArray(); Assert.AreEqual(origUVElementArray.GetCount(), importUVElementArray.GetCount()); for (int i = 0; i < origUVElementArray.GetCount(); i++) { Assert.AreEqual(origUVElementArray.GetAt(i), importUVElementArray.GetAt(i)); } var origUVElementIndex = origUVElement.GetIndexArray(); var importUVElementIndex = origUVElement.GetIndexArray(); Assert.AreEqual(origUVElementIndex.GetCount(), importUVElementIndex.GetCount()); for (int i = 0; i < origUVElementIndex.GetCount(); i++) { Assert.AreEqual(origUVElementIndex.GetAt(i), importUVElementIndex.GetAt(i)); } }
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); }
public void TestGetPolygonVertexNormal() { using (FbxMesh mesh = CreateObject("mesh")) { mesh.InitControlPoints(4); mesh.SetControlPointAt(new FbxVector4(0, 0, 0), 0); mesh.SetControlPointAt(new FbxVector4(1, 0, 0), 1); mesh.SetControlPointAt(new FbxVector4(1, 0, 1), 2); mesh.SetControlPointAt(new FbxVector4(0, 0, 1), 3); mesh.BeginPolygon(); mesh.AddPolygon(0); mesh.AddPolygon(1); mesh.AddPolygon(2); mesh.AddPolygon(3); mesh.EndPolygon(); // Add normals to the mesh FbxVector4 normal0 = new FbxVector4(0, 0, 1); FbxVector4 normal1 = new FbxVector4(0, 1, 0); FbxVector4 normal2 = new FbxVector4(0, 1, 1); FbxVector4 normal3 = new FbxVector4(0.301511344577764d, 0.904534033733291d, 0.301511344577764d); using (var fbxLayerElement = FbxLayerElementNormal.Create(mesh, "Normals")) { // Set the Normals on the default layer FbxLayer fbxLayer = mesh.GetLayer(0); if (fbxLayer == null) { mesh.CreateLayer(); fbxLayer = mesh.GetLayer(0); } fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); fbxLayerElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray(); fbxElementArray.Add(normal0); fbxElementArray.Add(normal1); fbxElementArray.Add(normal2); fbxElementArray.Add(normal3); fbxLayer.SetNormals(fbxLayerElement); } FbxVector4 readNormal0; FbxVector4 readNormal1; FbxVector4 readNormal2; FbxVector4 readNormal3; // test if all normals can be read Assert.IsTrue(mesh.GetPolygonVertexNormal(0, 0, out readNormal0)); Assert.IsTrue(mesh.GetPolygonVertexNormal(0, 1, out readNormal1)); Assert.IsTrue(mesh.GetPolygonVertexNormal(0, 2, out readNormal2)); Assert.IsTrue(mesh.GetPolygonVertexNormal(0, 3, out readNormal3)); // test if the normals have the correct values Assert.That(normal0.X, Is.EqualTo(readNormal0.X).Using(FloatEqualityComparer.Instance)); Assert.That(normal0.Y, Is.EqualTo(readNormal0.Y).Using(FloatEqualityComparer.Instance)); Assert.That(normal0.Z, Is.EqualTo(readNormal0.Z).Using(FloatEqualityComparer.Instance)); Assert.That(normal0.W, Is.EqualTo(readNormal0.W).Using(FloatEqualityComparer.Instance)); Assert.That(normal1.X, Is.EqualTo(readNormal1.X).Using(FloatEqualityComparer.Instance)); Assert.That(normal1.Y, Is.EqualTo(readNormal1.Y).Using(FloatEqualityComparer.Instance)); Assert.That(normal1.Z, Is.EqualTo(readNormal1.Z).Using(FloatEqualityComparer.Instance)); Assert.That(normal1.W, Is.EqualTo(readNormal1.W).Using(FloatEqualityComparer.Instance)); Assert.That(normal2.X, Is.EqualTo(readNormal2.X).Using(FloatEqualityComparer.Instance)); Assert.That(normal2.Y, Is.EqualTo(readNormal2.Y).Using(FloatEqualityComparer.Instance)); Assert.That(normal2.Z, Is.EqualTo(readNormal2.Z).Using(FloatEqualityComparer.Instance)); Assert.That(normal2.W, Is.EqualTo(readNormal2.W).Using(FloatEqualityComparer.Instance)); Assert.That(normal3.X, Is.EqualTo(readNormal3.X).Using(FloatEqualityComparer.Instance)); Assert.That(normal3.Y, Is.EqualTo(readNormal3.Y).Using(FloatEqualityComparer.Instance)); Assert.That(normal3.Z, Is.EqualTo(readNormal3.Z).Using(FloatEqualityComparer.Instance)); Assert.That(normal3.W, Is.EqualTo(readNormal3.W).Using(FloatEqualityComparer.Instance)); } }
// For use only by FbxExportGlobals. internal static FbxMesh CreateFbxMesh(FbxExportGlobals G, GeometryPool pool, string poolName) { FbxMesh fbxMesh = FbxMesh.Create(G.m_manager, poolName); ExportMesh mesh = new ExportMesh(pool); int nVerts = mesh.m_pool.m_Vertices.Count; fbxMesh.InitControlPoints(nVerts); unsafe { fixed(Vector3 *f = mesh.m_pool.m_Vertices.GetBackingArray()) { Globals.SetControlPoints(fbxMesh, (IntPtr)f); } } List <int> triangles = mesh.m_pool.m_Tris; // Not available in Unity's wrappers // fbxMesh.ReservePolygonCount(triangles.Count / 3); // fbxMesh.ReservePolygonVertexCount(triangles.Count); for (int i = 0; i < triangles.Count; i += 3) { fbxMesh.BeginPolygon(-1 /* Material */, -1 /* Texture */, -1 /* Group */, false /* Legacy */); fbxMesh.AddPolygon(triangles[i]); fbxMesh.AddPolygon(triangles[i + 1]); fbxMesh.AddPolygon(triangles[i + 2]); fbxMesh.EndPolygon(); } FbxLayer layer0 = fbxMesh.GetLayer(0); if (layer0 == null) { fbxMesh.CreateLayer(); layer0 = fbxMesh.GetLayer(0); } var layerElementNormal = FbxLayerElementNormal.Create(fbxMesh, "normals"); layerElementNormal.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); layerElementNormal.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); CopyToFbx(layerElementNormal.GetDirectArray(), mesh.m_pool.m_Normals); layer0.SetNormals(layerElementNormal); var layerElementColor = FbxLayerElementVertexColor.Create(fbxMesh, "color"); layerElementColor.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); layerElementColor.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); CopyToFbx(layerElementColor.GetDirectArray(), mesh.m_linearColor); layer0.SetVertexColors(layerElementColor); var layerElementTangent = FbxLayerElementTangent.Create(fbxMesh, "tangents"); layerElementTangent.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); layerElementTangent.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); CopyToFbx(layerElementTangent.GetDirectArray(), mesh.m_pool.m_Tangents); layer0.SetTangents(layerElementTangent); // Compute and export binormals since Unity's FBX importer won't import the tangents without // them, even though they're not used. var layerElementBinormal = FbxLayerElementBinormal.Create(fbxMesh, "binormals"); layerElementBinormal.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); layerElementBinormal.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); var binormals = mesh.m_pool.m_Tangents .Select((tan, idx) => { var b3 = Vector3.Cross(tan, mesh.m_pool.m_Normals[idx]) * tan.w; return(new Vector4(b3.x, b3.y, b3.z, 1)); }) .ToList(); CopyToFbx(layerElementBinormal.GetDirectArray(), binormals); layer0.SetBinormals(layerElementBinormal); var layerElementMaterial = FbxLayerElementMaterial.Create(fbxMesh, "materials"); layerElementMaterial.SetMappingMode(FbxLayerElement.EMappingMode.eAllSame); layer0.SetMaterials(layerElementMaterial); // Export everything up to the last uvset containing data // even if some intermediate uvsets have no data. // Otherwise Unity will get the uvset numbering wrong on import List <List <Vector2> > uvSets = DemuxTexcoords(mesh.m_pool); for (int i = 0; i < uvSets.Count; i++) { FbxLayer layerN = fbxMesh.GetLayer(i); while (layerN == null) { fbxMesh.CreateLayer(); layerN = fbxMesh.GetLayer(i); } var layerElementUV = FbxLayerElementUV.Create(fbxMesh, String.Format("uv{0}", i)); layerElementUV.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); layerElementUV.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); List <Vector2> uvSet = uvSets[i]; if (uvSet == null) { // Do nothing // Replicates what the old fbx export code did; seems to work fine } else { Debug.Assert(uvSet.Count == nVerts); CopyToFbx(layerElementUV.GetDirectArray(), uvSet); } layerN.SetUVs(layerElementUV, FbxLayerElement.EType.eTextureDiffuse); } return(fbxMesh); }
/// <summary> /// Export the mesh's normals, binormals and tangents using /// layer 0. /// </summary> /// public void ExportNormalsEtc(MeshInfo mesh, FbxMesh fbxMesh) { /// Set the Normals on Layer 0. FbxLayer fbxLayer = fbxMesh.GetLayer(0 /* default layer */); if (fbxLayer == null) { fbxMesh.CreateLayer(); fbxLayer = fbxMesh.GetLayer(0 /* default layer */); } using (var fbxLayerElement = FbxLayerElementNormal.Create(fbxMesh, "Normals")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); // TODO: normals for each triangle vertex instead of averaged per control point //fbxNormalLayer.SetMappingMode (FbxLayerElement.eByPolygonVertex); 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 < mesh.Normals.Length; n++) { fbxElementArray.Add(new FbxVector4(mesh.Normals [n] [0], mesh.Normals [n] [1], mesh.Normals [n] [2])); } fbxLayer.SetNormals(fbxLayerElement); } /// Set the binormals on Layer 0. using (var fbxLayerElement = FbxLayerElementBinormal.Create(fbxMesh, "Binormals")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); // TODO: normals for each triangle vertex instead of averaged per control point //fbxBinormalLayer.SetMappingMode (FbxLayerElement.eByPolygonVertex); 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 < mesh.Binormals.Length; n++) { fbxElementArray.Add(new FbxVector4(mesh.Binormals [n] [0], mesh.Binormals [n] [1], mesh.Binormals [n] [2])); } fbxLayer.SetBinormals(fbxLayerElement); } /// Set the tangents on Layer 0. using (var fbxLayerElement = FbxLayerElementTangent.Create(fbxMesh, "Tangents")) { fbxLayerElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); // TODO: normals for each triangle vertex instead of averaged per control point //fbxBinormalLayer.SetMappingMode (FbxLayerElement.eByPolygonVertex); 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 < mesh.Normals.Length; n++) { fbxElementArray.Add(new FbxVector4(mesh.Tangents [n] [0], mesh.Tangents [n] [1], mesh.Tangents [n] [2])); } fbxLayer.SetTangents(fbxLayerElement); } }