@@ -54,7 +54,7 @@ public class ModelExporter : System.IDisposable
54
54
/// <summary>
55
55
/// Export the mesh's UVs using layer 0.
56
56
/// </summary>
57
- public void ExportUVsAndNormals ( MeshInfo mesh , FbxMesh fbxMesh , int [ ] fbxTriangles )
57
+ public void ExportUVsAndNormals ( MeshInfo mesh , FbxMesh fbxMesh , int [ ] unmergedTriangles )
58
58
{
59
59
// Set the normals on Layer 0.
60
60
FbxLayer fbxLayer = fbxMesh . GetLayer ( 0 /* default layer */ ) ;
@@ -65,22 +65,20 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
65
65
66
66
using ( var fbxLayerElement = FbxLayerElementNormal . Create ( fbxMesh , "Normals" ) )
67
67
{
68
- fbxLayerElement . SetMappingMode ( FbxLayerElement . EMappingMode . eByControlPoint ) ;
69
-
70
- // TODO: normals for each triangle vertex instead of averaged per control point
71
- //fbxNormalLayer.SetMappingMode (FbxLayerElement.eByPolygonVertex);
68
+ fbxLayerElement . SetMappingMode ( FbxLayerElement . EMappingMode . eByPolygonVertex ) ;
72
69
73
70
fbxLayerElement . SetReferenceMode ( FbxLayerElement . EReferenceMode . eDirect ) ;
74
71
75
72
// Add one normal per each vertex face index (3 per triangle)
76
73
FbxLayerElementArray fbxElementArray = fbxLayerElement . GetDirectArray ( ) ;
77
74
78
- for ( int n = 0 ; n < mesh . Normals . Length ; n ++ )
79
- {
80
- fbxElementArray . Add ( new FbxVector4 ( - mesh . Normals [ n ] [ 0 ] ,
81
- mesh . Normals [ n ] [ 1 ] ,
82
- mesh . Normals [ n ] [ 2 ] ) ) ;
83
- }
75
+ for ( int n = 0 ; n < unmergedTriangles . Length ; n ++ ) {
76
+ int unityTriangle = unmergedTriangles [ n ] ;
77
+ fbxElementArray . Add ( new FbxVector4 ( - mesh . Normals [ unityTriangle ] [ 0 ] ,
78
+ mesh . Normals [ unityTriangle ] [ 1 ] ,
79
+ mesh . Normals [ unityTriangle ] [ 2 ] ) ) ;
80
+ }
81
+
84
82
fbxLayer . SetNormals ( fbxLayerElement ) ;
85
83
}
86
84
@@ -92,20 +90,19 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
92
90
// set texture coordinates per vertex
93
91
FbxLayerElementArray fbxElementArray = fbxLayerElement . GetDirectArray ( ) ;
94
92
93
+ // TODO: only copy unique UVs into this array, and index appropriately
95
94
for ( int n = 0 ; n < mesh . UV . Length ; n ++ ) {
96
95
fbxElementArray . Add ( new FbxVector2 ( mesh . UV [ n ] [ 0 ] ,
97
96
mesh . UV [ n ] [ 1 ] ) ) ;
98
97
}
99
98
100
99
// For each face index, point to a texture uv
101
- var unityTriangles = mesh . Triangles ;
102
100
FbxLayerElementArray fbxIndexArray = fbxLayerElement . GetIndexArray ( ) ;
103
- fbxIndexArray . SetCount ( unityTriangles . Length ) ;
101
+ fbxIndexArray . SetCount ( unmergedTriangles . Length ) ;
104
102
105
- for ( int i = 0 ; i < fbxTriangles . Length ; i ++ ) {
106
- fbxIndexArray . SetAt ( i , fbxTriangles [ i ] ) ;
103
+ for ( int i = 0 ; i < unmergedTriangles . Length ; i ++ ) {
104
+ fbxIndexArray . SetAt ( i , unmergedTriangles [ i ] ) ;
107
105
}
108
-
109
106
fbxLayer . SetUVs ( fbxLayerElement , FbxLayerElement . EType . eTextureDiffuse ) ;
110
107
}
111
108
}
@@ -215,50 +212,66 @@ public void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, FbxScene fbxScene)
215
212
216
213
NumMeshes ++ ;
217
214
NumTriangles += meshInfo . Triangles . Length / 3 ;
218
- NumVertices += meshInfo . VertexCount ;
219
215
220
216
// create the mesh structure.
221
217
FbxMesh fbxMesh = FbxMesh . Create ( fbxScene , "Scene" ) ;
222
218
223
219
// Create control points.
224
- int NumControlPoints = meshInfo . VertexCount ;
220
+ Dictionary < Vector3 , int > ControlPointToIndex = new Dictionary < Vector3 , int > ( ) ;
221
+
222
+ int NumControlPoints = 0 ;
223
+ for ( int v = 0 ; v < meshInfo . VertexCount ; v ++ ) {
224
+ if ( ControlPointToIndex . ContainsKey ( meshInfo . Vertices [ v ] ) ) {
225
+ continue ;
226
+ }
227
+ ControlPointToIndex [ meshInfo . Vertices [ v ] ] = NumControlPoints ;
228
+
229
+ NumControlPoints ++ ;
230
+ }
231
+
232
+ NumVertices += NumControlPoints ;
225
233
226
234
fbxMesh . InitControlPoints ( NumControlPoints ) ;
227
235
228
236
// copy control point data from Unity to FBX
229
- for ( int v = 0 ; v < meshInfo . VertexCount ; v ++ )
230
- {
237
+ foreach ( var controlPoint in ControlPointToIndex . Keys ) {
231
238
fbxMesh . SetControlPointAt ( new FbxVector4 (
232
- - meshInfo . Vertices [ v ] . x ,
233
- meshInfo . Vertices [ v ] . y ,
234
- meshInfo . Vertices [ v ] . z
235
- ) , v ) ;
239
+ - controlPoint . x ,
240
+ controlPoint . y ,
241
+ controlPoint . z
242
+ ) , ControlPointToIndex [ controlPoint ] ) ;
236
243
}
237
244
238
245
/*
239
246
* Triangles have to be added in reverse order,
240
247
* or else they will be inverted on import
241
248
* (due to the conversion from left to right handed coords)
242
249
*/
243
- int [ ] fbxTriangles = new int [ meshInfo . Triangles . Length ] ;
250
+ int [ ] unmergedTriangles = new int [ meshInfo . Triangles . Length ] ;
244
251
int current = 0 ;
245
252
for ( int f = 0 ; f < meshInfo . Triangles . Length / 3 ; f ++ )
246
253
{
247
254
fbxMesh . BeginPolygon ( ) ;
248
255
256
+ // triangle vertices have to be reordered to be 0,2,1 instead
257
+ // of 0,1,2, as this gets flipped back during import
249
258
foreach ( int val in new int [ ] { 0 , 2 , 1 } ) {
250
259
int tri = meshInfo . Triangles [ 3 * f + val ] ;
260
+
261
+ // Save the triangle order (without merging vertices) so we
262
+ // properly export UVs, normals, binormals, etc.
263
+ unmergedTriangles [ current ] = tri ;
264
+
265
+ int index = ControlPointToIndex [ meshInfo . Vertices [ tri ] ] ;
266
+ tri = index ;
251
267
fbxMesh . AddPolygon ( tri ) ;
252
268
253
- // save the exported triangle order so we
254
- // properly export UVs
255
- fbxTriangles [ current ] = tri ;
256
269
current ++ ;
257
270
}
258
271
fbxMesh . EndPolygon ( ) ;
259
272
}
260
273
261
- ExportUVsAndNormals ( meshInfo , fbxMesh , fbxTriangles ) ;
274
+ ExportUVsAndNormals ( meshInfo , fbxMesh , unmergedTriangles ) ;
262
275
263
276
var fbxMaterial = ExportMaterial ( meshInfo . Material , fbxScene ) ;
264
277
fbxNode . AddMaterial ( fbxMaterial ) ;
0 commit comments