ThreeJSExporter_MorphTargets_v0.ms 22 KB

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