ThreeJSExporter_MorphTargets_v0.ms 22 KB

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