-
-
Save zgao4/813832b68315678cce6e to your computer and use it in GitHub Desktop.
A FreeCAD webGL maker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import FreeCAD,WebGui | |
SCALE = 10 # global scale modifier | |
template = """<!DOCTYPE HTML> | |
<html lang="en"> | |
<head> | |
<title>FreeCAD webGL viewer</title> | |
<meta charset="utf-8"> | |
<style type="text/css"> | |
body { | |
background-color: #888888; | |
margin: 0px; | |
overflow: hidden; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"></div> | |
<script type="text/javascript" src="./Three.js"></script> | |
<!-- FreeCAD:ShapeDefs --> | |
<script type="text/javascript"> | |
var camera, scene, renderer, object; | |
var targetRotation = 0; | |
var targetRotationOnMouseDown = 0; | |
var targetRotationY = 0; | |
var targetRotationYOnMouseDown = 0; | |
var mouseX = 0; | |
var mouseXOnMouseDown = 0; | |
var mouseY = 0; | |
var mouseYOnMouseDown = 0; | |
var windowHalfX = window.innerWidth / 2; | |
var windowHalfY = window.innerHeight / 2; | |
init(); | |
setInterval( loop, 1000 / 60 ); | |
function init() { | |
var container = document.getElementById( 'container' ); | |
camera = new THREE.Camera( 50, window.innerWidth / window.innerHeight, 1, 2000 ); | |
camera.position.z = 1000; | |
scene = new THREE.Scene(); | |
scene.addLight( new THREE.AmbientLight( 0x0ff20 ) ); | |
light1 = new THREE.PointLight( 0xff0040 ); | |
scene.addLight( light1 ); | |
<!-- FreeCAD:ShapeCreate --> | |
//renderer = new THREE.CanvasRenderer(); | |
renderer = new THREE.WebGLRenderer(); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
container.appendChild( renderer.domElement ); | |
document.addEventListener( 'mousedown', onDocumentMouseDown, false ); | |
} | |
function onDocumentMouseDown( event ) { | |
event.preventDefault(); | |
document.addEventListener( 'mousemove', onDocumentMouseMove, false ); | |
document.addEventListener( 'mouseup', onDocumentMouseUp, false ); | |
document.addEventListener( 'mouseout', onDocumentMouseOut, false ); | |
mouseXOnMouseDown = event.clientX - windowHalfX; | |
mouseYOnMouseDown = event.clientY - windowHalfY; | |
targetRotationOnMouseDown = targetRotation; | |
} | |
function onDocumentMouseMove( event ) { | |
mouseX = event.clientX - windowHalfX; | |
mouseY = event.clientY - windowHalfY; | |
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; | |
targetRotationY = targetRotationYOnMouseDown + ( mouseY - mouseYOnMouseDown ) * 0.02; | |
} | |
function onDocumentMouseUp( event ) { | |
document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); | |
document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); | |
document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); | |
} | |
function onDocumentMouseOut( event ) { | |
document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); | |
document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); | |
document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); | |
} | |
function loop() { | |
var time = new Date().getTime() * 0.0005; | |
//object.rotation.x -= 0.005; | |
//object.rotation.y -= 0.01; | |
object.rotation.y += ( targetRotation - object.rotation.y ) * 0.02; | |
object.rotation.x += ( targetRotationY - object.rotation.x ) * 0.02; | |
renderer.render(scene, camera); | |
} | |
</script> | |
</body> | |
</html>""" | |
def to3js(obj): | |
"""Converts a freecad object to three.js javascript code""" | |
if not obj.isDerivedFrom("Part::Feature"): | |
return '' | |
# header | |
js = "var Shape" + obj.Name + " = function () {\n" | |
js += "var scope = this;\n" | |
js += "THREE.Geometry.call( this );\n\n" | |
# create mesh | |
m = obj.Shape.tessellate(1) | |
# export vertices | |
for v in m[0]: | |
js += "v(%.4f,%.4f,%.4f);\n"%(v.x,v.y,v.z) | |
js += "\n" | |
# export faces | |
index = 0 | |
for f in m[1]: | |
js += "f3(%i,%i,%i);\n"%(f[0],f[1],f[2]) | |
# make all work | |
js += "this.sortFacesByMaterial();\n" | |
js += "function v( x, y, z ) {\n" | |
js += "scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n" | |
js += "}\n" | |
js += "function f3( a, b, c , nx, ny, nz) {\n" | |
js += "scope.faces.push( new THREE.Face3( a, b, c , nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n" | |
js += "}\n" | |
js += "}\n\n" | |
js += "Shape" + obj.Name + ".prototype = new THREE.Geometry();\n" | |
js += "Shape" + obj.Name + ".prototype.constructor = Shape" + obj.Name + ";" | |
return js | |
def getHTML(objs): | |
"""gets an html page with the given objects""" | |
shapedefs = "" | |
shapecreates = "" | |
for obj in objs: | |
shapedefs += '<script type="text/javascript">\n' + to3js(obj) + "\n</script>\n" | |
shapecreates += "object = new THREE.Mesh( new Shape" + obj.Name + "(), new THREE.MeshNormalMaterial({opacity:1,shading:THREE.SmoothShading}) );\n" | |
shapecreates += "object.overdraw = true;\nobject.scale.x = object.scale.y = object.scale.z =" + str(SCALE) + ".;\nscene.addObject( object );\n" | |
html = template.replace("<!-- FreeCAD:ShapeDefs -->",shapedefs) | |
html = html.replace("<!-- FreeCAD:ShapeCreate -->",shapecreates) | |
return html | |
def getObjects(): | |
"""Returns viible objects from the active documnt""" | |
objs = [] | |
for obj in FreeCAD.ActiveDocument.Objects: | |
if obj.ViewObject.isVisible(): | |
objs.append(obj) | |
return objs | |
def show(): | |
"""Opens a webGL viewer with the scene contents""" | |
html = getHTML(getObjects()) | |
WebGui.openBrowserHTML(html,'file://' + FreeCAD.getResourceDir() + 'Mod/Web/WebGL/','WebGL viewer') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment