You are currently browsing the tag archive for the ‘llSetTexture’ tag.

As with all my script posts, I am assuming here that you already know the basics of how to create and edit prims and scripts.

I’ve already covered the rotation option for animating textures, in my post about creating a simple rippling water texture. In this post, however, I want to look at the other animation options, and give some examples. The only one I’m not going to cover is the scaling option, which works in a similar way to the rotation option, but which I have never found a real use for.

Let’s start with what most people think of in terms of texture animations, which is where the animation displays a series of ‘frames’. As a simple example, here is an alternative way of creating a rippling water effect, this time using an animation. To see this in action, rez a cube, and create a new script for it. Replace the contents of the script with the following:

default
{
 state_entry()
 {
  llSetTexture("349b2fec-0f7e-bd5f-5bcc-7090d27ae0fb", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP, ALL_SIDES, 3, 3, 1, 9, 12.0);
 }
}

As with all the examples in this post, I am taking the textures from the asset server using their UUID, so they should be available to anyone. Of course, you don’t have to do it this way – you can apply animated textures to the prim in the normal way if you want (in which case you can remove the llSetTexture call in the above example).

The texture in this example is 128 x 128, and has the frames laid out in a 3 x 3 grid (the texture was created using the Gimp drawing package). It is actually rather smaller than is necessary, and hence not very high quality. A 256 x 256 version of the texture would be better quality, and would still load reasonably quickly.

Let’s look at each of the parameters of the llSetTextureAnim function.

The first parameter is a set of flags which are combined together using an OR (the ‘|’ symbol). In my example, only two options are included: ANIM_ON, which switches the animation on (no surprise there!) and the LOOP option, which tells the animation to return to the beginning and start again once it has reached the last frame. The alternative to LOOP is PING-PONG, which still keeps the animation running continuously, but when it reaches the last frame it then plays the frames in reverse until it gets back to the first frame, and so on.

If you don’t specify one or other of LOOP or PING-PONG the animation will play through just once and then stop (it will redisplay the first frame, though). We’ll see a possible use for this later.

The other possible flags for this parameter are SCALE, ROTATE, REVERSE, and SMOOTH. As I said above, I won’t be going in to SCALE and ROTATE in this post. REVERSE simply plays the animation backwards. I’ll come back to the SMOOTH option later.

The next two parameters tell the function how the frames are laid out in the texture. In my example, they are laid out in a 3 x 3 grid, so we set both values to 3. A common alternative would be to have the frames laid out horizontally in a long strip. If this sample texture had been done that way we would have had a strip 9 frames long, so these parameters would be 1, 9.

The next two parameters tell the function which frames to display, from the first frame to the last frame. You can use this if you only want to display part of the animation (possibly you might want to display different parts at different times). In this case we want to use all the frames.

The last parameter is the speed of the animation — the higher the number, the faster the animation. It is approximately (very approximately!) in frames per second, and values between 5 and 15 are usually appropriate, though of course this depends on your animation.

Now, what about that SMOOTH option? Well, this works in a rather different way. Instead of displaying individual frame, the SMOOTH option basically scrolls the entire texture sideways. Because of this, it is possible to use this to scroll a texture which isn’t animated (in other words, a texture which isn’t actually a series of frames).

As an example, let’s create a slowly drifting starfield. Rez a cube, and size it so that it is about 4 m wide and 2 m tall. Create a new script in it, and replace the script contents with the following:

default
{
 state_entry()
 {
  llSetTexture("43019701-cf5c-d484-3b35-3fb59fe895b4", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, 1, 2, 1, 1, 0.02);
 }
}

Notice that although the texture is not animated, we have specified a Y frame count of 2. This might seem rather odd, and needs some explanation. As soon as you apply llSetTextureAnim, the script will override whatever X and Y repeat values that you have specified, and instead will size the texture to match the X and Y frame count that you have specified, stretching it as necessary.

In order to make the texture fill the X direction without stretching, the Y frame-count has been specified as 2, making the script treat the texture as a two-frame animation. Because the start and end frames are both 1, it only displays one frame, which in this case works out as the top half of the texture, with the result that the texture is scaled correctly for us. This is not really an efficient way of doing things! Really, an animated texture needs to have the same X:Y ratio as the prim face that you are going to use it on.

Next, something more useful. Let’s see how to use texture animation with Second Life’s waterfall textures, and create a simple waterfall.

Start by rezzing a cube, and size it so that it is 2 m wide, 4 m tall, and 0.2 m deep. On the Texture tab, set the rotation to 90.0. This is because animations which use SMOOTH, as we are going to do, always slide along the X axis, so we need to rotate the texture to make our water flow vertically.

Create a new script in it, and replace the script contents with the following:

default
{
 state_entry()
 {
  llSetTexture("af8c86bd-c377-c331-7476-58abeb7af8fc", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, 1, 2, 1, 1, 0.5);
 }
}

By itself, this should look reasonably effective. We can make it better, though. Take a copy of this prim, shifting it so that it is a little bit in front of the original prim. Edit the script in this copy, and replace it with the following:

default
{
 state_entry()
 {
  llSetTexture("49649c94-f720-6d0f-2246-49cc1835284f", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, 1, 2, 1, 1, 0.25);
 }
}

This now gives us two waterfall animations, running at different speeds. The result is very effective.

Near the start of this post I mentioned that if you had neither LOOP nor PING-PONG in the animation flags the animation would run through just once. Here is an example of this. It is a ‘LOCKED’ sign which flashes once when somebody touches it.

Rez a new cube, and size it to be 1 m wide, 0.5 m tall, and 0.5 m deep. Create a new script in it, and replace the script contents with the following:

default
{
 state_entry()
 {
  llSetTexture("7392be5b-ce2f-eb64-6a45-a4544ec539a9", ALL_SIDES);
  llSetTextureAnim(ANIM_ON, ALL_SIDES, 1, 2, 1, 2, 5.0);
 }
 touch_start(integer total_number)
 {
  // Curiously, we have to switch the animation off first.
  llSetTextureAnim(0, ALL_SIDES, 1, 2, 1, 2, 0.0);
  // Now run the animation once.
  llSetTextureAnim(ANIM_ON, ALL_SIDES, 1, 2, 1, 2, 5.0);
 }
}

Finally, some useful (I hope!) notes:

Finding the prim face: You’ll notice that in the above scripts I have specified ALL_SIDES as the side to apply the texture and animation. A lot of the time you will want to put the texture and animation on one side only. The easiest way to find out the side number of a prim face is to use the Advanced (or Debug) menu.

To active or deactivate the menu, hold down CTRL+ALT+d on your keyboard. The Advanced menu should appear on the main Second Life menu.

Once this menu is showing, edit the prim you want to investigate. Click the ‘Select Texture’ option, and select the face you want to check. Then hold down CTRL+SHIFT+ALT+t on your keyboard. Details of the texture will appear in the bottom-left of your screen, including the face number.

Switching off animations: If you want to switch off the animation on a texture, simply pass zero as the flag. The other parameters are irrelevant:

llSetTextureAnim(0, ALL_SIDES, 1, 1, 1, 1, 0.0);

Texture Size: remember that a texture with multiple frames can easily be very large indeed, and Second Life still has to load the entire texture (no, it doesn’t load it frame by frame!). Creating an effective animation using a minimum number of frames is a skill in its own right.

The LSL Wiki has additional useful information: http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSetTextureAnim

Sometimes it is useful to be able to change or apply textures through a script. Imagine, for example, a button or switch where you want to change the appearance when the user clicks on it.

There are a number of functions in the LSL library for dealing with textures. In this post I will cover the most basic of them. I’ll go into more details in subsequent posts.

Applying a Texture

Applying a texture to a prim is probably the simplest thing that can be done when scripting textures. You can use the llSetTexture function to do this, which simply needs the texture, and the side to apply the texture to. I’ll discuss prim sides a bit later, but for the example I’ll use the ALL_SIDES constant, which will apply the texture to all sides of the prim.

There are two different ways of specifying the texture. You can either use the name of the texture, or you can use the asset UUID of the texture.

To use the name, the texture must be included in the prim’s contents (just drag the texture from your inventory into the contents list of the prim).

Assume we have a texture called “test”. This script will apply the texture to all sides of the prim when the prim is touched:

default
{
    touch_start(int number)
    {
        llSetTexture("test", ALL_SIDES);
    }
}

Alternatively, we can specify the asset UUID. To find the UUID, right-click on the texture in your inventory, and select the Copy Asset UUID option. You can then paste the result into the script, like so:

default
{
    touch_start(int number)
    {
        llSetTexture("3c8f1c70-671a-4cb6-9f06-58b95c77e6a6", ALL_SIDES);
    }
}

The advantage with using the UUID is that the texture does not need to be in the prim’s inventory, it only needs to exist somewhere in SL’s asset server.

Note that the asset UUID in the above code is a real one, and will get you a “test card” pattern that you can use for testing offsets (see below).

Aside: What happens if you upload a texture into your inventory, get the UUID for it, then delete the texture? Will the texture vanish from Second Life altogether? No, it won’t. Once a texture is uploaded, it is permanently added to the asset server, and deleting it from your inventory has no effect on it — you simply won’t be able to refer to it by name any longer. It will still exist on the server, and you can still use the UUID to refer to it in a script.

Sides

Suppose you want to apply a texture to just one side of a prim. To do this you simply specify the side number:

llSetTexture(“test”, 1);

Ah, but how do you know which side has which number? That’s the tricky bit. Assume that you have just rezzed a cube, and haven’t rotated it in any way. The sides will be numbered as follows:

top: 0
side with lowest y: 1
side with highest x: 2
side with highest y: 3
side with lowest x: 4
bottom: 5

If you hollow the cube, side 5 is the inside (yes, all four interior sides count as a single side), and the bottom becomes side 6.

Working out the side numbers for a rotated cube, or for a more complex prim, gets rather more difficult, and can involve a lot of trial and error. A better way is to use the debug menu. If you don’t have the debug menu displayed, press CTRL+ALT+D to reveal it.

To get information about one side of a prim, tick the ‘Select Texture’ option in the build dialog, select the prim side that you want to know about, then press CTRL+SHIFT+ALT+T. Information about the prim side will be displayed, including the side number.

Scaling and Offsetting

Once a texture is applied, you can scale and offset it using the llScaleTexture and llOffsetTexture functions.

llScaleTexture(0.5, 2.0, ALL_SIDES);

llOffsetTexture(0.5, 0.0, ALL_SIDES);

The horizontal and vertical parameters taken by these functions are exactly the same as those on the texture tab of the build dialog, so you can use the build dialog to help find the appropriate values.

If you have already worked with textures you will know that a scaling of 1.0 x 1.0 will fit the texture to the size of the prim, whereas higher values will tile the texture, and lower values will only display part of the texture.

For example, a value of 0.25 will display one quarter of the texture, stretching it to fit the prim. Which quarter of the texture is actually displayed depends on the offset, and the way in which the offset works is not immediately obvious.

Basically, the offset is from the centre of the texture. An offset of 0.0 x 0.0 will therefore centre the texture. How other offset values affect the texture is easier to explain using an actual example.

Here is the testcard texture which I mentioned above, applied initially with an offset of 0.0 x 0.0:

Test Card example 1

If you change the horizontal offset to 0.25 you get this:

Test Card example 2

Try changing the horizontal scaling to 0.25, and the horizontal offset to 0.0. This produces the following, which is actually displaying the centre of the scaled texture, showing half of one band of colour, and half of the other.

Test Card example 3

To offset it so that we are centred in a band of colour, we need to use an offset of 1/8, or 0.125. Set the horizontal offset to this value, and we get a single band.

Test Card example 4

To centre each band in turn, use the following offsets:

-0.375
-0.125
0.125
0.375

Obviously, this only works when the horizontal scale is 0.25.

Using scaling and offsetting to select just one portion of a texture can help to make more efficient use of textures, especially if you have a prim which needs to sometimes change appearance — you can pack the different images into a single texture, and select the appropriate part of the texture using the scale and offset. The alternative method is to have multiple textures, but this means that when the texture is changed, there is a delay while the new texture is loaded. Using the scale and offset method, the texture is already fully loaded, and the prim changes appearance almost instantly.

I’ll cover this more in a later post.

Links

You will find a lot of useful information about the texture-handling functions on the LSL Wiki:

LSL Wiki