@@ -205,7 +205,35 @@ THREE.ThreeMFLoader.prototype = {
205205
206206 }
207207
208- function parseBasematerialsNode ( /* basematerialsNode */ ) {
208+ function parseBasematerialsNode ( basematerialsNode ) {
209+
210+ var basematerialsData = {
211+ id : basematerialsNode . getAttribute ( 'id' ) , // required
212+ basematerials : [ ]
213+ } ;
214+
215+ var basematerialNodes = basematerialsNode . querySelectorAll ( 'base' ) ;
216+
217+ for ( var i = 0 ; i < basematerialNodes . length ; i ++ ) {
218+
219+ var basematerialNode = basematerialNodes [ i ] ;
220+ var basematerialData = parseBasematerialNode ( basematerialNode ) ;
221+ basematerialsData . basematerials . push ( basematerialData ) ;
222+
223+ }
224+
225+ return basematerialsData ;
226+
227+ }
228+
229+ function parseBasematerialNode ( basematerialNode ) {
230+
231+ var basematerialData = { } ;
232+
233+ basematerialData [ 'name' ] = basematerialNode . getAttribute ( 'name' ) ; // required
234+ basematerialData [ 'displaycolor' ] = basematerialNode . getAttribute ( 'displaycolor' ) ; // required
235+
236+ return basematerialData ;
209237
210238 }
211239
@@ -437,7 +465,7 @@ THREE.ThreeMFLoader.prototype = {
437465
438466 if ( basematerialsNode ) {
439467
440- resourcesData [ 'basematerial ' ] = parseBasematerialsNode ( basematerialsNode ) ;
468+ resourcesData [ 'basematerials ' ] = parseBasematerialsNode ( basematerialsNode ) ;
441469
442470 }
443471
@@ -514,39 +542,171 @@ THREE.ThreeMFLoader.prototype = {
514542
515543 }
516544
517- function buildMesh ( meshData ) {
545+ function buildMesh ( meshData , objects , modelData , objectData ) {
546+
547+ // geometry
518548
519549 var geometry = new THREE . BufferGeometry ( ) ;
520550 geometry . setIndex ( new THREE . BufferAttribute ( meshData [ 'triangles' ] , 1 ) ) ;
521551 geometry . addAttribute ( 'position' , new THREE . BufferAttribute ( meshData [ 'vertices' ] , 3 ) ) ;
522552
523- if ( meshData [ 'colors' ] ) {
553+ // groups
554+
555+ var basematerialsData = modelData [ 'resources' ] [ 'basematerials' ] ;
556+ var triangleProperties = meshData [ 'triangleProperties' ] ;
557+
558+ var start = 0 ;
559+ var count = 0 ;
560+ var currentMaterialIndex = - 1 ;
561+
562+ for ( var i = 0 , l = triangleProperties . length ; i < l ; i ++ ) {
563+
564+ var triangleProperty = triangleProperties [ i ] ;
565+ var pid = triangleProperty . pid ;
566+
567+ // only proceed if the triangle refers to a basematerials definition
568+
569+ if ( basematerialsData && ( basematerialsData . id === pid ) ) {
570+
571+ if ( currentMaterialIndex === - 1 ) currentMaterialIndex = triangleProperty . p1 ;
572+
573+ if ( currentMaterialIndex === triangleProperty . p1 ) {
574+
575+ count += 3 ; // primitves per triangle
576+
577+ } else {
524578
525- geometry . addAttribute ( 'color' , new THREE . BufferAttribute ( meshData [ 'colors' ] , 3 ) ) ;
579+ geometry . addGroup ( start , count , currentMaterialIndex ) ;
580+
581+ start += count ;
582+ count = 3 ;
583+ currentMaterialIndex = triangleProperty . p1 ;
584+
585+ }
586+
587+ }
526588
527589 }
528590
591+ if ( geometry . groups . length > 0 ) mergeGroups ( geometry ) ;
592+
529593 geometry . computeBoundingSphere ( ) ;
530594
531- var materialOpts = {
532- flatShading : true
533- } ;
595+ // material
596+
597+ var material ;
598+
599+ if ( basematerialsData && ( basematerialsData . id === objectData . pid ) ) {
600+
601+ var materialIndex = objectData . pindex ;
602+ var basematerialData = basematerialsData . basematerials [ materialIndex ] ;
603+
604+ material = getBuild ( basematerialData , objects , modelData , objectData , buildBasematerial ) ;
605+
606+ } else if ( geometry . groups . length > 0 ) {
607+
608+ var groups = geometry . groups ;
609+ material = [ ] ;
534610
535- if ( meshData [ 'colors' ] && 0 < meshData [ 'colors' ] . length ) {
611+ for ( var i = 0 , l = groups . length ; i < l ; i ++ ) {
536612
537- materialOpts [ 'vertexColors' ] = THREE . VertexColors ;
613+ var group = groups [ i ] ;
614+ var basematerialData = basematerialsData . basematerials [ group . materialIndex ] ;
615+
616+ material . push ( getBuild ( basematerialData , objects , modelData , objectData , buildBasematerial ) ) ;
617+
618+ }
538619
539620 } else {
540621
541- materialOpts [ 'color' ] = 0xaaaaff ;
622+ // default material
623+
624+ material = new THREE . MeshPhongMaterial ( { color : 0xaaaaff , flatShading : true } ) ;
542625
543626 }
544627
545- var material = new THREE . MeshPhongMaterial ( materialOpts ) ;
546628 return new THREE . Mesh ( geometry , material ) ;
547629
548630 }
549631
632+ function mergeGroups ( geometry ) {
633+
634+ // sort by material index
635+
636+ var groups = geometry . groups . sort ( function ( a , b ) {
637+
638+ if ( a . materialIndex !== b . materialIndex ) return a . materialIndex - b . materialIndex ;
639+
640+ return a . start - b . start ;
641+
642+ } ) ;
643+
644+ // reorganize index buffer
645+
646+ var index = geometry . index ;
647+
648+ var itemSize = index . itemSize ;
649+ var srcArray = index . array ;
650+
651+ var targetOffset = 0 ;
652+
653+ var targetArray = new srcArray . constructor ( srcArray . length ) ;
654+
655+ for ( var i = 0 ; i < groups . length ; i ++ ) {
656+
657+ var group = groups [ i ] ;
658+
659+ var groupLength = group . count * itemSize ;
660+ var groupStart = group . start * itemSize ;
661+
662+ var sub = srcArray . subarray ( groupStart , groupStart + groupLength ) ;
663+
664+ targetArray . set ( sub , targetOffset ) ;
665+
666+ targetOffset += groupLength ;
667+
668+ }
669+
670+ srcArray . set ( targetArray ) ;
671+
672+ // update groups
673+
674+ var start = 0 ;
675+
676+ for ( i = 0 ; i < groups . length ; i ++ ) {
677+
678+ group = groups [ i ] ;
679+
680+ group . start = start ;
681+ start += group . count ;
682+
683+ }
684+
685+ // merge groups
686+
687+ var lastGroup = groups [ 0 ] ;
688+
689+ geometry . groups = [ lastGroup ] ;
690+
691+ for ( i = 1 ; i < groups . length ; i ++ ) {
692+
693+ group = groups [ i ] ;
694+
695+ if ( lastGroup . materialIndex === group . materialIndex ) {
696+
697+ lastGroup . count += group . count ;
698+
699+ } else {
700+
701+ lastGroup = group ;
702+ geometry . groups . push ( lastGroup ) ;
703+
704+ }
705+
706+ }
707+
708+ }
709+
550710 function applyExtensions ( extensions , meshData , modelXml ) {
551711
552712 if ( ! extensions ) {
@@ -585,16 +745,42 @@ THREE.ThreeMFLoader.prototype = {
585745
586746 }
587747
588- function getBuild ( data , objects , modelData , builder ) {
748+ function getBuild ( data , objects , modelData , objectData , builder ) {
589749
590750 if ( data . build !== undefined ) return data . build ;
591751
592- data . build = builder ( data , objects , modelData ) ;
752+ data . build = builder ( data , objects , modelData , objectData ) ;
593753
594754 return data . build ;
595755
596756 }
597757
758+ function buildBasematerial ( materialData ) {
759+
760+ var material = new THREE . MeshPhongMaterial ( { flatShading : true } ) ;
761+
762+ material . name = materialData . name ;
763+
764+ // displaycolor MUST be specified with a value of a 6 or 8 digit hexadecimal number, e.g. "#RRGGBB" or "#RRGGBBAA"
765+
766+ var displaycolor = materialData . displaycolor ;
767+
768+ var color = displaycolor . substring ( 0 , 7 ) ;
769+ material . color . setStyle ( color ) ;
770+ material . color . convertSRGBToLinear ( ) ; // displaycolor is in sRGB
771+
772+ // process alpha if set
773+
774+ if ( displaycolor . length === 9 ) {
775+
776+ material . opacity = parseInt ( displaycolor . charAt ( 7 ) + displaycolor . charAt ( 8 ) , 16 ) / 255 ;
777+
778+ }
779+
780+ return material ;
781+
782+ }
783+
598784 function buildComposite ( compositeData , objects , modelData ) {
599785
600786 var composite = new THREE . Group ( ) ;
@@ -634,22 +820,23 @@ THREE.ThreeMFLoader.prototype = {
634820 function buildObject ( objectId , objects , modelData ) {
635821
636822 var objectData = modelData [ 'resources' ] [ 'object' ] [ objectId ] ;
637- var meshData = objectData [ 'mesh' ] ;
638823
639- if ( meshData ) {
824+ if ( objectData [ 'mesh' ] ) {
825+
826+ var meshData = objectData [ 'mesh' ] ;
640827
641828 var extensions = modelData [ 'extensions' ] ;
642829 var modelXml = modelData [ 'xml' ] ;
643830
644831 applyExtensions ( extensions , meshData , modelXml ) ;
645832
646- objects [ objectData . id ] = getBuild ( meshData , objects , modelData , buildMesh ) ;
833+ objects [ objectData . id ] = getBuild ( meshData , objects , modelData , objectData , buildMesh ) ;
647834
648835 } else {
649836
650837 var compositeData = objectData [ 'components' ] ;
651838
652- objects [ objectData . id ] = getBuild ( compositeData , objects , modelData , buildComposite ) ;
839+ objects [ objectData . id ] = getBuild ( compositeData , objects , modelData , objectData , buildComposite ) ;
653840
654841 }
655842
0 commit comments