Last active
June 5, 2020 12:56
-
-
Save yorikvanhavre/e9722c280118b1ef141c4061d9d2dd8a to your computer and use it in GitHub Desktop.
FreeCAD offline rendering example
This file contains 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
#!/usr/bin/python3 | |
""" | |
This is a test file to test offline rendering functionality. It takes a FreeCAD file (colors.FCStd in | |
the examples below) and will produce colors.obj, colors.mtl, colors.dae, colors.ifc, colors.stp | |
and colors.png files in the same directory. It also saves a copy of the colors.FCStd file with | |
colors preserved. | |
Instructions: | |
- make sure you have the latest version of FreeCAD installed | |
- make sure you have the pivy (python bindongs for coin3D) package installed | |
- make sure FreeCAD is importable from python (use the commented line below if needed) | |
- on linux, the X server must have indirect rendering enabled in order to be able to do | |
offline PNG rendering. Unfortunatley, this is turned off by default on most recent | |
distros. The easiest way I found is to edit (or create if inexistant) /etc/X11/xorg.conf | |
and add this: | |
Section "ServerFlags" | |
Option "AllowIndirectGLX" "on" | |
Option "IndirectGLX" "on" | |
EndSection | |
(if your xorg.conf already has a "ServerFlags" section, just add the two options in it). | |
There might be other ways for other distros though, google for "enable indirect glx" | |
with your distro name and version | |
""" | |
import os # builtin python lib | |
import sys # builtin python lib | |
# if needed, uncomment and set the path to your FreeCAD.so (or FreeCAD.pyd on windows) below: | |
# sys.path.append("/path/to/FreeCAD.so") | |
# Another way, more system-independent, is to symlink your FreeCAD.so file to | |
# .local/lib/Python3.7/site-packages (user-wide) or | |
# /usr/lib/python3.7/dis-packages (system-wide) | |
# (using your version of python3 instead of 3.7 in the links above if applicable) | |
import FreeCAD # main freecad lib, to be imported before any other FreeCAD component (will add their paths to sys) | |
import importOBJ # builtin FreeCAD exporter | |
import importDAE # builtin FreeCAD exporter | |
import importIFC # builtin FreeCAD exporter | |
import importWebGL # builtin FreeCAD exporter | |
import Import # builtin FreeCAD exporter (step & iges) | |
import OfflineRenderingUtils # the offline rendering utilities module | |
# build full filepaths (not 100% required, relative paths work in python too, but always safer) | |
freecadFile = os.path.join(os.getcwd(),"colors.FCStd") | |
baseFileName = os.path.splitext(freecadFile)[0] | |
# extract the original xml file for verification later | |
OfflineRenderingUtils.extract(freecadFile,"GuiDocument.xml",os.path.join(os.path.dirname(freecadFile),"GuiDocument.xml")) | |
# open FreeCAD file | |
doc = FreeCAD.open(freecadFile) | |
# build color dict | |
# setting nodiffuse=True (optional) discards per-face colors, and only sets one color per object | |
# only the STEP exporter accepts per-face colors. The others would consider the first color in the per-face colors list as | |
# the object color, which might be not what we want, so it's best to turn it off here. | |
colors = OfflineRenderingUtils.getColors(freecadFile,nodiffuse=True) | |
# get the camera data from the file (used in some functions below) | |
camera = OfflineRenderingUtils.getCamera(freecadFile) | |
# export to OBJ | |
importOBJ.export(doc.Objects,baseFileName+".obj",colors=colors) | |
# export to DAE | |
importDAE.export(doc.Objects,baseFileName+".dae",colors=colors) | |
# export to IFC | |
importIFC.export(doc.Objects,baseFileName+".ifc",colors=colors) | |
# export to WebGL | |
importWebGL.export(doc.Objects,baseFileName+".html",colors=colors,camera=camera) | |
# export to STEP | |
# The STEP exporter accepts different kind of data than the above | |
# exporters. Use the function below to reformat it the proper way | |
stepdata = OfflineRenderingUtils.getStepData(doc.Objects,colors) | |
Import.export(stepdata,baseFileName+".stp") | |
# export to PNG | |
scene = OfflineRenderingUtils.buildScene(doc.Objects,colors) | |
OfflineRenderingUtils.render(baseFileName+".png",scene,camera,width=800,height=600) | |
# view the scene in a standalone coin viewer (optional, just for fun) | |
#OfflineRenderingUtils.viewer(scene) | |
# file saving with a color dictionary | |
OfflineRenderingUtils.save(doc,filename=baseFileName+"_nochange.FCStd",colors=colors,camera=camera) | |
# file saving reusing a full GuiDocument dictionary | |
guidata = OfflineRenderingUtils.getGuiData(freecadFile) | |
# let's the colros of the "Cube" object to yellow | |
cubecolors = guidata["Cube"]["DiffuseColor"]["value"] | |
cubecolors = [(1.0,1.0,0.0) for color in cubecolors] | |
guidata["Cube"]["DiffuseColor"]["value"] = cubecolors | |
# also change ShapeColor because the test below will discard diffuse colors | |
guidata["Cube"]["ShapeColor"]["value"] = (1.0,1.0,0.0) | |
# save the file | |
changedFile = baseFileName+"_changed.FCStd" | |
OfflineRenderingUtils.save(doc,filename=changedFile,guidata=guidata) | |
# make another PNG to check the changed color | |
colors = OfflineRenderingUtils.getColors(changedFile,nodiffuse=True) | |
scene = OfflineRenderingUtils.buildScene(doc.Objects,colors) | |
OfflineRenderingUtils.render(baseFileName+"_changed.png",scene,camera,width=800,height=600) | |
# extract the modified xml file for verification later | |
OfflineRenderingUtils.extract(changedFile,"GuiDocument.xml",os.path.join(os.path.dirname(changedFile),"GuiDocument_changed.xml")) | |
# create diff between the two xml files | |
os.system("diff GuiDocument.xml GuiDocument_changed.xml > changed.diff") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment