Skip to content

Commit

Permalink
Arch: Improvements to OfflineRenderingUtils (ability to generate shad…
Browse files Browse the repository at this point in the history
…ows)
  • Loading branch information
yorikvanhavre committed Jul 16, 2019
1 parent ff1a7fd commit ed22aad
Showing 1 changed file with 90 additions and 11 deletions.
101 changes: 90 additions & 11 deletions src/Mod/Arch/OfflineRenderingUtils.py
Expand Up @@ -155,7 +155,7 @@ def startElement(self, tag, attributes):
elif tag == "Integer":
self.currentval = int(attributes["value"])
elif tag == "String":
self.currentval = int(attributes["value"])
self.currentval = attributes["value"]
elif tag == "Float":
self.currentval = float(attributes["value"])
elif tag == "ColorList":
Expand All @@ -174,7 +174,8 @@ def startElement(self, tag, attributes):
elif isinstance(self.currentval,list):
self.currentval.append(attributes["value"])
elif tag == "Python":
self.currentval = (attributes["value"],attributes["encoded"],attributes["module"],attributes["class"])
if "module" in attributes:
self.currentval = (attributes["value"],attributes["encoded"],attributes["module"],attributes["class"])
elif tag == "Camera":
self.guidata["GuiCameraSettings"] = attributes["settings"]

Expand Down Expand Up @@ -289,12 +290,14 @@ def getStepData(objects,colors):
return data


def render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0)):
def render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0),lightdir=None):

"""render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0)):
"""render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0),lightdir=None):
Renders a PNG image of given width and height and background color from the given coin scene, using
the given coin camera (ortho or perspective). If zoom is True the camera will be resized to fit all
objects. The outputfile must be a file path to save a png image."""
objects. The outputfile must be a file path to save a png image. Optionally a light direction as a (x,y,z)
tuple can be given. In this case, a directional light will be added and shadows will
be turned on. This might not work with soem 3D drivers."""

# On Linux, the X server must have indirect rendering enabled in order to be able to do offline
# PNG rendering. Unfortunately, this is turned off by default on most recent distros. The easiest
Expand All @@ -313,9 +316,10 @@ def render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,bac
print("Starting offline renderer")
# build an offline scene root separator
root = coin.SoSeparator()
# add one light (mandatory)
light = coin.SoDirectionalLight()
root.addChild(light)
if not lightdir:
# add one light (mandatory)
light = coin.SoDirectionalLight()
root.addChild(light)
if not camera:
# create a default camera if none was given
camera = coin.SoPerspectiveCamera()
Expand All @@ -332,6 +336,8 @@ def render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,bac
# no scene was given, add a simple cube
cube = coin.SoCube()
root.addChild(cube)
if lightdir:
root = embedLight(root,lightdir)
vpRegion = coin.SbViewportRegion(width,height)
if zoom:
camera.viewAll(root,vpRegion)
Expand Down Expand Up @@ -416,9 +422,13 @@ def getCoinCamera(camerastring):



def viewer(scene=None,background=(1.0,1.0,1.0)):
def viewer(scene=None,background=(1.0,1.0,1.0),lightdir=None):

"""viewer(scene=None,background=(1.0,1.0,1.0)): starts a standalone coin viewer with the contents of the given scene"""
"""viewer(scene=None,background=(1.0,1.0,1.0),lightdir=None): starts
a standalone coin viewer with the contents of the given scene. You can
give a background color, and optionally a light direction as a (x,y,z)
tuple. In this case, a directional light will be added and shadows will
be turned on. This might not work with soem 3D drivers."""

# Initialize Coin. This returns a main window to use
from pivy import sogui
Expand All @@ -438,6 +448,9 @@ def viewer(scene=None,background=(1.0,1.0,1.0)):
scene.addChild(mat)
scene.addChild(coin.SoCone())

if lightdir:
scene = embedLight(scene,lightdir)

# ref the scene so it doesn't get garbage-collected
scene.ref()

Expand All @@ -454,6 +467,44 @@ def viewer(scene=None,background=(1.0,1.0,1.0)):



def embedLight(scene,lightdir):

"""embedLight(scene,lightdir): embeds a given coin node
inside a shadow group with directional light with the
given direction (x,y,z) tuple. Returns the final coin node"""

from pivy import coin

# buggy - no SoShadowGroup in pivy?
#sgroup = coin.SoShadowGroup()
#sgroup.quality = 1
#sgroup.precision = 1
#slight = SoShadowDirectionalLight()
#slight.direction = lightdir
#slight.intensity = 20.0

buf = """
#Inventor V2.1 ascii
ShadowGroup {
quality 1
precision 1
ShadowDirectionalLight {
direction """+str(lightdir[0])+" "+str(lightdir[1])+" "+str(lightdir[2])+"""
intensity 200.0
# enable this to reduce the shadow view distance
# maxShadowDistance 200
}
}"""

inp = coin.SoInput()
inp.setBuffer(buf)
sgroup = coin.SoDB.readAll(inp)

sgroup.addChild(scene)
return sgroup



def save(document,filename=None,guidata=None,colors=None,camera=None):

"""save(document,filename=None,guidata=None,colors=None,camera=None): Saves the current document. If no filename
Expand Down Expand Up @@ -737,7 +788,7 @@ def getViewProviderClass(obj):
def extract(filename,inputpath,outputpath=None):

"""extract(filename,inputpath,outputpath=None): extracts 'inputpath' which is a filename
stored in infile (a FreeCAD or zip file). If outputpath is given, the file is saved as outputpath and
stored in filename (a FreeCAD or zip file). If outputpath is given, the file is saved as outputpath and
nothing is returned. If not, the contents of the inputfile are returned and nothing is saved."""

zdoc = zipfile.ZipFile(filename)
Expand All @@ -757,4 +808,32 @@ def extract(filename,inputpath,outputpath=None):
else:
return data



def openiv(filename):

"""openiv(filename): opens an .iv file and returns a coin node from it"""

f = open(filename,"r")
buf = f.read()
f.close()
inp = coin.SoInput()
inp.setBuffer(buf)
node = coin.SoDB.readAll(inp)
return node



def saveiv(scene,filename):

"""saveiv(scene,filename): saves an .iv file with the contents of the given coin node"""

wa=coin.SoWriteAction()
wa.getOutput().openFile(filename)
wa.getOutput().setBinary(False)
wa.apply(sc)
wa.getOutput().closeFile()



## @}

0 comments on commit ed22aad

Please sign in to comment.