Posted by: Peter Quirk | December 28, 2008

Tutorial: Creating a reflecting mirror with an RTT camera

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:

Original source

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.

 Step1

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.

step2

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.

Advertisements

Responses

  1. I have repeated this tutorial to the letter many times, but keep getting the following message on the console:

    [CLIENT]: unhandled ObjectSpinStop packet

    The result is not RTT image on the object, any ideas?

  2. This error is caused by touching an object that doesn’t have a valid LSL script (e.g. compilation error) or an invalid class name in the Rex / Misc / Class Name field. Since we’re using the latter, check the following:

    1. That your mirror is really in front of the dresser’s built-in mirror surface. Check by unlinking the mirror if it is linked and moving the dresser backwards.

    2. Check that the class name is correct.
    — It must be in the samples folder.
    — It must be listed in the __init__.py script in the samples folder.
    — The method name (the part after the dot) is case-sensitive. It must match in the __init__.py file and in the Rex/Misc/Classname field.

    3. If this doesn’t help, restart Python from the Opensim console window using “python restart” command. Observe the output to see if any errors are reported as the script’s init method is invoked.

    4. When you touch the mirror, observe the opensim console window to see if there are any errors before the unhandled ObjectSpinStop packet message.

    5. One other thing – check the order in which you linked the dresser and the mirror. The mirror should be the root object.

    Hope this helps!

    — Peter

  3. I just tried this using ModRex and Opensim by
    following your instructions. I created the
    samplemirror.py file as specified and edited
    the lines previously in the samplertt.py file.
    I also added the import to the __init.py so
    that it is loaded when opensim starts.

    I am using a GreenSkin texture from the OGRE
    demos, found out the asset ID from my inventory
    for this texture, and put this in samplemirror.py
    so that it uses this texture rather than the brick
    one (which I don’t have).

    In-world, I create a random prim, put in
    the class name: samplemirror.RttCam
    I also texture map the prim in Green Skin.
    When I click on the prim, I can see that
    the python script is executing because I
    get the toggle between “Removing render
    to texture camera” and “Creating render
    to texture camera”. Nothing appears on
    the prim.

    Should I name the camera object:

    mirror_cam

    or should this be a separate object? I
    have it current named mirror_cam

  4. I have tested this procedure with modrex build 96 and Opensim build 8777. The only thing that didn’t work was restarting the Python interpreter without restarting the server. When Python restarts, it processes __init__.py correctly, but reports that it cannot find samplemirror. Shutting down and restarting the server solved the problem.

  5. […] Learn how to make the mirror reflect like a real mirror using this tutorial. Possibly related posts: (automatically generated)Taking Sketchup models into realXtendImporting […]

  6. Hello, thanks for the tutorial, which I have followed to the teeth, but still am experiencing problems with.

    When I set it all up and click the prim used my console give me:

    unhandled ObjectSpinStop package

    Any help would be very appriciated, I’ve subscribed via email, so I’ll get it :)

    Thanks again,
    Janus

  7. Hi again.

    I found that I couldn’t run any of the phyton samples in 0.4, and that the server 0.4 from the official site didn’t start the python service( ini was set right). So I downloaded the “empty” server from here: http://www.cybertechnews.org/?p=250 and it starts up with that, and I’m now able to run the sample scripts(ofcourse I didn’t check before posting the previous :) ) and to make the mirror.

    Great! Thanks for the tutorial, giving us less know with scripting a change to learn.

  8. hi, peter do you have an idea how can we hold any object in realXtend environment like we can drink a glass of water in Second life and avatar can hold it while using the function llStartAnimation (“hold_R_handgun”).
    thanks in advance


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: