RealXtend 0.4 includes a new feature from Ogre3D that renders a scene from a particular viewpoint onto a texture. Using this so-called Render-to-Texture (RTT) camera feature we can easily create a mirror for the dresser we constructed in the previous tutorial.
The only documentation available on the RTT camera at present is the sample Python script (samplertt.py) in rexserverScriptenginesPythonScriptSamples. Here’s the full code listing:
The RTT camera is implemented in the viewer. The rexRTTCameraWorld method (line 35) instructs all avatars in the region to create a camera at position pos, looking in the direction of lookat and render the scene onto any texture with the given textureId. A localized method, rexRttCamera, operates on just the agent invoking the script.
We can use this script with a few small changes to implement a mirror. First, reset the material in the mirror portion of the dresser to blank. In my case, this was the third material in the rex material panel, though the material was called 2_Metal_Corrogated_Shiny.
Next, we need to make thin prim to hold the texture. The “glass” in the dresser model is recessed into the wood, so it is possible to create a thin prim that just touches or penetrates the wooden frame. The following discussion assumes that your dresser is positioned at the south end of a room. You should build the glass prim without any rotations. Otherwise, you’ll need to code rotations in the script, and that can be painful if you’re not conversant with rotations in LSL. The dimensions of my mirror were:
X (width) 0.850m
Y (depth) 0.020m
Z (height) 0.608m
The rotations were all 0.0.
The front texture (facing my avatar) was set to 2_Metal_Corrogated_Shiny. When the mirror was carefully positioned in the frame, the effect was indistinguishable from the original design. Assign a name to the prim if you haven’t already.
Copy the samplertt.py file to samplemirror.py and make the following changes. You don’t need to shut down the server or the viewer, but you do need access to the server file system and console to do this:
1. Change line 15 to: return “samplemirror.RttCam”
2. Change line 19 to: print “samplemirror.RttCam EventCreated”
3. Change line 30 to: lookAt = pos + Vector3(0, 0.010, 0)
4. Change line 31 to: cameraName = “mirror_cam”
5. Edit line 32 by substituting the UUID of 2_Metal_Corrogated_Shiny for the UUID assigned to the textureId variable. (To get the UUID, right-click on the texture in your inventory and “Copy Asset UUID”. You can paste this into the editor in the conventional manner.)
Save the samplemirror.py file.
The lookAt parameter above is set to look at the surface of the mirror, which is half the depth in the positive Y direction from the center of the mirror prim.
Edit __init__.py in the sample directory. Add the line “import samplemirror” to the end of the file and save it.
When you alter or add a Python script, you need to restart the IronPython scripting engine. You can do this without restarting the entire server by typing “python restart” in the opensim console. (In Windows this is the DOS command window with rexserver in the title.)
Edit the glass prim and select the rex tab, Misc sub-tab. Set the class name to samplemirror.RttCam and close the editor dialog. (Note that the portion of the class name after the period must match the case of the name used in the code.)
If you’ve done everything correctly, clicking on the mirror will result in something like this – an inverted image! Clicking again will result in the default texture being displayed.
The inverted image problem is easily fixed by setting the horizontal and vertical flip options in the texture tab for the mirror.
With the basic functionality in place, there are a couple of refinements you should attempt. Firstly, if you zoom in on the reflection you will notice that the image is a little blocky due to the low resolution (caused by the 128 x 128 texture). Secondly, you should be aware that the RTT functionality is optimized for textures whose dimensions are a power of two. The mirror is rectangular. Mine has proportions of .850/.608. The texture has dimensions of 128 x 128. The Python script is coded to capture a 256 x 256 image. You could find or make a model that has mirror with better proportions (square or twice as long in one dimension as another). The approach I took was to use a square mirror (.85 x .85) and a higher resolution texture 256×256. The bottom part of the mirror is buried in the frame so it looks rectangular. I also linked the mirror and dresser, and scaled the combination up a little so that the top of my avatar’s head was just visible in the mirror. Lastly, the reflections are stronger if you have some local lights.