@@ -65,7 +65,9 @@ public static ModelExporter Create ()
65
65
Dictionary < string , FbxTexture > TextureMap = new Dictionary < string , FbxTexture > ( ) ;
66
66
67
67
/// <summary>
68
+ /// Map the name of a prefab to an FbxMesh (for preserving instances)
68
69
/// </summary>
70
+ Dictionary < string , FbxMesh > SharedMeshes = new Dictionary < string , FbxMesh > ( ) ;
69
71
70
72
/// <summary>
71
73
/// return layer for mesh
@@ -304,14 +306,13 @@ public FbxDouble3 GetMaterialColor (Material unityMaterial, string unityPropName
304
306
/// <summary>
305
307
/// Export (and map) a Unity PBS material to FBX classic material
306
308
/// </summary>
307
- public FbxSurfaceMaterial ExportMaterial ( Material unityMaterial , FbxScene fbxScene , FbxMesh fbxMesh )
309
+ public FbxSurfaceMaterial ExportMaterial ( Material unityMaterial , FbxScene fbxScene )
308
310
{
309
311
if ( Verbose )
310
312
Debug . Log ( string . Format ( "exporting material {0}" , unityMaterial . name ) ) ;
311
313
312
314
var materialName = unityMaterial ? unityMaterial . name : "DefaultMaterial" ;
313
315
if ( MaterialMap . ContainsKey ( materialName ) ) {
314
- AssignLayerElementMaterial ( fbxMesh ) ;
315
316
return MaterialMap [ materialName ] ;
316
317
}
317
318
@@ -343,13 +344,21 @@ public FbxSurfaceMaterial ExportMaterial (Material unityMaterial, FbxScene fbxSc
343
344
ExportTexture ( unityMaterial , "_SpecGlosMap" , fbxMaterial , FbxSurfaceMaterial . sSpecular ) ;
344
345
}
345
346
346
- AssignLayerElementMaterial ( fbxMesh ) ;
347
-
348
347
MaterialMap . Add ( materialName , fbxMaterial ) ;
349
348
return fbxMaterial ;
350
349
}
351
350
352
- private void AssignLayerElementMaterial ( FbxMesh fbxMesh )
351
+ /// <summary>
352
+ /// Sets up the material to polygon mapping for fbxMesh.
353
+ /// To determine which part of the mesh uses which material, look at the submeshes
354
+ /// and which polygons they represent.
355
+ /// Assuming equal number of materials as submeshes, and that they are in the same order.
356
+ /// (i.e. submesh 1 uses material 1)
357
+ /// </summary>
358
+ /// <param name="fbxMesh">Fbx mesh.</param>
359
+ /// <param name="mesh">Mesh.</param>
360
+ /// <param name="materials">Materials.</param>
361
+ private void AssignLayerElementMaterial ( FbxMesh fbxMesh , Mesh mesh , int materialCount )
353
362
{
354
363
// Add FbxLayerElementMaterial to layer 0 of the node
355
364
FbxLayer fbxLayer = fbxMesh . GetLayer ( 0 /* default layer */ ) ;
@@ -359,14 +368,31 @@ private void AssignLayerElementMaterial(FbxMesh fbxMesh)
359
368
}
360
369
361
370
using ( var fbxLayerElement = FbxLayerElementMaterial . Create ( fbxMesh , "Material" ) ) {
362
- // Using all same means that the entire mesh uses the same material
363
- fbxLayerElement . SetMappingMode ( FbxLayerElement . EMappingMode . eAllSame ) ;
364
- fbxLayerElement . SetReferenceMode ( FbxLayerElement . EReferenceMode . eIndexToDirect ) ;
371
+ // if there is only one material then set everything to that material
372
+ if ( materialCount == 1 ) {
373
+ fbxLayerElement . SetMappingMode ( FbxLayerElement . EMappingMode . eAllSame ) ;
374
+ fbxLayerElement . SetReferenceMode ( FbxLayerElement . EReferenceMode . eIndexToDirect ) ;
375
+
376
+ FbxLayerElementArray fbxElementArray = fbxLayerElement . GetIndexArray ( ) ;
377
+ fbxElementArray . Add ( 0 ) ;
378
+ } else {
379
+ fbxLayerElement . SetMappingMode ( FbxLayerElement . EMappingMode . eByPolygon ) ;
380
+ fbxLayerElement . SetReferenceMode ( FbxLayerElement . EReferenceMode . eIndexToDirect ) ;
381
+
382
+ FbxLayerElementArray fbxElementArray = fbxLayerElement . GetIndexArray ( ) ;
365
383
366
- FbxLayerElementArray fbxElementArray = fbxLayerElement . GetIndexArray ( ) ;
384
+ // assuming that each polygon is a triangle
385
+ // TODO: Add support for other mesh topologies (e.g. quads)
386
+ fbxElementArray . SetCount ( mesh . triangles . Length / 3 ) ;
367
387
368
- // Map the entire geometry to the FbxNode material at index 0
369
- fbxElementArray . Add ( 0 ) ;
388
+ for ( int i = 0 ; i < mesh . subMeshCount ; i ++ ) {
389
+ int start = ( ( int ) mesh . GetIndexStart ( i ) ) / 3 ;
390
+ int count = ( ( int ) mesh . GetIndexCount ( i ) ) / 3 ;
391
+ for ( int j = start ; j < start + count ; j ++ ) {
392
+ fbxElementArray . SetAt ( j , i ) ;
393
+ }
394
+ }
395
+ }
370
396
fbxLayer . SetMaterials ( fbxLayerElement ) ;
371
397
}
372
398
}
@@ -375,10 +401,10 @@ private void AssignLayerElementMaterial(FbxMesh fbxMesh)
375
401
/// Unconditionally export this mesh object to the file.
376
402
/// We have decided; this mesh is definitely getting exported.
377
403
/// </summary>
378
- public void ExportMesh ( MeshInfo meshInfo , FbxNode fbxNode , FbxScene fbxScene , bool weldVertices = true )
404
+ public FbxMesh ExportMesh ( MeshInfo meshInfo , FbxNode fbxNode , FbxScene fbxScene , bool weldVertices = true )
379
405
{
380
406
if ( ! meshInfo . IsValid )
381
- return ;
407
+ return null ;
382
408
383
409
NumMeshes ++ ;
384
410
NumTriangles += meshInfo . Triangles . Length / 3 ;
@@ -427,8 +453,10 @@ meshInfo.Vertices [v].z*UnitScaleFactor
427
453
}
428
454
}
429
455
430
- var fbxMaterial = ExportMaterial ( meshInfo . Material , fbxScene , fbxMesh ) ;
431
- fbxNode . AddMaterial ( fbxMaterial ) ;
456
+ foreach ( var mat in meshInfo . Materials ) {
457
+ var fbxMaterial = ExportMaterial ( mat , fbxScene ) ;
458
+ fbxNode . AddMaterial ( fbxMaterial ) ;
459
+ }
432
460
433
461
/*
434
462
* Triangles have to be added in reverse order,
@@ -459,11 +487,15 @@ meshInfo.Vertices [v].z*UnitScaleFactor
459
487
fbxMesh . EndPolygon ( ) ;
460
488
}
461
489
490
+ AssignLayerElementMaterial ( fbxMesh , meshInfo . mesh , meshInfo . Materials . Length ) ;
491
+
462
492
ExportComponentAttributes ( meshInfo , fbxMesh , unmergedTriangles ) ;
463
493
464
494
// set the fbxNode containing the mesh
465
495
fbxNode . SetNodeAttribute ( fbxMesh ) ;
466
496
fbxNode . SetShadingMode ( FbxNode . EShadingMode . eWireFrame ) ;
497
+
498
+ return fbxMesh ;
467
499
}
468
500
469
501
// get a fbxNode's global default position.
@@ -517,6 +549,40 @@ protected void ExportTransform (UnityEngine.Transform unityTransform, FbxNode fb
517
549
return ;
518
550
}
519
551
552
+ /// <summary>
553
+ /// if this game object is a model prefab then export with shared components
554
+ /// </summary>
555
+ protected bool ExportInstance ( GameObject unityGo , FbxNode fbxNode , FbxScene fbxScene )
556
+ {
557
+ PrefabType unityPrefabType = PrefabUtility . GetPrefabType ( unityGo ) ;
558
+
559
+ if ( unityPrefabType != PrefabType . PrefabInstance ) return false ;
560
+
561
+ Object unityPrefabParent = PrefabUtility . GetPrefabParent ( unityGo ) ;
562
+
563
+ if ( Verbose )
564
+ Debug . Log ( string . Format ( "exporting instance {0}({1})" , unityGo . name , unityPrefabParent . name ) ) ;
565
+
566
+ FbxMesh fbxMesh = null ;
567
+
568
+ if ( ! SharedMeshes . TryGetValue ( unityPrefabParent . name , out fbxMesh ) )
569
+ {
570
+ bool weldVertices = FbxExporters . EditorTools . ExportSettings . instance . weldVertices ;
571
+ fbxMesh = ExportMesh ( GetMeshInfo ( unityGo ) , fbxNode , fbxScene , weldVertices ) ;
572
+ if ( fbxMesh != null ) {
573
+ SharedMeshes [ unityPrefabParent . name ] = fbxMesh ;
574
+ }
575
+ }
576
+
577
+ if ( fbxMesh == null ) return false ;
578
+
579
+ // set the fbxNode containing the mesh
580
+ fbxNode . SetNodeAttribute ( fbxMesh ) ;
581
+ fbxNode . SetShadingMode ( FbxNode . EShadingMode . eWireFrame ) ;
582
+
583
+ return true ;
584
+ }
585
+
520
586
/// <summary>
521
587
/// Unconditionally export components on this game object
522
588
/// </summary>
@@ -545,8 +611,11 @@ protected int ExportComponents (
545
611
546
612
ExportTransform ( unityGo . transform , fbxNode , exportType ) ;
547
613
548
- bool weldVertices = FbxExporters . EditorTools . ExportSettings . instance . weldVertices ;
549
- ExportMesh ( GetMeshInfo ( unityGo ) , fbxNode , fbxScene , weldVertices ) ;
614
+ // try exporting mesh as an instance, export regularly if we cannot
615
+ if ( ! ExportInstance ( unityGo , fbxNode , fbxScene ) ) {
616
+ bool weldVertices = FbxExporters . EditorTools . ExportSettings . instance . weldVertices ;
617
+ ExportMesh ( GetMeshInfo ( unityGo ) , fbxNode , fbxScene , weldVertices ) ;
618
+ }
550
619
551
620
if ( Verbose )
552
621
Debug . Log ( string . Format ( "exporting {0}" , fbxNode . GetName ( ) ) ) ;
@@ -895,7 +964,7 @@ public Vector3 [] Binormals {
895
964
/// The material used, if any; otherwise null.
896
965
/// We don't support multiple materials on one gameobject.
897
966
/// </summary>
898
- public Material Material {
967
+ public Material [ ] Materials {
899
968
get {
900
969
if ( ! unityObject ) {
901
970
return null ;
@@ -906,12 +975,14 @@ public Material Material {
906
975
}
907
976
908
977
if ( FbxExporters . EditorTools . ExportSettings . instance . mayaCompatibleNames ) {
909
- renderer . sharedMaterial . name = ConvertToMayaCompatibleName ( renderer . sharedMaterial . name ) ;
978
+ foreach ( var mat in renderer . sharedMaterials ) {
979
+ mat . name = ConvertToMayaCompatibleName ( mat . name ) ;
980
+ }
910
981
}
911
982
912
983
// .material instantiates a new material, which is bad
913
984
// most of the time.
914
- return renderer . sharedMaterial ;
985
+ return renderer . sharedMaterials ;
915
986
}
916
987
}
917
988
0 commit comments