From 7e11f28866cefe50b7f803745243c5ff01348e92 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 9 Apr 2013 19:43:45 -0300 Subject: [PATCH] 0001035: WebGL exporter The Arch module now features a webgl exporter that produces an all-included HTML file that displays the exported objects in WebGL-capable web browsers. Many enhancements are still necessary, especially with lights and materials. At time of export, the exporter downloads the three.js library from github and includes it in the HTML file, so it has no other dependencies. --- src/Mod/Arch/CMakeLists.txt | 1 + src/Mod/Arch/InitGui.py | 1 + src/Mod/Arch/importWebGL.py | 166 +++++++++++++++++++++++++++++++ src/Mod/Draft/Draft.py | 26 ++--- src/WindowsInstaller/ModArch.wxi | 2 +- 5 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 src/Mod/Arch/importWebGL.py diff --git a/src/Mod/Arch/CMakeLists.txt b/src/Mod/Arch/CMakeLists.txt index fcfd728bb..28f691455 100644 --- a/src/Mod/Arch/CMakeLists.txt +++ b/src/Mod/Arch/CMakeLists.txt @@ -21,6 +21,7 @@ SET(Arch_SRCS ArchAxis.py ArchVRM.py ArchRoof.py + importWebGL.py ) SOURCE_GROUP("" FILES ${Arch_SRCS}) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index ddba892dc..1f5f2386d 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -129,6 +129,7 @@ class ArchWorkbench(Workbench): FreeCADGui.addWorkbench(ArchWorkbench) FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC") FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") +FreeCAD.addExportType("WebGL file (*.html)","importWebGL") # check for pycollada try: import collada diff --git a/src/Mod/Arch/importWebGL.py b/src/Mod/Arch/importWebGL.py new file mode 100644 index 000000000..a8a8c4a2c --- /dev/null +++ b/src/Mod/Arch/importWebGL.py @@ -0,0 +1,166 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2013 * +#* Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Arch,Draft +from DraftTools import translate + +tab = " " + +if open.__module__ == '__builtin__': + pythonopen = open + +def export(exportList,filename): + "exports the given objects to a .html file" + + # get three.min.js + threejspath = Arch.download("https://raw.github.com/mrdoob/three.js/master/build/three.min.js") + threejsfile = pythonopen(threejspath,"r") + threeminjs = threejsfile.read() + threejsfile.close() + + # get objects data + objectsData = '' + for obj in exportList: + objectsData += getObjectData(obj) + + # build the final file + template = getTemplate() + template = template.replace("$ThreeMinJs",threeminjs) + template = template.replace("$CameraData",getCameraData()) + template = template.replace("$ObjectsData",objectsData) + template = template.replace("$TestData",getTestData()) + outfile = pythonopen(filename,"wb") + outfile.write(template) + outfile.close() + FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename) + +def getCameraData(): + "returns the position and direction of the camera as three.js snippet" + + # getting camera position + pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base + #result = "camera.position.set( -10,5,15" # test position + result = "camera.position.set( " + result += str(pos.x) + ", " + result += str(pos.y) + ", " + result += str(pos.z) + + # getting camera lookat vector + lookat = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() + lookat = pos.add(lookat) + result += " );\n"+tab+"camera.lookAt( scene.position );\n"+tab + #result += " );\n"+tab+"camera.lookAt( " + #result += str(lookat.x) + ", " + #result += str(lookat.y) + ", " + #result += str(lookat.z) + #result += " );\n"+tab + + # print result + return result + +def getObjectData(obj): + "returns the geometry data of an object as three.js snippet" + + if obj.isDerivedFrom("Part::Feature"): + fcmesh = obj.Shape.tessellate(0.1) + result = "var geom = new THREE.Geometry();\n" + + # adding vertices data + for i in range(len(fcmesh[0])): + v = fcmesh[0][i] + result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n" + result += tab+"console.log(geom.vertices)\n" + for i in range(len(fcmesh[0])): + result += tab+"geom.vertices.push(v"+str(i)+");\n" + + # adding facets data + for f in fcmesh[1]: + result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n" + + # adding material + col = obj.ViewObject.ShapeColor + rgb = Draft.getrgb(col,testbw=False) + #rgb = "#888888" # test color + result += tab+"var material = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" + + # adding the mesh to the scene + result += tab+"var mesh = new THREE.Mesh( geom, material );\n" + result += tab+"scene.add( mesh );\n"+tab + + # print result + return result + +def getTestData(): + "returns a simple cube as three.js snippet" + + #return """var geometry = new THREE.CubeGeometry( .5, .5, .5 ); + # var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } ); + # var mesh = new THREE.Mesh( geometry, material ); + # scene.add( mesh );""" + + return "" + +def getTemplate(): + "returns a html template" + + result = """ + + + FreeCAD model + + + + + + """ + + return result + diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 8a30efe50..8d2a39a97 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1283,18 +1283,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct return "0.02,0.02" return "none" - def getrgb(color): - "getRGB(color): returns a rgb value #000000 from a freecad color" - r = str(hex(int(color[0]*255)))[2:].zfill(2) - g = str(hex(int(color[1]*255)))[2:].zfill(2) - b = str(hex(int(color[2]*255)))[2:].zfill(2) - col = "#"+r+g+b - if col == "#ffffff": - print getParam('SvgLinesBlack') - if getParam('SvgLinesBlack'): - col = "#000000" - return col - def getProj(vec): if not plane: return vec nx = DraftVecUtils.project(vec,plane.u) @@ -1520,6 +1508,20 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct else: svg = getCircle(obj.Shape.Edges[0]) return svg + +def getrgb(color,testbw=True): + """getRGB(color,[testbw]): returns a rgb value #000000 from a freecad color + if testwb = True (default), pure white will be converted into pure black""" + r = str(hex(int(color[0]*255)))[2:].zfill(2) + g = str(hex(int(color[1]*255)))[2:].zfill(2) + b = str(hex(int(color[2]*255)))[2:].zfill(2) + col = "#"+r+g+b + if testbw: + if col == "#ffffff": + #print getParam('SvgLinesBlack') + if getParam('SvgLinesBlack'): + col = "#000000" + return col def makeDrawingView(obj,page,lwmod=None,tmod=None): ''' diff --git a/src/WindowsInstaller/ModArch.wxi b/src/WindowsInstaller/ModArch.wxi index f8bdd05c8..d43d16aef 100644 --- a/src/WindowsInstaller/ModArch.wxi +++ b/src/WindowsInstaller/ModArch.wxi @@ -32,7 +32,6 @@ - @@ -46,6 +45,7 @@ +