Skip to content

Instantly share code, notes, and snippets.

@hyOzd
Last active May 8, 2021 01:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyOzd/2b38adff6a04e1613622 to your computer and use it in GitHub Desktop.
Save hyOzd/2b38adff6a04e1613622 to your computer and use it in GitHub Desktop.
An experimental FreeCAD macro that will export visible objects as X3D
#
# This is an experimental FreeCAD macro that will export current scene
# as X3D file. Only the visible objects that can be converted to mesh
# will be exported with their color.
#
import FreeCAD
import FreeCADGui
import xml.etree.ElementTree as et
from PySide.QtGui import QFileDialog
import os
def getShapeNode(vertices, faces, diffuseColor=None):
"""Returns a <Shape> node for given mesh data.
vertices: list of vertice coordinates as `Vector` type
faces: list of tuple of vertice indexes ex: (1, 2, 3)
diffuseColor: tuple in the form of (R, G, B)"""
shapeNode = et.Element('Shape')
faceNode = et.SubElement(shapeNode, 'IndexedFaceSet')
faceNode.set('coordIndex', ' '.join(["%d %d %d -1" % face for face in faces]))
coordinateNode = et.SubElement(faceNode, 'Coordinate')
coordinateNode.set('point',
' '.join(["%f %f %f" % (p.x, p.y, p.z) for p in vertices]))
if diffuseColor:
appearanceNode = et.SubElement(shapeNode, 'Appearance')
materialNode = et.SubElement(appearanceNode, 'Material')
materialNode.set('diffuseColor', "%f %f %f" % diffuseColor)
return shapeNode
def exportX3D(objects, filepath):
"""Export given list of objects to a X3D file.
Each object is a dictionary in this form:
{
points : [Vector, Vector...],
faces : [(pi, pi, pi), ...], # pi: point index
color : (R, G, B) # number range is 0-1.0
}"""
fileNode = et.Element('X3D')
fileNode.set('profile', 'Interchange')
fileNode.set('version', '3.3')
sceneNode = et.SubElement(fileNode, 'Scene')
for o in objects:
shapeNode = getShapeNode(o["points"], o["faces"], o["color"])
sceneNode.append(shapeNode)
with open(filepath, "wr") as f:
f.write(et.tostring(fileNode))
def getDocumentDir(doc):
"""Returns directory for given document. `None` if the file is not
saved yet."""
if doc.FileName:
return os.path.dirname(doc.FileName)
else:
return None
def run():
doc = FreeCAD.activeDocument()
objects = []
for o in doc.Objects:
if o.ViewObject.Visibility:
if hasattr(o, "Shape"):
mesh = o.Shape.tessellate(1)
if (not mesh[0]) or (not mesh[1]):
continue # some objects (such as Part:Circle)
# generate empty mesh, skip them
objects.append({
"points": mesh[0],
"faces": mesh[1],
"color": o.ViewObject.ShapeColor[0:3]
})
if objects:
savefile = QFileDialog.getSaveFileName(
parent = FreeCADGui.getMainWindow(),
caption = "Export X3D file",
dir = getDocumentDir(doc))[0]
exportX3D(objects, savefile)
else:
raise Exception("There is nothing to export!")
if __name__ == "__main__":
run()
@hyOzd
Copy link
Author

hyOzd commented Mar 27, 2016

@jmwright no problem at all. About the notifications, github doesn't send notifications on gist comments :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment