source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/utils/exporters/max/ThreeJSExporter.ms@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 17.8 KB
Line 
1-------------------------------------------------------------------------------------
2-- ThreeJSExporter.ms
3-- Exports geometry from 3ds max to Three.js models in ASCII JSON format v3
4-- By alteredq / http://alteredqualia.com
5-------------------------------------------------------------------------------------
6
7rollout ThreeJSExporter "ThreeJSExporter"
8(
9 -- Variables
10
11 local ostream,
12
13 headerFormat = "\"metadata\":
14{
15\"sourceFile\": \"%\",
16\"generatedBy\": \"3ds max ThreeJSExporter\",
17\"formatVersion\": 3.1,
18\"vertices\": %,
19\"normals\": %,
20\"colors\": %,
21\"uvs\": %,
22\"triangles\": %,
23\"materials\": %
24},
25
26",
27
28 vertexFormat = "%,%,%",
29
30 vertexNormalFormat = "%,%,%",
31 UVFormat = "%,%",
32
33 triFormat = "%,%,%,%",
34 triUVFormat = "%,%,%,%,%,%,%",
35 triNFormat = "%,%,%,%,%,%,%",
36 triUVNFormat = "%,%,%,%,%,%,%,%,%,%",
37
38 footerFormat = "}"
39
40 -------------------------------------------------------------------------------------
41 -- User interface
42
43
44 group "ThreeJSExporter v0.8"
45 (
46
47 label msg "Exports selected meshes in Three.js ascii JSON format" align:#left
48 hyperLink lab1 "Original source at GitHub" address:"https://github.com/alteredq/three.js/blob/master/utils/exporters/max/ThreeJSExporter.ms" color:(color 255 120 0) align:#left
49
50 label dummy1 "--------------------------------------------------------" align:#left
51
52 checkbox exportColor "Export vertex colors" checked:false enabled:true
53 checkbox exportUv "Export uvs" checked:true enabled:true
54 checkbox exportNormal "Export normals" checked:true enabled:true
55 checkbox smoothNormal "Use vertex normals" checked:false enabled:true
56
57 label dummy2 "--------------------------------------------------------" align:#left
58
59 checkbox flipYZ "Flip YZ" checked:true enabled:true
60 checkbox flipUV "Flip UV" checked:false enabled:true
61 checkbox flipFace "Flip all faces" checked:false enabled:true
62 checkbox autoflipFace "Try fixing flipped faces" checked:false enabled:true
63
64 label dummy3 "--------------------------------------------------------" align:#left
65
66 button btn_export "Export selected objects"
67
68 )
69
70
71 -------------------------------------------------------------------------------------
72 -- Dump vertices
73
74 function DumpVertices src =
75 (
76
77 Format "\"vertices\": [" to:ostream
78
79 num = src.count
80
81 if num > 0 then
82 (
83
84 for i = 1 to num do
85 (
86
87 vert = src[i]
88
89 if flipYZ.checked then
90 (
91 x = vert.x
92 y = vert.z
93 z = vert.y
94
95 z *= -1
96
97 )
98 else
99 (
100
101 x = vert.x
102 y = vert.y
103 z = vert.z
104
105 )
106
107 Format vertexFormat x y z to:ostream
108
109 if i < num then Format "," to:ostream
110
111 )
112
113 )
114
115 Format "],\n\n" to:ostream
116
117 )
118
119 -------------------------------------------------------------------------------------
120 -- Dump colors
121
122 function DumpColors src useColors =
123 (
124
125 Format "\"colors\": [" to:ostream
126
127 num = src.count
128
129 if num > 0 and useColors then
130 (
131
132 for i = 1 to num do
133 (
134
135 col = src[i]
136
137 r = col.r as Integer
138 g = col.g as Integer
139 b = col.b as Integer
140
141 hexNum = ( bit.shift r 16 ) + ( bit.shift g 8 ) + b
142
143 -- hexColor = formattedPrint hexNum format:"#x"
144 -- Format "%" hexColor to:ostream
145
146 decColor = formattedPrint hexNum format:"#d"
147 Format "%" decColor to:ostream
148
149 if i < num then Format "," to:ostream
150
151 )
152
153 )
154
155 Format "],\n\n" to:ostream
156
157 )
158
159 -------------------------------------------------------------------------------------
160 -- Dump normals
161
162 function DumpNormals src =
163 (
164
165 Format "\"normals\": [" to:ostream
166
167 num = src.count
168
169 if num > 0 and exportNormal.checked then
170 (
171
172 for i = 1 to num do
173 (
174
175 normal = src[i]
176 normal = normalize normal as point3
177
178 if flipYZ.checked then
179 (
180
181 x = normal.x
182 y = normal.z
183 z = normal.y
184
185 z *= -1
186
187 )
188 else
189 (
190
191 x = normal.x
192 y = normal.y
193 z = normal.z
194
195 )
196
197 Format vertexNormalFormat x y z to:ostream
198
199 if i < num then Format "," to:ostream
200
201 )
202
203 )
204
205 Format "],\n\n" to:ostream
206
207 )
208
209 -------------------------------------------------------------------------------------
210 -- Dump uvs
211
212 function DumpUvs src =
213 (
214
215 Format "\"uvs\": [[" to:ostream
216
217 num = src.count
218
219 if num > 0 and exportUv.checked then
220 (
221
222 for i = 1 to num do
223 (
224
225 uvw = src[i]
226
227 u = uvw.x
228
229 if flipUV.checked then
230 (
231 v = 1 - uvw.y
232 )
233 else
234 (
235 v = uvw.y
236 )
237
238 Format UVFormat u v to:ostream
239
240 if i < num then Format "," to:ostream
241
242 )
243
244 )
245
246 Format "]],\n\n" to:ostream
247
248 )
249
250 -------------------------------------------------------------------------------------
251 -- Dump faces
252
253 function DumpFaces src useColors =
254 (
255
256 Format "\"faces\": [" to:ostream
257
258 num = src.count
259
260 if num > 0 then
261 (
262
263 for i = 1 to num do
264 (
265
266 zface = src[i]
267
268 fv = zface[1]
269 fuv = zface[2]
270 m = zface[3] - 1
271 fc = zface[4]
272
273 needsFlip = zface[5]
274
275 isTriangle = true
276 hasMaterial = true
277 hasFaceUvs = false
278 hasFaceVertexUvs = ((classof fuv == Point3) and exportUv.checked)
279 hasFaceNormals = false
280 hasFaceVertexNormals = (exportNormal.checked)
281 hasFaceColors = false
282 hasFaceVertexColors = ((classof fc == Point3) and useColors)
283
284 faceType = 0
285 faceType = bit.set faceType 1 (not isTriangle)
286 faceType = bit.set faceType 2 hasMaterial
287 faceType = bit.set faceType 3 hasFaceUvs
288 faceType = bit.set faceType 4 hasFaceVertexUvs
289 faceType = bit.set faceType 5 hasFaceNormals
290 faceType = bit.set faceType 6 hasFaceVertexNormals
291 faceType = bit.set faceType 7 hasFaceColors
292 faceType = bit.set faceType 8 hasFaceVertexColors
293
294 if i > 1 then
295 (
296 Format "," faceType to:ostream
297 )
298
299 Format "%" faceType to:ostream
300
301 if isTriangle then
302 (
303
304 va = (fv.x - 1) as Integer
305 vb = (fv.y - 1) as Integer
306 vc = (fv.z - 1) as Integer
307
308 if flipFace.checked or needsFlip then
309 (
310
311 tmp = vb
312 vb = vc
313 vc = tmp
314
315 )
316
317
318 Format ",%,%,%" va vb vc to:ostream
319
320
321 if hasMaterial then
322 (
323
324 Format ",%" m to:ostream
325
326 )
327
328 if hasFaceVertexUvs then
329 (
330
331 ua = (fuv.x - 1) as Integer
332 ub = (fuv.y - 1) as Integer
333 uc = (fuv.z - 1) as Integer
334
335 if flipFace.checked or needsFlip then
336 (
337
338 tmp = ub
339 ub = uc
340 uc = tmp
341
342 )
343
344 Format ",%,%,%" ua ub uc to:ostream
345
346 )
347
348 if hasFaceVertexNormals then
349 (
350
351 if smoothNormal.checked then
352 (
353
354 -- normals have the same indices as vertices
355
356 na = va
357 nb = vb
358 nc = vc
359
360 )
361 else
362 (
363 -- normals have the same indices as face
364
365 na = i - 1
366 nb = na
367 nc = na
368
369 )
370
371 if flipFace.checked or needsFlip then
372 (
373
374 tmp = nb
375 nb = nc
376 nc = tmp
377
378 )
379
380 Format ",%,%,%" na nb nc to:ostream
381
382 )
383
384
385 if hasFaceVertexColors then
386 (
387
388 ca = (fc.x - 1) as Integer
389 cb = (fc.y - 1) as Integer
390 cc = (fc.z - 1) as Integer
391
392 if flipFace.checked or needsFlip then
393 (
394
395 tmp = cb
396 cb = cc
397 cc = tmp
398
399 )
400
401 Format ",%,%,%" ca cb cc to:ostream
402
403 )
404
405 )
406
407 )
408
409 )
410
411 Format "]\n\n" to:ostream
412
413 )
414
415 -------------------------------------------------------------------------------------
416 -- Dump color
417
418 function DumpColor pcolor label =
419 (
420 r = pcolor.r / 255
421 g = pcolor.g / 255
422 b = pcolor.b / 255
423
424 fr = formattedPrint r format:".4f"
425 fg = formattedPrint g format:".4f"
426 fb = formattedPrint b format:".4f"
427
428 Format "\"%\" : [%, %, %],\n" label fr fg fb to:ostream
429
430 )
431
432 -------------------------------------------------------------------------------------
433 -- Dump map
434
435 function DumpMap pmap label =
436 (
437
438 if classof pmap == BitmapTexture then
439 (
440 bm = pmap.bitmap
441
442 if bm != undefined then
443 (
444
445 fname = filenameFromPath bm.filename
446 Format "\"%\" : \"%\",\n" label fname to:ostream
447
448 )
449
450 )
451
452 )
453
454 -------------------------------------------------------------------------------------
455 -- Export materials
456
457 function ExportMaterials zmaterials zcolors =
458 (
459
460 Format "\"materials\": [\n" to:ostream
461
462 totalMaterials = zmaterials.count
463
464 for i = 1 to totalMaterials do
465 (
466 mat = zmaterials[i]
467
468 Format "{\n" to:ostream
469
470 -- debug
471
472 Format "\"DbgIndex\" : %,\n" (i-1) to:ostream
473
474 if classof mat != BooleanClass then
475 (
476
477 useVertexColors = zcolors[i]
478
479 Format "\"DbgName\" : \"%\",\n" mat.name to:ostream
480
481 -- colors
482
483 DumpColor mat.diffuse "colorDiffuse"
484 DumpColor mat.ambient "colorAmbient"
485 DumpColor mat.specular "colorSpecular"
486
487 t = mat.opacity / 100
488 s = mat.glossiness
489
490 Format "\"transparency\" : %,\n" t to:ostream
491 Format "\"specularCoef\" : %,\n" s to:ostream
492
493 -- maps
494
495 DumpMap mat.diffuseMap "mapDiffuse"
496 DumpMap mat.ambientMap "mapAmbient"
497 DumpMap mat.specularMap "mapSpecular"
498 DumpMap mat.bumpMap "mapBump"
499 DumpMap mat.opacityMap "mapAlpha"
500
501 )
502 else
503 (
504
505 useVertexColors = false
506
507 Format "\"DbgName\" : \"%\",\n" "dummy" to:ostream
508
509 DumpColor red "colorDiffuse"
510
511 )
512
513 Format "\"vertexColors\" : %\n" useVertexColors to:ostream
514 Format "}" to:ostream
515
516 if ( i < totalMaterials ) then Format "," to:ostream
517 Format "\n\n" to:ostream
518
519 )
520
521 Format "],\n\n" to:ostream
522
523 )
524
525 -------------------------------------------------------------------------------------
526 -- Extract vertices from mesh
527
528 function ExtractVertices obj whereto =
529 (
530
531 n = obj.numVerts
532
533 for i = 1 to n do
534 (
535
536 v = GetVert obj i
537 append whereto v
538
539 )
540
541 )
542
543 -------------------------------------------------------------------------------------
544 -- Extract vertex colors from mesh
545
546 function ExtractColors obj whereto =
547 (
548
549 nColors = GetNumCPVVerts obj
550
551 if nColors > 0 then
552 (
553
554 for i = 1 to nColors do
555 (
556
557 c = GetVertColor obj i
558 append whereto c
559
560 )
561
562 )
563
564 )
565
566
567 -------------------------------------------------------------------------------------
568 -- Extract normals from mesh
569
570 function ExtractNormals obj whereto needsFlip =
571 (
572
573 if smoothNormal.checked then
574 (
575
576 num = obj.numVerts
577
578 for i = 1 to num do
579 (
580
581 n = GetNormal obj i
582
583 if flipFace.checked or needsFlip then
584 (
585 n.x *= -1
586 n.y *= -1
587 n.z *= -1
588 )
589
590 append whereto n
591
592 )
593
594 )
595 else
596 (
597
598 num = obj.numFaces
599
600 for i = 1 to num do
601 (
602
603 n = GetFaceNormal obj i
604
605 if flipFace.checked or needsFlip then
606 (
607 n.x *= -1
608 n.y *= -1
609 n.z *= -1
610 )
611
612 append whereto n
613
614 )
615
616 )
617
618 )
619
620 -------------------------------------------------------------------------------------
621 -- Extract uvs from mesh
622
623 function ExtractUvs obj whereto =
624 (
625 n = obj.numTVerts
626
627 for i = 1 to n do
628 (
629
630 v = GetTVert obj i
631 append whereto v
632
633 )
634
635 )
636
637 -------------------------------------------------------------------------------------
638 -- Extract faces from mesh
639
640 function ExtractFaces objMesh objMaterial whereto allMaterials needsFlip hasVColors offsetVert offsetUv offsetColor =
641 (
642 n = objMesh.numFaces
643 hasUVs = objMesh.numTVerts > 0
644
645 useMultiMaterial = false
646 materialIDList = #()
647
648 materialClass = classof objMaterial
649
650 if materialClass == StandardMaterial then
651 (
652
653 fm = findItem allMaterials objMaterial
654
655 )
656 else if materialClass == MultiMaterial then
657 (
658
659 useMultiMaterial = true
660
661 for i = 1 to n do
662 (
663
664 mID = GetFaceMatID objMesh i
665 materialIndex = findItem objMaterial.materialIDList mID
666
667 if materialIndex > 0 then
668 (
669
670 subMaterial = objMaterial.materialList[materialIndex]
671
672 mMergedIndex = findItem allMaterials subMaterial
673
674 if mMergedIndex > 0 then
675 (
676
677 materialIDList[mID] = mMergedIndex
678
679 )
680 else
681 (
682
683 materialIDList[mID] = findItem allMaterials false
684
685 )
686
687 )
688 else
689 (
690
691 materialIDList[mID] = findItem allMaterials false
692
693 )
694
695 )
696
697 )
698 else
699 (
700
701 -- undefined material
702
703 fm = findItem allMaterials false
704
705 )
706
707 for i = 1 to n do
708 (
709
710 zface = #()
711
712 fv = GetFace objMesh i
713
714 fv.x += offsetVert
715 fv.y += offsetVert
716 fv.z += offsetVert
717
718 if useMultiMaterial then
719 (
720
721 mID = GetFaceMatID objMesh i
722 fm = materialIDList[mID]
723
724 )
725
726 if hasUVs then
727 (
728
729 fuv = GetTVFace objMesh i
730
731 fuv.x += offsetUv
732 fuv.y += offsetUv
733 fuv.z += offsetUv
734
735 )
736 else
737 (
738
739 fuv = false
740
741 )
742
743 if hasVColors then
744 (
745
746 fc = GetVCFace objMesh i
747
748 fc.x += offsetColor
749 fc.y += offsetColor
750 fc.z += offsetColor
751
752 )
753 else
754 (
755
756 fc = false
757
758 )
759
760 append zface fv
761 append zface fuv
762 append zface fm
763 append zface fc
764 append zface needsFlip
765
766 append whereto zface
767
768 )
769
770 )
771
772 -------------------------------------------------------------------------------------
773 -- Extract materials from eventual multi-material
774
775 function ExtractMaterials objMesh objMaterial whereto wheretoColors zname hasVColors =
776 (
777
778 materialClass = classof objMaterial
779
780 if materialClass == StandardMaterial then
781 (
782
783 if ( findItem whereto objMaterial ) == 0 then
784 (
785
786 append whereto objMaterial
787 append wheretoColors hasVColors
788
789 )
790
791 )
792 else if materialClass == MultiMaterial then
793 (
794
795 n = objMesh.numFaces
796
797 for i = 1 to n do
798 (
799
800 mID = getFaceMatId objMesh i
801 materialIndex = findItem objMaterial.materialIDList mID
802
803 if materialIndex > 0 then
804 (
805
806 subMaterial = objMaterial.materialList[materialIndex]
807
808 if ( findItem whereto subMaterial ) == 0 then
809 (
810
811 append whereto subMaterial
812 append wheretoColors hasVColors
813
814 )
815
816 )
817
818 )
819
820 )
821 else
822 (
823
824 -- unknown or undefined material
825
826 append whereto false
827 append wheretoColors false
828
829 )
830
831 )
832
833 -------------------------------------------------------------------------------------
834 -- Hack to figure out if normals are messed up
835
836 function NeedsFaceFlip node =
837 (
838 needsFlip = false
839
840 local tmp = Snapshot node
841
842 face_normal = normalize ( getfacenormal tmp 1 )
843
844 face = getface tmp 1
845
846 va = getvert tmp face[1]
847 vb = getvert tmp face[2]
848 vc = getvert tmp face[3]
849
850 computed_normal = normalize ( cross (vc - vb) (va - vb) )
851
852 if distance computed_normal face_normal > 0.1 then needsFlip = true
853
854 delete tmp
855
856 return needsFlip
857 )
858
859 -------------------------------------------------------------------------------------
860 -- Extract only things that either already are or can be converted to meshes
861
862 function ExtractMesh node =
863 (
864
865 if SuperClassOf node == GeometryClass then
866 (
867 needsFlip = false
868 hasVColors = false
869
870 zmesh = SnapshotAsMesh node
871
872 if autoflipFace.checked then
873 (
874
875 needsFlip = NeedsFaceFlip node
876
877 )
878
879 if exportColor.checked and ( getNumCPVVerts zmesh ) > 0 then
880 (
881
882 hasVColors = true
883
884 )
885
886 return #( zmesh, node.name, node.material, needsFlip, hasVColors )
887
888 )
889
890 -- Not geometry ... could be a camera, light, etc.
891
892 return #( false, node.name, 0, false, false )
893
894 )
895
896 -------------------------------------------------------------------------------------
897 -- Export scene
898
899 function ExportScene =
900 (
901
902 -- Extract meshes
903
904 meshObjects = #()
905
906 mergedVertices = #()
907 mergedNormals = #()
908 mergedColors = #()
909
910 mergedUvs = #()
911 mergedFaces = #()
912
913 mergedMaterials = #()
914 mergedMaterialsColors = #()
915
916 sceneHasVColors = false
917
918 for obj in selection do
919 (
920
921 result = ExtractMesh obj
922 meshObj = result[1]
923
924 if ClassOf meshObj == TriMesh then
925 (
926
927 meshName = result[2]
928 meshMaterial = result[3]
929 needsFlip = result[4]
930 hasVColors = result[5]
931
932 sceneHasVColors = sceneHasVColors or hasVColors
933
934 append meshObjects result
935
936 vertexOffset = mergedVertices.count
937 uvOffset = mergedUvs.count
938 colorOffset = mergedColors.count
939
940 ExtractMaterials meshObj meshMaterial mergedMaterials mergedMaterialsColors meshName hasVColors
941
942 ExtractVertices meshObj mergedVertices
943 ExtractNormals meshObj mergedNormals needsFlip
944 ExtractColors meshObj mergedColors
945
946 ExtractUvs meshObj mergedUvs
947
948 ExtractFaces meshObj meshMaterial mergedFaces mergedMaterials needsFlip hasVColors vertexOffset uvOffset colorOffset
949
950 )
951
952 )
953
954 totalVertices = mergedVertices.count
955 totalFaces = mergedFaces.count
956 totalMaterials = mergedMaterials.count
957
958 totalColors = 0
959 totalNormals = 0
960 totalUvs = 0
961
962 useColors = false
963
964 if sceneHasVColors and exportColor.checked then
965 (
966
967 totalColors = mergedColors.count
968 useColors = true
969
970 )
971
972 if exportNormal.checked then
973 (
974
975 totalNormals = mergedNormals.count
976
977 )
978
979 if exportUv.checked then
980 (
981
982 totalUvs = mergedUvs.count
983
984 )
985
986
987 -- Dump objects (debug)
988
989 -- Format "// Source objects:\n\n" to:ostream
990
991 -- i = 0
992
993 -- for obj in meshObjects do
994 -- (
995
996 -- meshName = obj[2]
997 -- Format "// %: %\n" i meshName to:ostream
998 -- i += 1
999
1000 -- )
1001
1002 -- Dump model
1003
1004 Format "{\n\n" to:ostream
1005
1006 -- Dump header
1007
1008 Format headerFormat maxFileName totalVertices totalNormals totalColors totalUvs totalFaces totalMaterials to:ostream
1009
1010 -- Dump all materials in the scene
1011
1012 ExportMaterials mergedMaterials mergedMaterialsColors
1013
1014 -- Dump merged data from all selected geometries
1015
1016 DumpVertices mergedVertices
1017 DumpNormals mergedNormals
1018 DumpColors mergedColors useColors
1019 DumpUvs mergedUvs
1020 DumpFaces mergedFaces useColors
1021
1022 -- Dump footer
1023
1024 Format footerFormat to:ostream
1025
1026 )
1027
1028
1029 -------------------------------------------------------------------------------------
1030 -- Open and prepare a file handle for writing
1031
1032 function GetSaveFileStream =
1033 (
1034 zname = getFilenameFile maxFileName
1035 zname += ".js"
1036
1037 fname = GetSaveFileName filename:zname types:"JavaScript file (*.js)|*.js|All Files(*.*)|*.*|"
1038 if fname == undefined then
1039 (
1040
1041 return undefined
1042
1043 )
1044
1045 ostream = CreateFile fname
1046 if ostream == undefined then
1047 (
1048
1049 MessageBox "Couldn't open file for writing !"
1050 return undefined
1051
1052 )
1053
1054 return ostream
1055 )
1056
1057 -------------------------------------------------------------------------------------
1058 -- Export button click handler
1059
1060 on btn_export pressed do
1061 (
1062 ostream = GetSaveFileStream()
1063 if ostream != undefined then
1064 (
1065
1066 ExportScene()
1067 close ostream
1068
1069 )
1070
1071 )
1072
1073)
1074createDialog ThreeJSExporter width:300
Note: See TracBrowser for help on using the repository browser.