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.
This commit is contained in:
Yorik van Havre 2013-04-09 19:43:45 -03:00
parent eb8370a337
commit 7e11f28866
5 changed files with 183 additions and 13 deletions

View File

@ -21,6 +21,7 @@ SET(Arch_SRCS
ArchAxis.py
ArchVRM.py
ArchRoof.py
importWebGL.py
)
SOURCE_GROUP("" FILES ${Arch_SRCS})

View File

@ -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

166
src/Mod/Arch/importWebGL.py Normal file
View File

@ -0,0 +1,166 @@
#***************************************************************************
#* *
#* Copyright (c) 2013 *
#* Yorik van Havre <yorik@uncreated.net> *
#* *
#* 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 = """<!DOCTYPE html>
<html>
<head>
<title>FreeCAD model</title>
<script>$ThreeMinJs</script>
<script>
window.onload = function() {
var renderer = new THREE.WebGLRenderer();
renderer.setSize( 800, 600 );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
35, // Field of view
800 / 600, // Aspect ratio
0.1, // Near plane
10000 // Far plane
);
$CameraData // placeholder for the FreeCAD camera
$TestData // placeholder for a test cube
$ObjectsData // placeholder for the FreeCAD objects
var light = new THREE.PointLight( 0xFFFF00 );
light.position.set( -10, -10, 10 );
scene.add( light );
renderer.render( scene, camera );
};
</script>
</head>
<body></body>
</html>"""
return result

View File

@ -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):
'''

View File

@ -32,7 +32,6 @@
<File Id="ArchCellPy" Name="ArchCell.py" DiskId="1" />
<File Id="ArchCommandsPy" Name="ArchCommands.py" DiskId="1" />
<File Id="ArchComponentPy" Name="ArchComponent.py" DiskId="1" />
<!--<File Id="ArchIfcSchemaExp" Name="IFC2X3_TC1.exp" DiskId="1" />-->
<File Id="ArchIfcReaderPy" Name="ifcReader.py" DiskId="1" />
<File Id="importDAEPy" Name="importDAE.py" DiskId="1" />
<File Id="importIFCPy" Name="importIFC.py" DiskId="1" />
@ -46,6 +45,7 @@
<File Id="ArchAxisPy" Name="ArchAxis.py" DiskId="1" />
<File Id="ArchVRMPy" Name="ArchVRM.py" DiskId="1" />
<File Id="ArchRoofPy" Name="ArchRoof.py" DiskId="1" />
<File Id="importWebGLPy" Name="importWebGL.py" DiskId="1" />
</Component>
</Directory>
</Include>