def createMask(): vertices = osg.Vec3Array() vertices.push_back(osg.Vec3(-0.5, -0.5, 0.0)) vertices.push_back(osg.Vec3(0.5, -0.5, 0.0)) vertices.push_back(osg.Vec3(0.5, 0.5, 0.0)) vertices.push_back(osg.Vec3(-0.5, 0.5, 0.0)) geom = osg.Geometry() geom.setVertexArray(vertices) geom.addPrimitiveSet(osg.DrawArrays(GL_QUADS, 0, 4)) geode = osg.Geode() geode.addDrawable(geom) stencil = osg.Stencil() stencil.setFunction(osg.Stencil.ALWAYS, 1, ~0u) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.REPLACE) ss = geode.getOrCreateStateSet() ss.setAttributeAndModes(stencil, osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE) ss.setAttribute(osg.ColorMask(False, False, False, False), osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE) return geode
def setupBin3(rootNode, mirror,z): #// set up the stencil ops so that only operator on this mirrors stencil value. stencil = osg.Stencil() stencil.setFunction(osg.Stencil.EQUAL,1,4294967295); stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.KEEP); #// switch off the writing to the color bit planes. colorMask = osg.ColorMask(); colorMask.setMask(False,False,False,False); #// set up depth so all writing to depth goes to maximum depth. depth = osg.Depth(); depth.setFunction(osg.Depth.ALWAYS); depth.setRange(1.0,1.0); statesetBin3 = osg.StateSet(); statesetBin3.setRenderBinDetails(3,"RenderBin"); statesetBin3.setMode(osg.GL_CULL_FACE,osg.StateAttribute.OFF); statesetBin3.setAttributeAndModes(stencil,osg.StateAttribute.ON); statesetBin3.setAttribute(colorMask); statesetBin3.setAttribute(depth); #// set up the mirror geode. geode = osg.Geode(); geode.addDrawable(mirror); geode.setStateSet(statesetBin3); rootNode.addChild(geode);
def createMirroredScene(model): #// calculate where to place the mirror according to the #// loaded models bounding sphere. bs = model.getBound(); width_factor = 1.5; height_factor = 0.3; xMin = bs._center.x-bs._radius*width_factor; xMax = bs._center.x+bs._radius*width_factor; yMin = bs._center.y-bs._radius*width_factor; yMax = bs._center.y+bs._radius*width_factor; z = bs._center.z-bs._radius*height_factor; #// create a textured, transparent node at the appropriate place. mirror = createMirrorSurface(xMin,xMax,yMin,yMax,z); rootNode = osg.MatrixTransform(); rootNode.setMatrix(osg.Matrix.rotate(toRad(45.0),1.0,0.0,0.0)); #// make sure that the global color mask exists. rootColorMask = osg.ColorMask(); rootColorMask.setMask(True,True,True,True); #// set up depth to be inherited by the rest of the scene unless #// overrideen. this is overridden in bin 3. rootDepth = osg.Depth() rootDepth.setFunction(osg.Depth.LESS); rootDepth.setRange(0.0,1.0); rootStateSet = osg.StateSet(); rootStateSet.setAttribute(rootColorMask); rootStateSet.setAttribute(rootDepth); rootNode.setStateSet(rootStateSet) #// bin1 - set up the stencil values and depth for mirror. setupBin1(rootNode,mirror,z) setupBin2(rootNode,model,z) setupBin3(rootNode,mirror,z) setupBin4(rootNode,model,z) setupBin5(rootNode,mirror,z) return rootNode;
def setupBin1(rootNode, mirror,z): #// set up the stencil ops so that the stencil buffer get set at #// the mirror plane stencil = osg.Stencil(); stencil.setFunction(osg.Stencil.ALWAYS,1,4294967295) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.REPLACE); #// switch off the writing to the color bit planes. colorMask = osg.ColorMask(); colorMask.setMask(False,False,False,False); statesetBin1 = osg.StateSet() statesetBin1.setRenderBinDetails(1,"RenderBin"); statesetBin1.setMode(osg.GL_CULL_FACE,osg.StateAttribute.OFF); statesetBin1.setAttributeAndModes(stencil,osg.StateAttribute.ON); statesetBin1.setAttribute(colorMask); #// set up the mirror geode. geode = osg.Geode(); geode.addDrawable(mirror); geode.setStateSet(statesetBin1); rootNode.addChild(geode);
def createMirroredScene(model): # calculate where to place the mirror according to the # loaded models bounding sphere. bs = model.getBound() width_factor = 1.5 height_factor = 0.3 xMin = bs.center().x()-bs.radius()*width_factor xMax = bs.center().x()+bs.radius()*width_factor yMin = bs.center().y()-bs.radius()*width_factor yMax = bs.center().y()+bs.radius()*width_factor z = bs.center().z()-bs.radius()*height_factor # create a textured, transparent node at the appropriate place. mirror = createMirrorSurface(xMin,xMax,yMin,yMax,z) rootNode = osg.MatrixTransform() rootNode.setMatrix(osg.Matrix.rotate(osg.inDegrees(45.0),1.0,0.0,0.0)) # make sure that the global color mask exists. rootColorMask = osg.ColorMask() rootColorMask.setMask(True,True,True,True) # set up depth to be inherited by the rest of the scene unless # overrideen. this is overridden in bin 3. rootDepth = osg.Depth() rootDepth.setFunction(osg.Depth.LESS) rootDepth.setRange(0.0,1.0) rootStateSet = osg.StateSet() rootStateSet.setAttribute(rootColorMask) rootStateSet.setAttribute(rootDepth) rootNode.setStateSet(rootStateSet) # bin1 - set up the stencil values and depth for mirror. # set up the stencil ops so that the stencil buffer get set at # the mirror plane stencil = osg.Stencil() stencil.setFunction(osg.Stencil.ALWAYS,1,~0u) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.REPLACE) # switch off the writing to the color bit planes. colorMask = osg.ColorMask() colorMask.setMask(False,False,False,False) statesetBin1 = osg.StateSet() statesetBin1.setRenderBinDetails(1,"RenderBin") statesetBin1.setMode(GL_CULL_FACE,osg.StateAttribute.OFF) statesetBin1.setAttributeAndModes(stencil,osg.StateAttribute.ON) statesetBin1.setAttribute(colorMask) # set up the mirror geode. geode = osg.Geode() geode.addDrawable(mirror) geode.setStateSet(statesetBin1) rootNode.addChild(geode) # bin one - draw scene without mirror or reflection, unset # stencil values where scene is infront of mirror and hence # occludes the mirror. stencil = osg.Stencil() stencil.setFunction(osg.Stencil.ALWAYS,0,~0u) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.REPLACE) statesetBin2 = osg.StateSet() statesetBin2.setRenderBinDetails(2,"RenderBin") statesetBin2.setAttributeAndModes(stencil,osg.StateAttribute.ON) groupBin2 = osg.Group() groupBin2.setStateSet(statesetBin2) groupBin2.addChild(model) rootNode.addChild(groupBin2) # bin3 - set up the depth to the furthest depth value # set up the stencil ops so that only operator on this mirrors stencil value. stencil = osg.Stencil() stencil.setFunction(osg.Stencil.EQUAL,1,~0u) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.KEEP) # switch off the writing to the color bit planes. colorMask = osg.ColorMask() colorMask.setMask(False,False,False,False) # set up depth so all writing to depth goes to maximum depth. depth = osg.Depth() depth.setFunction(osg.Depth.ALWAYS) depth.setRange(1.0,1.0) statesetBin3 = osg.StateSet() statesetBin3.setRenderBinDetails(3,"RenderBin") statesetBin3.setMode(GL_CULL_FACE,osg.StateAttribute.OFF) statesetBin3.setAttributeAndModes(stencil,osg.StateAttribute.ON) statesetBin3.setAttribute(colorMask) statesetBin3.setAttribute(depth) # set up the mirror geode. geode = osg.Geode() geode.addDrawable(mirror) geode.setStateSet(statesetBin3) rootNode.addChild(geode) # bin4 - draw the reflection. # now create the 'reflection' of the loaded model by applying # create a Transform which flips the loaded model about the z axis # relative to the mirror node, the loadedModel is added to the # Transform so now appears twice in the scene, but is shared so there # is negligable memory overhead. Also use an osg.StateSet # attached to the Transform to override the face culling on the subgraph # to prevert an 'inside' out view of the reflected model. # set up the stencil ops so that only operator on this mirrors stencil value. # this clip plane removes any of the scene which when mirror would # poke through the mirror. However, this clip plane should really # flip sides once the eye point goes to the back of the mirror... clipplane = osg.ClipPlane() clipplane.setClipPlane(0.0,0.0,-1.0,z) clipplane.setClipPlaneNum(0) clipNode = osg.ClipNode() clipNode.addClipPlane(clipplane) dstate = clipNode.getOrCreateStateSet() dstate.setRenderBinDetails(4,"RenderBin") dstate.setMode(GL_CULL_FACE,osg.StateAttribute.OVERRIDE|osg.StateAttribute.OFF) stencil = osg.Stencil() stencil.setFunction(osg.Stencil.EQUAL,1,~0u) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.KEEP) dstate.setAttributeAndModes(stencil,osg.StateAttribute.ON) reverseMatrix = osg.MatrixTransform() reverseMatrix.setStateSet(dstate) reverseMatrix.preMult(osg.Matrix.translate(0.0,0.0,-z)* osg.Matrix.scale(1.0,1.0,-1.0)* osg.Matrix.translate(0.0,0.0,z)) reverseMatrix.addChild(model) clipNode.addChild(reverseMatrix) rootNode.addChild(clipNode) # bin5 - draw the textured mirror and blend it with the reflection. # set up depth so all writing to depth goes to maximum depth. depth = osg.Depth() depth.setFunction(osg.Depth.ALWAYS) stencil = osg.Stencil() stencil.setFunction(osg.Stencil.EQUAL,1,~0u) stencil.setOperation(osg.Stencil.KEEP, osg.Stencil.KEEP, osg.Stencil.ZERO) # set up additive blending. trans = osg.BlendFunc() trans.setFunction(osg.BlendFunc.ONE,osg.BlendFunc.ONE) statesetBin5 = createMirrorTexturedState("Images/tank.rgb") statesetBin5.setRenderBinDetails(5,"RenderBin") statesetBin5.setMode(GL_CULL_FACE,osg.StateAttribute.OFF) statesetBin5.setAttributeAndModes(stencil,osg.StateAttribute.ON) statesetBin5.setAttributeAndModes(trans,osg.StateAttribute.ON) statesetBin5.setAttribute(depth) # set up the mirror geode. geode = osg.Geode() geode.addDrawable(mirror) geode.setStateSet(statesetBin5) rootNode.addChild(geode)