export_to_three.js.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. '''
  2. author : "George Profenza"
  3. url : ("disturb", "disturbmedia.com/blog","My blog, http://tomaterial.blogspot.com")
  4. Export meshes the three.js 3D Engine by mr.doob's et al.
  5. More details on the engine here:
  6. https://github.com/mrdoob/three.js
  7. Currently supports UVs. If the model doesn't display correctly
  8. you might need to reverse some normals/do some cleanup.
  9. Also, if you use Selection Tags and basic ColorMaterials,
  10. the colours will be picked up as face colors. Call autoColor() on the
  11. model you use for this.
  12. The mesh transformations(position, rotation, scale) are saved
  13. and you can get them using: getPosition(), getRotation() and getScale()
  14. each returning a THREE.Vector3
  15. In short
  16. var myGeom = new myC4DGeom();
  17. var myModel = new THREE.Mesh( myGeom, new THREE.MeshFaceMaterial());
  18. //set transforms
  19. model.position = myGeom.getPosition()
  20. model.rotation = myGeom.getRotation()
  21. model.scale = myGeom.getScale()
  22. //set selection tags colours
  23. myGeom.autoColor()
  24. More details on this exporter and more js examples here:
  25. https://github.com/orgicus/three.js
  26. Have fun!
  27. This script requires Cinema 4D R11.5 minimum and the Py4D Plugin:
  28. http://www.py4d.com/get-py4d/
  29. '''
  30. import c4d
  31. from c4d import documents,UVWTag,storage
  32. from c4d.utils import *
  33. from c4d import symbols as sy, plugins, utils, bitmaps, gui
  34. import math
  35. import re
  36. # utils
  37. clean = lambda varStr: re.sub('\W|^(?=\d)','_', varStr)
  38. # from Active State's Python recipies: http://code.activestate.com/recipes/266466-html-colors-tofrom-rgb-tuples/
  39. def RGBToHTMLColor(rgb_tuple):
  40. return '0x%02x%02x%02x' % rgb_tuple
  41. def Export():
  42. if not op: return
  43. if op.GetType() != 5100:
  44. print 'Selected Object is not an editable mesh'
  45. return
  46. unit = 0.001#for scale
  47. fps = doc.GetFps()
  48. bd = doc.GetRenderBaseDraw()
  49. scr = bd.GetFrameScreen()
  50. rd = doc.GetActiveRenderData()
  51. name = op.GetName()
  52. classname = clean(name)
  53. c4dPath = c4d.storage.GeGetC4DPath(sy.C4D_PATH_LIBRARY)
  54. jsFile = open(c4dPath+'/scripts/Three.js','r')
  55. js = jsFile.read()
  56. htmlFile = open(c4dPath+'/scripts/template.html','r')
  57. html = htmlFile.read()
  58. html = html.replace('%s',classname)
  59. code = 'var %s = function () {\n\n\tvar scope = this;\n\n\tTHREE.Geometry.call(this);\n\n' % classname
  60. def GetMesh(code):
  61. # goto 0
  62. doc.SetTime(c4d.BaseTime(0, fps))
  63. c4d.DrawViews( c4d.DA_ONLY_ACTIVE_VIEW|c4d.DA_NO_THREAD|c4d.DA_NO_REDUCTION|c4d.DA_STATICBREAK )
  64. c4d.GeSyncMessage(c4d.EVMSG_TIMECHANGED)
  65. doc.SetTime(doc.GetTime())
  66. c4d.EventAdd(c4d.EVENT_ANIMATE)
  67. SendModelingCommand(command = MCOMMAND_REVERSENORMALS, list = [op], mode = MODIFY_ALL, bc = c4d.BaseContainer(), doc = doc)
  68. verts = op.GetPointAll()
  69. for v in verts:
  70. code += '\tv( %.6f, %.6f, %.6f );\n' % (v.x, -v.y, v.z)
  71. code += '\n'
  72. ncount = 0
  73. uvcount = 0
  74. faces = op.GetAllPolygons()
  75. normals = op.CreatePhongNormals()
  76. ndirection = 1
  77. hasUV = False
  78. for tag in op.GetTags():
  79. if tag.GetName() == "UVW":
  80. uvw = tag
  81. hasUV = True
  82. for f in faces:
  83. if(f.d == f.c):
  84. if(normals):
  85. code += '\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.a, f.b, f.c, normals[ncount].x*ndirection, normals[ncount].y*ndirection, normals[ncount].z*ndirection)
  86. else:
  87. code += '\tf3( %d, %d, %d );\n' % (f.a, f.b, f.c)
  88. else:
  89. if(normals):
  90. code += '\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.a, f.b, f.c, f.d, normals[ncount].x*ndirection, normals[ncount].y*ndirection, normals[ncount].z*ndirection)
  91. else:
  92. code += '\tf4( %d, %d, %d, %d );\n' % (f.a, f.b, f.c, f.d)
  93. if hasUV:
  94. uv = uvw.Get(uvcount);
  95. # uvs += '[Vector('+str(uv[0].x)+','+str(1.0-uv[0].y)+'),Vector('+str(uv[1].x)+','+str(1.0-uv[1].y)+'),Vector('+str(uv[2].x)+','+str(1.0-uv[2].y)+')],'
  96. if len(uv) == 4:
  97. code += '\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f);\n' % (uv[0].x, uv[0].y, uv[1].x, uv[1].y, uv[2].x, uv[2].y, uv[3].x, uv[3].y)
  98. else:
  99. code += '\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f);\n' % (uv[0].x, uv[0].y, uv[1].x, uv[1].y, uv[2].x, uv[2].y)
  100. ncount += 1
  101. uvcount += 1
  102. code +='\n\tthis.computeCentroids();\n\tthis.computeNormals(true);\n'
  103. #selection color
  104. code +='\n\tscope.colors = {};\n'
  105. code +='\tscope.selections = {};\n'
  106. selName = ''
  107. for tag in op.GetTags():
  108. if(tag.GetType() == 5616): #texture tag
  109. material = tag.GetMaterial()
  110. color = material[sy.MATERIAL_COLOR_COLOR]
  111. tag.SetBit(c4d.BIT_ACTIVE)
  112. selName = clean(tag[sy.TEXTURETAG_RESTRICTION])
  113. if len(selName) == 0: print "*** WARNING! *** Missing selection name for material: " + material.GetName()
  114. code += '\tscope.colors["'+selName+'"] = '+str(RGBToHTMLColor((color.x*255,color.y*255,color.z*255)))+';\n'
  115. if tag.GetType() == 5673: #selection tag
  116. # print 'selection: ' + tag.GetName()
  117. sel = tag.GetSelection()
  118. selName = clean(tag.GetName())
  119. ids = sel.GetAll(op.GetPointCount())
  120. indices = [i for i, e in enumerate(ids) if e != 0]
  121. code += '\tscope.selections["'+selName+'"] = '+str(indices)+';\n'
  122. code += '\n\tscope.autoColor = function(){\n'
  123. code += '\t\tfor(var s in this.selections){\n'
  124. code += '\t\t\tfor(var i = 0 ; i < this.selections[s].length; i++) this.faces[this.selections[s][i]].material = [new THREE.MeshBasicMaterial({color:this.colors[s]})];\n'
  125. code += '\t\t}\n\t}\n'
  126. # model position, rotation, scale rotation x,y,z = H,P,B => three.js x,y,z is P,H,B => y,x,z
  127. p = op.GetPos()
  128. r = op.GetRot()
  129. s = op.GetScale()
  130. code += '\n\tscope.getPosition = function(){\treturn new THREE.Vector3'+str((p.x,p.y,p.z))+';\t}\n'
  131. code += '\n\tscope.getRotation = function(){\treturn new THREE.Vector3'+str((r.y,r.x,r.z))+';\t}\n'
  132. code += '\n\tscope.getScale = function(){\treturn new THREE.Vector3'+str((s.x,s.y,s.z))+';\t}\n'
  133. code += '\n'
  134. code += '\tfunction v( x, y, z ) {\n\n'
  135. code += '\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n'
  136. code += '\t}\n\n'
  137. code += '\tfunction f3( a, b, c, nx, ny, nz ) {\n\n'
  138. code += '\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n'
  139. code += '\t}\n\n'
  140. code += '\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n'
  141. code += '\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n'
  142. code += '\t}\n\n'
  143. code += '\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n'
  144. code += '\t\tvar uv = [];\n'
  145. code += '\t\tuv.push( new THREE.UV( u1, v1 ) );\n'
  146. code += '\t\tuv.push( new THREE.UV( u2, v2 ) );\n'
  147. code += '\t\tuv.push( new THREE.UV( u3, v3 ) );\n'
  148. code += '\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n'
  149. code += '\t\tscope.uvs.push( uv );\n'
  150. code += '\t}\n\n'
  151. code += '}\n\n'
  152. code += '%s.prototype = new THREE.Geometry();\n' % classname
  153. code += '%s.prototype.constructor = %s;' % (classname, classname)
  154. SendModelingCommand(command = MCOMMAND_REVERSENORMALS, list = [op], mode = MODIFY_ALL, bc = c4d.BaseContainer(), doc = doc)
  155. return code
  156. code = GetMesh(code)
  157. docPath = doc.GetDocumentPath()
  158. jspath = docPath+'/'+classname+'.js'
  159. htmlpath = docPath+'/'+classname+'.html'
  160. file = open(jspath,'w')
  161. file.write(code)
  162. file.close()
  163. file = open(htmlpath,'w')
  164. file.write(html)
  165. file.close()
  166. file = open(docPath+'/Three.js','w')
  167. file.write(js)
  168. file.close()
  169. print 'Export Complete!'
  170. Export()