|
@@ -0,0 +1,1097 @@
|
|
|
+-------------------------------------------------------------------------------------
|
|
|
+-- ThreeJSExporter.ms
|
|
|
+-- Exports geometry from 3ds max to Three.js models in ASCII JSON format v3
|
|
|
+-- By alteredq / http://alteredqualia.com
|
|
|
+--
|
|
|
+-- 2014.06.25
|
|
|
+-- Add vertex export from each frame
|
|
|
+-------------------------------------------------------------------------------------
|
|
|
+function eav_attime obj t =
|
|
|
+(
|
|
|
+ local i
|
|
|
+ local s_out = ""
|
|
|
+ s_out = s_out as stringstream
|
|
|
+
|
|
|
+ local zmesh = at time t (SnapshotAsMesh obj)
|
|
|
+ local n = zmesh.numverts
|
|
|
+
|
|
|
+ local vrs_ar = #()
|
|
|
+ local v = [0,0,0]
|
|
|
+
|
|
|
+ for i = 1 to n do
|
|
|
+ (
|
|
|
+ v = (GetVert zmesh i)
|
|
|
+ append vrs_ar v
|
|
|
+ )
|
|
|
+
|
|
|
+ for i = 1 to vrs_ar.count do
|
|
|
+ (
|
|
|
+ v = vrs_ar[i]
|
|
|
+ format "%, %, %" v.x v.z -v.y to:s_out
|
|
|
+
|
|
|
+ if i < vrs_ar.count then
|
|
|
+ (
|
|
|
+ format ", " to:s_out
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ return (s_out as string)
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+TODO 2014.06.25
|
|
|
+Export animation from modifiers
|
|
|
+*/
|
|
|
+function eav_get_range_from_trans_con obj &i_t1 &i_t2 =
|
|
|
+(
|
|
|
+-- Get keys range from Pos, rotation, scale controllers
|
|
|
+ local i
|
|
|
+ local con
|
|
|
+ local t1min = 0, t2max = 0
|
|
|
+
|
|
|
+ for i = 1 to 3 do
|
|
|
+ (
|
|
|
+ con = obj.controller[i]
|
|
|
+
|
|
|
+ format "\nController: %" obj.controller[i].name
|
|
|
+ format " (keys count: %)" con.keys.count
|
|
|
+
|
|
|
+ if con.keys.count == 0 then
|
|
|
+ (
|
|
|
+ continue
|
|
|
+ )
|
|
|
+
|
|
|
+ t1 = con.keys[1].time.frame as integer
|
|
|
+ t2 = (con.keys[con.keys.count].time.frame) as integer
|
|
|
+
|
|
|
+ if i == 1 then
|
|
|
+ (
|
|
|
+ t1min = t1
|
|
|
+ t2max = t2
|
|
|
+ )
|
|
|
+
|
|
|
+ if t1 < t1min then
|
|
|
+ (
|
|
|
+ t1min = t1
|
|
|
+ )
|
|
|
+
|
|
|
+ if t2 > t2max then
|
|
|
+ (
|
|
|
+ t2max = t2
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ i_t1 = t1min
|
|
|
+ i_t2 = t2max
|
|
|
+
|
|
|
+ if( i_t1 == 0 )and( i_t2 == 0 )then
|
|
|
+ (
|
|
|
+ return(false)
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ return(true)
|
|
|
+ )
|
|
|
+)
|
|
|
+
|
|
|
+function eav_get_range_from_mods_con obj &i_t1 &i_t2 =
|
|
|
+(
|
|
|
+ local i
|
|
|
+ local cmod, mod_con
|
|
|
+ local props, pr
|
|
|
+ local t1min = 0, t2max = 0
|
|
|
+
|
|
|
+-- format "\n\nModifiers:\n"
|
|
|
+
|
|
|
+ for i = 1 to obj.modifiers.count do
|
|
|
+ (
|
|
|
+ cmod = obj.modifiers[i]
|
|
|
+
|
|
|
+ -- format "\n%: \"%\" (%)\n" i (cmod.name) (classof cmod)
|
|
|
+
|
|
|
+ props = getpropnames cmod
|
|
|
+
|
|
|
+ for pr in props do
|
|
|
+ (
|
|
|
+ mod_con = (getPropertyController cmod pr)
|
|
|
+
|
|
|
+ if mod_con == undefined then
|
|
|
+ (
|
|
|
+ continue
|
|
|
+ )
|
|
|
+
|
|
|
+ if mod_con.keys.count <= 0 then
|
|
|
+ (
|
|
|
+ continue
|
|
|
+ )
|
|
|
+
|
|
|
+ -- format "\t%\t(keys: %)\n" pr (mod_con.keys.count)
|
|
|
+
|
|
|
+ t1 = mod_con.keys[1].time.frame as integer
|
|
|
+ t2 = (mod_con.keys[mod_con.keys.count].time.frame) as integer
|
|
|
+
|
|
|
+ if i == 1 then
|
|
|
+ (
|
|
|
+ t1min = t1
|
|
|
+ t2max = t2
|
|
|
+ )
|
|
|
+
|
|
|
+ if t1 < t1min then
|
|
|
+ (
|
|
|
+ t1min = t1
|
|
|
+ )
|
|
|
+
|
|
|
+ if t2 > t2max then
|
|
|
+ (
|
|
|
+ t2max = t2
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ i_t1 = t1min
|
|
|
+ i_t2 = t2max
|
|
|
+
|
|
|
+ if( i_t1 == 0 )and( i_t2 == 0 )then
|
|
|
+ (
|
|
|
+ return(false)
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ return(true)
|
|
|
+ )
|
|
|
+
|
|
|
+)
|
|
|
+
|
|
|
+function eav_exp_obj obj ostream =
|
|
|
+(
|
|
|
+ local i, t1, t2, t1_m, t2_m
|
|
|
+ local b_ran_set = false
|
|
|
+ local b_ran_mod_set = false
|
|
|
+ format "\n\n-----------------------------\nObject: \"%\"\n" obj.name
|
|
|
+
|
|
|
+ -- Total range:
|
|
|
+/* local frames_num = animationRange.end.frame - animationRange.start.frame
|
|
|
+ frames_num = frames_num as integer
|
|
|
+*/
|
|
|
+
|
|
|
+ -- Range detection between keys:
|
|
|
+ b_ran_set = eav_get_range_from_trans_con obj &t1 &t2
|
|
|
+ b_ran_mod_set = eav_get_range_from_mods_con obj &t1_m &t2_m
|
|
|
+
|
|
|
+ format "\n\nKey ranges detected:\n"
|
|
|
+ format " transform: (% to %) - %\n" t1 t2 b_ran_set
|
|
|
+ format " modifiers: (% to %) - %\n" t1_m t2_m b_ran_mod_set
|
|
|
+
|
|
|
+ if b_ran_set and b_ran_mod_set then
|
|
|
+ (
|
|
|
+ -- format "\nAll ranges set - compare\n"
|
|
|
+ -- Set smallest first key, and latest final key
|
|
|
+ if t1_m < t1 then
|
|
|
+ (
|
|
|
+ t1 = t1_m
|
|
|
+ )
|
|
|
+
|
|
|
+ if t2_m > t2 then
|
|
|
+ (
|
|
|
+ t2 = t2_m
|
|
|
+ )
|
|
|
+ )
|
|
|
+ else if( not b_ran_set )and( b_ran_mod_set )then
|
|
|
+ (
|
|
|
+ -- format "\nTrans range not set\n"
|
|
|
+ t1 = t1_m
|
|
|
+ t2 = t2_m
|
|
|
+ )
|
|
|
+ else if( not b_ran_mod_set )and( b_ran_set )then
|
|
|
+ (
|
|
|
+ -- format "\nmods range not set\n"
|
|
|
+ -- all values t1, t2 - save in initial state
|
|
|
+ )
|
|
|
+ else if( not b_ran_set )and( not b_ran_mod_set )then
|
|
|
+ (
|
|
|
+ format "\n No key range set. Exit function\n"
|
|
|
+ return(false)
|
|
|
+ )
|
|
|
+
|
|
|
+ format "\n final range for export: (% to %)\n" t1 t2
|
|
|
+
|
|
|
+ ---- Output
|
|
|
+ format "\n\"morphTargets\": [" to:ostream
|
|
|
+
|
|
|
+ for i = t1 to t2 do
|
|
|
+ (
|
|
|
+ format "\n{\"name\": \"FRAME000\", \"vertices\": [" to:ostream
|
|
|
+ format "%]}" (eav_attime obj i) to:ostream
|
|
|
+
|
|
|
+ if i < t2 then
|
|
|
+ (
|
|
|
+ format "," to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ format " ],\n\n" to:ostream
|
|
|
+
|
|
|
+ format "\n\n\"morphColors\": [],\n\n\n" to:ostream
|
|
|
+)
|
|
|
+
|
|
|
+function exp_anim_verts_sel ostream =
|
|
|
+(
|
|
|
+ Clearlistener()
|
|
|
+ format "\n---- Export verts:\n"
|
|
|
+
|
|
|
+ for obj in selection do
|
|
|
+ (
|
|
|
+ if superclassof obj != geometryclass then continue
|
|
|
+ eav_exp_obj obj ostream
|
|
|
+ )
|
|
|
+ format "\n----\n"
|
|
|
+)
|
|
|
+----
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+--------------------------------------------------------------------------------
|
|
|
+--------------------------------------------------------------------------------
|
|
|
+rollout ThreeJSExporter "ThreeJSExporter"
|
|
|
+(
|
|
|
+ -- Variables
|
|
|
+
|
|
|
+ local ostream,
|
|
|
+ headerFormat = "\"metadata\":{\"sourceFile\": \"%\",\"generatedBy\": \"3ds max ThreeJSExporter\",\"formatVersion\": 3.1,\"vertices\": %,\"normals\": %,\"colors\": %,\"uvs\": %,\"triangles\": %,\"materials\": %},",
|
|
|
+
|
|
|
+ vertexFormat = "%,%,%",
|
|
|
+
|
|
|
+ vertexNormalFormat = "%,%,%",
|
|
|
+ UVFormat = "%,%",
|
|
|
+
|
|
|
+ triFormat = "%,%,%,%",
|
|
|
+ triUVFormat = "%,%,%,%,%,%,%",
|
|
|
+ triNFormat = "%,%,%,%,%,%,%",
|
|
|
+ triUVNFormat = "%,%,%,%,%,%,%,%,%,%",
|
|
|
+
|
|
|
+ footerFormat = "}"
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- User interface
|
|
|
+
|
|
|
+ group "ThreeJSExporter v0.8"
|
|
|
+ (
|
|
|
+ label msg "Exports selected meshes in Three.js ascii JSON format" align:#left
|
|
|
+ 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
|
|
|
+
|
|
|
+ label dummy1 "--------------------------------------------------------" align:#left
|
|
|
+
|
|
|
+ checkbox exportColor "Export vertex colors" checked:false enabled:true
|
|
|
+ checkbox exportUv "Export uvs" checked:true enabled:true
|
|
|
+ checkbox exportNormal "Export normals" checked:true enabled:true
|
|
|
+ checkbox smoothNormal "Use vertex normals" checked:false enabled:true
|
|
|
+
|
|
|
+ label dummy2 "--------------------------------------------------------" align:#left
|
|
|
+
|
|
|
+ checkbox flipYZ "Flip YZ" checked:true enabled:true
|
|
|
+ checkbox flipUV "Flip UV" checked:false enabled:true
|
|
|
+ checkbox flipFace "Flip all faces" checked:false enabled:true
|
|
|
+ checkbox autoflipFace "Try fixing flipped faces" checked:false enabled:true
|
|
|
+
|
|
|
+ label dummy3 "--------------------------------------------------------" align:#left
|
|
|
+
|
|
|
+ checkbox cb_exp_mt "Export Morph Targets" checked:true enabled:true
|
|
|
+
|
|
|
+ label dummy4 "--------------------------------------------------------" align:#left
|
|
|
+ button btn_export "Export selected objects"
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump vertices
|
|
|
+ function DumpVertices src =
|
|
|
+ (
|
|
|
+ Format "\"vertices\": [" to:ostream
|
|
|
+ num = src.count
|
|
|
+
|
|
|
+ if num > 0 then
|
|
|
+ (
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ vert = src[i]
|
|
|
+
|
|
|
+ if flipYZ.checked then
|
|
|
+ (
|
|
|
+ x = vert.x
|
|
|
+ y = vert.z
|
|
|
+ z = vert.y
|
|
|
+
|
|
|
+ z *= -1
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ x = vert.x
|
|
|
+ y = vert.y
|
|
|
+ z = vert.z
|
|
|
+ )
|
|
|
+
|
|
|
+ Format vertexFormat x y z to:ostream
|
|
|
+ if i < num then Format "," to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ Format "],\n\n" to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ ---- 2014.06.25 16:15
|
|
|
+ function dump_morph_targets =
|
|
|
+ (
|
|
|
+ Clearlistener()
|
|
|
+ format "\n---- dump_morph_targets():\n"
|
|
|
+
|
|
|
+ if not cb_exp_mt.state then
|
|
|
+ (
|
|
|
+ format "\nNot checked\n"
|
|
|
+ return()
|
|
|
+ )
|
|
|
+
|
|
|
+ exp_anim_verts_sel ostream
|
|
|
+
|
|
|
+ format "\n----\n"
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump colors
|
|
|
+ function DumpColors src useColors =
|
|
|
+ (
|
|
|
+ Format "\"colors\": [" to:ostream
|
|
|
+ num = src.count
|
|
|
+
|
|
|
+ if num > 0 and useColors then
|
|
|
+ (
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ col = src[i]
|
|
|
+
|
|
|
+ r = col.r as Integer
|
|
|
+ g = col.g as Integer
|
|
|
+ b = col.b as Integer
|
|
|
+
|
|
|
+ hexNum = ( bit.shift r 16 ) + ( bit.shift g 8 ) + b
|
|
|
+
|
|
|
+ -- hexColor = formattedPrint hexNum format:"#x"
|
|
|
+ -- Format "%" hexColor to:ostream
|
|
|
+
|
|
|
+ decColor = formattedPrint hexNum format:"#d"
|
|
|
+ Format "%" decColor to:ostream
|
|
|
+
|
|
|
+ if i < num then Format "," to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ Format "],\n\n" to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump normals
|
|
|
+ function DumpNormals src =
|
|
|
+ (
|
|
|
+ Format "\"normals\": [" to:ostream
|
|
|
+ num = src.count
|
|
|
+
|
|
|
+ if num > 0 and exportNormal.checked then
|
|
|
+ (
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ normal = src[i]
|
|
|
+ normal = normalize normal as point3
|
|
|
+
|
|
|
+ if flipYZ.checked then
|
|
|
+ (
|
|
|
+ x = normal.x
|
|
|
+ y = normal.z
|
|
|
+ z = normal.y
|
|
|
+
|
|
|
+ z *= -1
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ x = normal.x
|
|
|
+ y = normal.y
|
|
|
+ z = normal.z
|
|
|
+ )
|
|
|
+
|
|
|
+ Format vertexNormalFormat x y z to:ostream
|
|
|
+ if i < num then Format "," to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ Format "],\n\n" to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump uvs
|
|
|
+ function DumpUvs src =
|
|
|
+ (
|
|
|
+ Format "\"uvs\": [[" to:ostream
|
|
|
+ num = src.count
|
|
|
+
|
|
|
+ if num > 0 and exportUv.checked then
|
|
|
+ (
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ uvw = src[i]
|
|
|
+
|
|
|
+ u = uvw.x
|
|
|
+
|
|
|
+ if flipUV.checked then
|
|
|
+ (
|
|
|
+ v = 1 - uvw.y
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ v = uvw.y
|
|
|
+ )
|
|
|
+
|
|
|
+ Format UVFormat u v to:ostream
|
|
|
+ if i < num then Format "," to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ Format "]],\n\n" to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump faces
|
|
|
+ function DumpFaces src useColors =
|
|
|
+ (
|
|
|
+ Format "\"faces\": [" to:ostream
|
|
|
+ num = src.count
|
|
|
+
|
|
|
+ if num > 0 then
|
|
|
+ (
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ zface = src[i]
|
|
|
+
|
|
|
+ fv = zface[1]
|
|
|
+ fuv = zface[2]
|
|
|
+ m = zface[3] - 1
|
|
|
+ fc = zface[4]
|
|
|
+
|
|
|
+ needsFlip = zface[5]
|
|
|
+
|
|
|
+ isTriangle = true
|
|
|
+ hasMaterial = true
|
|
|
+ hasFaceUvs = false
|
|
|
+ hasFaceVertexUvs = ((classof fuv == Point3) and exportUv.checked)
|
|
|
+ hasFaceNormals = false
|
|
|
+ hasFaceVertexNormals = (exportNormal.checked)
|
|
|
+ hasFaceColors = false
|
|
|
+ hasFaceVertexColors = ((classof fc == Point3) and useColors)
|
|
|
+
|
|
|
+ faceType = 0
|
|
|
+ faceType = bit.set faceType 1 (not isTriangle)
|
|
|
+ faceType = bit.set faceType 2 hasMaterial
|
|
|
+ faceType = bit.set faceType 3 hasFaceUvs
|
|
|
+ faceType = bit.set faceType 4 hasFaceVertexUvs
|
|
|
+ faceType = bit.set faceType 5 hasFaceNormals
|
|
|
+ faceType = bit.set faceType 6 hasFaceVertexNormals
|
|
|
+ faceType = bit.set faceType 7 hasFaceColors
|
|
|
+ faceType = bit.set faceType 8 hasFaceVertexColors
|
|
|
+
|
|
|
+ if i > 1 then
|
|
|
+ (
|
|
|
+ Format "," faceType to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ Format "%" faceType to:ostream
|
|
|
+
|
|
|
+ if isTriangle then
|
|
|
+ (
|
|
|
+ va = (fv.x - 1) as Integer
|
|
|
+ vb = (fv.y - 1) as Integer
|
|
|
+ vc = (fv.z - 1) as Integer
|
|
|
+
|
|
|
+ if flipFace.checked or needsFlip then
|
|
|
+ (
|
|
|
+ tmp = vb
|
|
|
+ vb = vc
|
|
|
+ vc = tmp
|
|
|
+ )
|
|
|
+
|
|
|
+ Format ",%,%,%" va vb vc to:ostream
|
|
|
+
|
|
|
+ if hasMaterial then
|
|
|
+ (
|
|
|
+ Format ",%" m to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ if hasFaceVertexUvs then
|
|
|
+ (
|
|
|
+ ua = (fuv.x - 1) as Integer
|
|
|
+ ub = (fuv.y - 1) as Integer
|
|
|
+ uc = (fuv.z - 1) as Integer
|
|
|
+
|
|
|
+ if flipFace.checked or needsFlip then
|
|
|
+ (
|
|
|
+ tmp = ub
|
|
|
+ ub = uc
|
|
|
+ uc = tmp
|
|
|
+ )
|
|
|
+ Format ",%,%,%" ua ub uc to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ if hasFaceVertexNormals then
|
|
|
+ (
|
|
|
+ if smoothNormal.checked then
|
|
|
+ (
|
|
|
+ -- normals have the same indices as vertices
|
|
|
+ na = va
|
|
|
+ nb = vb
|
|
|
+ nc = vc
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ -- normals have the same indices as face
|
|
|
+ na = i - 1
|
|
|
+ nb = na
|
|
|
+ nc = na
|
|
|
+ )
|
|
|
+
|
|
|
+ if flipFace.checked or needsFlip then
|
|
|
+ (
|
|
|
+ tmp = nb
|
|
|
+ nb = nc
|
|
|
+ nc = tmp
|
|
|
+ )
|
|
|
+ Format ",%,%,%" na nb nc to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ if hasFaceVertexColors then
|
|
|
+ (
|
|
|
+ ca = (fc.x - 1) as Integer
|
|
|
+ cb = (fc.y - 1) as Integer
|
|
|
+ cc = (fc.z - 1) as Integer
|
|
|
+
|
|
|
+ if flipFace.checked or needsFlip then
|
|
|
+ (
|
|
|
+ tmp = cb
|
|
|
+ cb = cc
|
|
|
+ cc = tmp
|
|
|
+ )
|
|
|
+ Format ",%,%,%" ca cb cc to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ Format "]\n\n" to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump color
|
|
|
+
|
|
|
+ function DumpColor pcolor label =
|
|
|
+ (
|
|
|
+ r = pcolor.r / 255
|
|
|
+ g = pcolor.g / 255
|
|
|
+ b = pcolor.b / 255
|
|
|
+
|
|
|
+ fr = formattedPrint r format:".4f"
|
|
|
+ fg = formattedPrint g format:".4f"
|
|
|
+ fb = formattedPrint b format:".4f"
|
|
|
+
|
|
|
+ Format "\"%\" : [%, %, %],\n" label fr fg fb to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Dump map
|
|
|
+ function DumpMap pmap label =
|
|
|
+ (
|
|
|
+ if classof pmap == BitmapTexture then
|
|
|
+ (
|
|
|
+ bm = pmap.bitmap
|
|
|
+
|
|
|
+ if bm != undefined then
|
|
|
+ (
|
|
|
+ fname = filenameFromPath bm.filename
|
|
|
+ Format "\"%\" : \"%\",\n" label fname to:ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Export materials
|
|
|
+ function ExportMaterials zmaterials zcolors =
|
|
|
+ (
|
|
|
+ Format "\"materials\": [\n" to:ostream
|
|
|
+
|
|
|
+ totalMaterials = zmaterials.count
|
|
|
+
|
|
|
+ for i = 1 to totalMaterials do
|
|
|
+ (
|
|
|
+ mat = zmaterials[i]
|
|
|
+
|
|
|
+ Format "{\n" to:ostream
|
|
|
+
|
|
|
+ -- debug
|
|
|
+ Format "\"DbgIndex\" : %,\n" (i-1) to:ostream
|
|
|
+
|
|
|
+ if classof mat != BooleanClass then
|
|
|
+ (
|
|
|
+ useVertexColors = zcolors[i]
|
|
|
+
|
|
|
+ Format "\"DbgName\" : \"%\",\n" mat.name to:ostream
|
|
|
+
|
|
|
+ -- colors
|
|
|
+ DumpColor mat.diffuse "colorDiffuse"
|
|
|
+ DumpColor mat.ambient "colorAmbient"
|
|
|
+ DumpColor mat.specular "colorSpecular"
|
|
|
+
|
|
|
+ t = mat.opacity / 100
|
|
|
+ s = mat.glossiness
|
|
|
+
|
|
|
+ Format "\"transparency\" : %,\n" t to:ostream
|
|
|
+ Format "\"specularCoef\" : %,\n" s to:ostream
|
|
|
+
|
|
|
+ -- maps
|
|
|
+ DumpMap mat.diffuseMap "mapDiffuse"
|
|
|
+ DumpMap mat.ambientMap "mapAmbient"
|
|
|
+ DumpMap mat.specularMap "mapSpecular"
|
|
|
+ DumpMap mat.bumpMap "mapBump"
|
|
|
+ DumpMap mat.opacityMap "mapAlpha"
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ useVertexColors = false
|
|
|
+ Format "\"DbgName\" : \"%\",\n" "dummy" to:ostream
|
|
|
+ DumpColor red "colorDiffuse"
|
|
|
+ )
|
|
|
+
|
|
|
+ Format "\"vertexColors\" : %\n" useVertexColors to:ostream
|
|
|
+ Format "}" to:ostream
|
|
|
+
|
|
|
+ if ( i < totalMaterials ) then Format "," to:ostream
|
|
|
+ Format "\n\n" to:ostream
|
|
|
+ )
|
|
|
+ Format "],\n\n" to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract vertices from mesh
|
|
|
+ function ExtractVertices obj whereto =
|
|
|
+ (
|
|
|
+ n = obj.numVerts
|
|
|
+ for i = 1 to n do
|
|
|
+ (
|
|
|
+ v = GetVert obj i
|
|
|
+ append whereto v
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract vertex colors from mesh
|
|
|
+
|
|
|
+ function ExtractColors obj whereto =
|
|
|
+ (
|
|
|
+ nColors = GetNumCPVVerts obj
|
|
|
+
|
|
|
+ if nColors > 0 then
|
|
|
+ (
|
|
|
+ for i = 1 to nColors do
|
|
|
+ (
|
|
|
+ c = GetVertColor obj i
|
|
|
+ append whereto c
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract normals from mesh
|
|
|
+
|
|
|
+ function ExtractNormals obj whereto needsFlip =
|
|
|
+ (
|
|
|
+ if smoothNormal.checked then
|
|
|
+ (
|
|
|
+ num = obj.numVerts
|
|
|
+
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ n = GetNormal obj i
|
|
|
+
|
|
|
+ if flipFace.checked or needsFlip then
|
|
|
+ (
|
|
|
+ n.x *= -1
|
|
|
+ n.y *= -1
|
|
|
+ n.z *= -1
|
|
|
+ )
|
|
|
+ append whereto n
|
|
|
+ )
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ num = obj.numFaces
|
|
|
+
|
|
|
+ for i = 1 to num do
|
|
|
+ (
|
|
|
+ n = GetFaceNormal obj i
|
|
|
+
|
|
|
+ if flipFace.checked or needsFlip then
|
|
|
+ (
|
|
|
+ n.x *= -1
|
|
|
+ n.y *= -1
|
|
|
+ n.z *= -1
|
|
|
+ )
|
|
|
+
|
|
|
+ append whereto n
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract uvs from mesh
|
|
|
+
|
|
|
+ function ExtractUvs obj whereto =
|
|
|
+ (
|
|
|
+ n = obj.numTVerts
|
|
|
+ for i = 1 to n do
|
|
|
+ (
|
|
|
+ v = GetTVert obj i
|
|
|
+ append whereto v
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract faces from mesh
|
|
|
+ function ExtractFaces objMesh objMaterial whereto allMaterials needsFlip hasVColors offsetVert offsetUv offsetColor =
|
|
|
+ (
|
|
|
+ n = objMesh.numFaces
|
|
|
+ hasUVs = objMesh.numTVerts > 0
|
|
|
+
|
|
|
+ useMultiMaterial = false
|
|
|
+ materialIDList = #()
|
|
|
+
|
|
|
+ materialClass = classof objMaterial
|
|
|
+
|
|
|
+ if materialClass == StandardMaterial then
|
|
|
+ (
|
|
|
+ fm = findItem allMaterials objMaterial
|
|
|
+ )
|
|
|
+ else if materialClass == MultiMaterial then
|
|
|
+ (
|
|
|
+ useMultiMaterial = true
|
|
|
+ for i = 1 to n do
|
|
|
+ (
|
|
|
+ mID = GetFaceMatID objMesh i
|
|
|
+ materialIndex = findItem objMaterial.materialIDList mID
|
|
|
+
|
|
|
+ if materialIndex > 0 then
|
|
|
+ (
|
|
|
+ subMaterial = objMaterial.materialList[materialIndex]
|
|
|
+
|
|
|
+ mMergedIndex = findItem allMaterials subMaterial
|
|
|
+
|
|
|
+ if mMergedIndex > 0 then
|
|
|
+ (
|
|
|
+ materialIDList[mID] = mMergedIndex
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ materialIDList[mID] = findItem allMaterials false
|
|
|
+ )
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ materialIDList[mID] = findItem allMaterials false
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ -- undefined material
|
|
|
+ fm = findItem allMaterials false
|
|
|
+ )
|
|
|
+
|
|
|
+ for i = 1 to n do
|
|
|
+ (
|
|
|
+ zface = #()
|
|
|
+
|
|
|
+ fv = GetFace objMesh i
|
|
|
+
|
|
|
+ fv.x += offsetVert
|
|
|
+ fv.y += offsetVert
|
|
|
+ fv.z += offsetVert
|
|
|
+
|
|
|
+ if useMultiMaterial then
|
|
|
+ (
|
|
|
+ mID = GetFaceMatID objMesh i
|
|
|
+ fm = materialIDList[mID]
|
|
|
+ )
|
|
|
+
|
|
|
+ if hasUVs then
|
|
|
+ (
|
|
|
+ fuv = GetTVFace objMesh i
|
|
|
+
|
|
|
+ fuv.x += offsetUv
|
|
|
+ fuv.y += offsetUv
|
|
|
+ fuv.z += offsetUv
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ fuv = false
|
|
|
+ )
|
|
|
+
|
|
|
+ if hasVColors then
|
|
|
+ (
|
|
|
+ fc = GetVCFace objMesh i
|
|
|
+
|
|
|
+ fc.x += offsetColor
|
|
|
+ fc.y += offsetColor
|
|
|
+ fc.z += offsetColor
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ fc = false
|
|
|
+ )
|
|
|
+
|
|
|
+ append zface fv
|
|
|
+ append zface fuv
|
|
|
+ append zface fm
|
|
|
+ append zface fc
|
|
|
+ append zface needsFlip
|
|
|
+
|
|
|
+ append whereto zface
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract materials from eventual multi-material
|
|
|
+ function ExtractMaterials objMesh objMaterial whereto wheretoColors zname hasVColors =
|
|
|
+ (
|
|
|
+ materialClass = classof objMaterial
|
|
|
+
|
|
|
+ if materialClass == StandardMaterial then
|
|
|
+ (
|
|
|
+ if ( findItem whereto objMaterial ) == 0 then
|
|
|
+ (
|
|
|
+ append whereto objMaterial
|
|
|
+ append wheretoColors hasVColors
|
|
|
+ )
|
|
|
+ )
|
|
|
+ else if materialClass == MultiMaterial then
|
|
|
+ (
|
|
|
+ n = objMesh.numFaces
|
|
|
+
|
|
|
+ for i = 1 to n do
|
|
|
+ (
|
|
|
+ mID = getFaceMatId objMesh i
|
|
|
+ materialIndex = findItem objMaterial.materialIDList mID
|
|
|
+
|
|
|
+ if materialIndex > 0 then
|
|
|
+ (
|
|
|
+ subMaterial = objMaterial.materialList[materialIndex]
|
|
|
+
|
|
|
+ if ( findItem whereto subMaterial ) == 0 then
|
|
|
+ (
|
|
|
+ append whereto subMaterial
|
|
|
+ append wheretoColors hasVColors
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ else
|
|
|
+ (
|
|
|
+ -- unknown or undefined material
|
|
|
+ append whereto false
|
|
|
+ append wheretoColors false
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Hack to figure out if normals are messed up
|
|
|
+ function NeedsFaceFlip node =
|
|
|
+ (
|
|
|
+ needsFlip = false
|
|
|
+ local tmp = Snapshot node
|
|
|
+ face_normal = normalize ( getfacenormal tmp 1 )
|
|
|
+ face = getface tmp 1
|
|
|
+
|
|
|
+ va = getvert tmp face[1]
|
|
|
+ vb = getvert tmp face[2]
|
|
|
+ vc = getvert tmp face[3]
|
|
|
+
|
|
|
+ computed_normal = normalize ( cross (vc - vb) (va - vb) )
|
|
|
+ if distance computed_normal face_normal > 0.1 then needsFlip = true
|
|
|
+ delete tmp
|
|
|
+ return needsFlip
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Extract only things that either already are or can be converted to meshes
|
|
|
+ function ExtractMesh node =
|
|
|
+ (
|
|
|
+ if SuperClassOf node == GeometryClass then
|
|
|
+ (
|
|
|
+ needsFlip = false
|
|
|
+ hasVColors = false
|
|
|
+
|
|
|
+ zmesh = SnapshotAsMesh node
|
|
|
+
|
|
|
+ if autoflipFace.checked then
|
|
|
+ (
|
|
|
+ needsFlip = NeedsFaceFlip node
|
|
|
+ )
|
|
|
+
|
|
|
+ if exportColor.checked and ( getNumCPVVerts zmesh ) > 0 then
|
|
|
+ (
|
|
|
+ hasVColors = true
|
|
|
+ )
|
|
|
+ return #( zmesh, node.name, node.material, needsFlip, hasVColors )
|
|
|
+ )
|
|
|
+ -- Not geometry ... could be a camera, light, etc.
|
|
|
+ return #( false, node.name, 0, false, false )
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Export scene
|
|
|
+ function ExportScene =
|
|
|
+ (
|
|
|
+ -- Extract meshes
|
|
|
+ meshObjects = #()
|
|
|
+
|
|
|
+ mergedVertices = #()
|
|
|
+ mergedNormals = #()
|
|
|
+ mergedColors = #()
|
|
|
+
|
|
|
+ mergedUvs = #()
|
|
|
+ mergedFaces = #()
|
|
|
+
|
|
|
+ mergedMaterials = #()
|
|
|
+ mergedMaterialsColors = #()
|
|
|
+
|
|
|
+ sceneHasVColors = false
|
|
|
+
|
|
|
+ for obj in selection do
|
|
|
+ (
|
|
|
+ result = ExtractMesh obj
|
|
|
+ meshObj = result[1]
|
|
|
+
|
|
|
+ if ClassOf meshObj == TriMesh then
|
|
|
+ (
|
|
|
+ meshName = result[2]
|
|
|
+ meshMaterial = result[3]
|
|
|
+ needsFlip = result[4]
|
|
|
+ hasVColors = result[5]
|
|
|
+
|
|
|
+ sceneHasVColors = sceneHasVColors or hasVColors
|
|
|
+
|
|
|
+ append meshObjects result
|
|
|
+
|
|
|
+ vertexOffset = mergedVertices.count
|
|
|
+ uvOffset = mergedUvs.count
|
|
|
+ colorOffset = mergedColors.count
|
|
|
+
|
|
|
+ ExtractMaterials meshObj meshMaterial mergedMaterials mergedMaterialsColors meshName hasVColors
|
|
|
+
|
|
|
+ ExtractVertices meshObj mergedVertices
|
|
|
+ ExtractNormals meshObj mergedNormals needsFlip
|
|
|
+ ExtractColors meshObj mergedColors
|
|
|
+
|
|
|
+ ExtractUvs meshObj mergedUvs
|
|
|
+
|
|
|
+ ExtractFaces meshObj meshMaterial mergedFaces mergedMaterials needsFlip hasVColors vertexOffset uvOffset colorOffset
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ totalVertices = mergedVertices.count
|
|
|
+ totalFaces = mergedFaces.count
|
|
|
+ totalMaterials = mergedMaterials.count
|
|
|
+
|
|
|
+ totalColors = 0
|
|
|
+ totalNormals = 0
|
|
|
+ totalUvs = 0
|
|
|
+
|
|
|
+ useColors = false
|
|
|
+
|
|
|
+ if sceneHasVColors and exportColor.checked then
|
|
|
+ (
|
|
|
+ totalColors = mergedColors.count
|
|
|
+ useColors = true
|
|
|
+ )
|
|
|
+
|
|
|
+ if exportNormal.checked then
|
|
|
+ (
|
|
|
+ totalNormals = mergedNormals.count
|
|
|
+ )
|
|
|
+
|
|
|
+ if exportUv.checked then
|
|
|
+ (
|
|
|
+ totalUvs = mergedUvs.count
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ -- Dump objects (debug)
|
|
|
+ -- Format "// Source objects:\n\n" to:ostream
|
|
|
+ -- i = 0
|
|
|
+ -- for obj in meshObjects do
|
|
|
+ -- (
|
|
|
+ -- meshName = obj[2]
|
|
|
+ -- Format "// %: %\n" i meshName to:ostream
|
|
|
+ -- i += 1
|
|
|
+ -- )
|
|
|
+
|
|
|
+ -- Dump model
|
|
|
+ Format "{\n\n" to:ostream
|
|
|
+
|
|
|
+ -- Dump header
|
|
|
+ Format headerFormat maxFileName totalVertices totalNormals totalColors totalUvs totalFaces totalMaterials to:ostream
|
|
|
+
|
|
|
+ -- Dump all materials in the scene
|
|
|
+ ExportMaterials mergedMaterials mergedMaterialsColors
|
|
|
+
|
|
|
+ -- Dump merged data from all selected geometries
|
|
|
+ DumpVertices mergedVertices
|
|
|
+
|
|
|
+ ---- 2014.06.25 16:14
|
|
|
+ dump_morph_targets()
|
|
|
+ ----
|
|
|
+
|
|
|
+ DumpNormals mergedNormals
|
|
|
+ DumpColors mergedColors useColors
|
|
|
+ DumpUvs mergedUvs
|
|
|
+ DumpFaces mergedFaces useColors
|
|
|
+
|
|
|
+ -- Dump footer
|
|
|
+ Format footerFormat to:ostream
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Open and prepare a file handle for writing
|
|
|
+ function GetSaveFileStream =
|
|
|
+ (
|
|
|
+ zname = getFilenameFile maxFileName
|
|
|
+ zname += ".js"
|
|
|
+
|
|
|
+ fname = GetSaveFileName filename:zname types:"JavaScript file (*.js)|*.js|All Files(*.*)|*.*|"
|
|
|
+ if fname == undefined then
|
|
|
+ (
|
|
|
+ return undefined
|
|
|
+ )
|
|
|
+
|
|
|
+ ostream = CreateFile fname
|
|
|
+ if ostream == undefined then
|
|
|
+ (
|
|
|
+ MessageBox "Couldn't open file for writing !"
|
|
|
+ return undefined
|
|
|
+ )
|
|
|
+ return ostream
|
|
|
+ )
|
|
|
+
|
|
|
+ -------------------------------------------------------------------------------------
|
|
|
+ -- Export button click handler
|
|
|
+ on btn_export pressed do
|
|
|
+ (
|
|
|
+ ostream = GetSaveFileStream()
|
|
|
+ if ostream != undefined then
|
|
|
+ (
|
|
|
+ ExportScene()
|
|
|
+ close ostream
|
|
|
+ )
|
|
|
+ )
|
|
|
+)
|
|
|
+createDialog ThreeJSExporter width:300
|