Vizard 7 » Tutorials & Examples » Example scripts » Render Nodes » Planar reflection
7.6

Planar reflection

\examples\renderNodes\renderNodePlanarReflection.py

This script shows how to create a mirror using render nodes.

"""
This script demonstrates how use render nodes
to peform realtime planar surface reflections.
One of the paintings in the gallery is replaced
with a reflective quad.
The viewpoint is represented by an avatar.
"""
import viz
import steve

viz.go()
viz.fov(60)

import vizinfo
vizinfo.InfoPanel()

def addReflection(node, mat=None, eye=viz.BOTH_EYE, resolution=[1024,1024]):

    #If reflection matrix is not specifed, use matrix of node object
    if mat is None:
        mat = node.getMatrix()

    #Position of node
    pos = viz.Vector(mat.getPosition())

    #Direction node is pointing
    dir = viz.Vector(mat.getForward())
    dir.normalize()

    #Quaternion rotation of node
    quat = mat.getQuat()

    #Create render texture
    tex = viz.addRenderTexture()

    #Create render node for rendering reflection
    lens = viz.addRenderNode(size=resolution)
    lens.attachTexture(tex)
    lens.setInheritView(True,viz.POST_MULT)
    #lens.disable(viz.CULL_FACE,op=viz.OP_OVERRIDE)
    lens.enable(viz.FLIP_POLYGON_ORDER,op=viz.OP_OVERRIDE)
    lens.renderToEye(eye)
    node.renderToEye(eye)
    node.renderToAllRenderNodesExcept([lens])

    #Setup reflection matrix
    rot = viz.Matrix.quat(quat)
    invRot = rot.inverse()
    lens.setMatrix(viz.Matrix.translate(-pos)*invRot*viz.Matrix.scale(1,1,-1)*rot*viz.Matrix.translate(pos))

    #Setup reflection clip plane
    s = viz.sign(viz.Vector(dir) * viz.Vector(pos))
    plane = vizmat.Plane(pos=pos,normal=dir)
    dist = plane.distance([0,0,0])
    lens.clipPlane([dir[0],dir[1],dir[2],s*dist-0.01])

    #Project reflection texture onto node
    node.texture(tex)
    node.texGen(viz.TEXGEN_PROJECT_EYE)

    return lens

# Add gallery environment
gallery = viz.add('gallery.osgb')

# Position/scale for quad to replace starry night
bb = gallery.getBoundingBox(node='painting_starry-night')
scale = [bb.size[0],bb.size[1],1.0]
pos = bb.center
pos[2] -= (bb.size[2] * 0.5) + 0.01

# Create reflection for left eye
leftEyeQuad = viz.addTexQuad(scale=scale, pos=pos, euler=(180,0,0))
leftEyeQuad.disable(viz.LIGHTING)
addReflection(leftEyeQuad,eye=viz.LEFT_EYE)

# Create reflection for right eye
rightEyeQuad = viz.addTexQuad(scale=scale, pos=pos, euler=(180,0,0))
rightEyeQuad.disable(viz.LIGHTING)
addReflection(rightEyeQuad,eye=viz.RIGHT_EYE)

# Add avatar to represent self
avatar = steve.Steve()
avatar.setTracker(viz.MainView)
avatar.renderToAllRenderNodes(excludeMainPass=True)