Scripting: Change Texture When Avatar Enters/Exits Model Bounds


#1

I’m trying to adapt the tutorials for changing the properties of a model; however, I’m not finding the specific properties for the following.

I am trying to have a small pod change from green to red when an avatar enters, and from red to green when the avatar exits. I’m trying to do this by swapping out the textures.

  1. What is the trigger for when an avatar enters/exits a model’s bounds? For ex., the examples point to clickDownOnEntity. Is there something similar for when the avatar enters/exits a model’s bounds?

  2. Is it possible to swap out a texture on a FBX binary model? I’m used to working with DAE, which references textures and does not pack them in the model file. If so, is this something that is referenced using an entity’s properties? Or is this an appropriate approach?

I appreciate any help!


#2

You can achieve 1 by adding an entity script. For example:

var entityScript = (function () {
    this.enterEntity = function (entityID) {
        print("Enter entity");
        Entities.editEntity(entityID, {
            color: { red: 255, green: 64, blue: 64 },
        });
    };
    this.leaveEntity = function (entityID) {
        print("Leave entity");
        Entities.editEntity(entityID, {
            color: { red: 128, green: 128, blue: 128 },
        });
    };
});

var entityID = Entities.addEntity({
    type: "Sphere",
    position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
    dimensions: { x: 3, y: 3, z: 3 },
    color: { red: 128, green: 128, blue: 128 },
    collisionless: true,  // So that avatar can walk through entity.
    script: "(" + entityScript + ")"  // Could host the script on a Web server instead.
});

#3

For 2, see the entity’s “textures” and “originalTextures” properties.

originalTextures: A JSON string of texture name, URL pairs used in the model. The property value is filled in after the entity has finished rezzing (i.e., textures have loaded). You can use JSON.parse() to parse the JSON string into a JavaScript object of name, URL pairs. Read-only.

textures: A JSON string of texture name, URL pairs used when rendering the model in place of the model’s original textures. Use a texture name from the originalTextures property to override that texture. Only the texture names and URLs to be overridden need be specified; original textures are used where there are no overrides. You can use JSON.stringify() to convert a JavaScript object of name, URL pairs into a JSON string.


#4

Thank you for the response.

First, enterEntity was what I was looking for. Thanks. I’m able to detect when an avatar enters or exits a sphere or cube entity. However, I am not able to detect when an avatar enters/exits a model.

Second, I might not have been clear that I am not trying to change the color of an entity by changing its RGB values, but instead I by swapping the texture. Is it possible to swap the texture of an entity using scripting?

Thanks again.


#5

Still banging away at this.

I’ve pulled the following together. This approach works if the entity is a primitive (like a cube or sphere) and all you are trying to do is to change the color of the entity using enterEntity or leaveEntity.

However, when using the same method to trigger an event using a model, this approach does not work. When your avatar crosses the bounds of the model, no events are triggered.

Here’s the code. Any ideas why events don’t trigger?

    var podURL = "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod.fbx";

    var entityScript = (function () {
        this.enterEntity = function (entityID) {
            print("Avatar entered model");
            //For swapping out textures when I get enterEntity to trigger
            // Entities.editEntity(entityID, {
            //   textures: JSON.stringify({
            //       Texture: "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod_texture_red.png"
            //   }),
            // });
        };
        this.leaveEntity = function (entityID) {
            print("Avatar exited model");
            //For swapping out textures when I get leaveEntity to trigger
            //Entities.editEntity(entityID, {
            //   textures: JSON.stringify({
            //       Texture: "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod_texture_green.png"
            //   }),
            // });
        };
    });

    var entityID = Entities.addEntity({
        type: "Model",
        modelURL: podURL,
        shapeType: "box",
        position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -.5 })),
        // For debugging - do I have the syntax correct to override a model texture (I do)
        // textures: JSON.stringify({
        //        "Personal Pod": "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod_texture_red.png"
        //    }),
        collisionless: true,  // So that avatar can walk through entity.
        script: "(" + entityScript + ")"
    });

#6

It may be necessary to:

  1. Create a .OBJ file that defines the collision volume. Probably need to make this large enough such that the avatar’s position (i.e., hips) enters inside it when the avatar steps onto the pod.
  2. Set the model’s shapeType property to "compound".
  3. Set the model’s compoundShapeURL property to point to the .OBJ file.

#7

Thank you ctrlaltdavid for your help as we solved this problem.

You were correct in that we needed to create an OBJ file and point to that file in our script using the compoundShapURL property.

Here is a video of the working script: https://www.youtube.com/watch?v=b8kUIjAOICM

And below is the working code:

var podURL = "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod/personal_pod_2.0.fbx";
var collisionURL = "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod/personal_pod_collision_volume.obj";

var entityScript = (function () {
    this.enterEntity = function (entityID) {
        print("Avatar entered model");
        //swap texture
        Entities.editEntity(entityID, {
           textures: JSON.stringify({
               "Personal Pod": "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod/personal_pod_texture_red.png"
           }),
        });
    };
    this.leaveEntity = function (entityID) {
        print("Avatar exited model");
        //swap texture
        Entities.editEntity(entityID, {
           textures: JSON.stringify({
               "Personal Pod": "http://cechidtgames.uc.edu/virtuoso/virtuoso_assets/personal_pod/personal_pod_texture_green.png"
           }),
         });
    };
});

var entityID = Entities.addEntity({
    type: "Model",
    modelURL: podURL,
    shapeType: "compound",
    compoundShapeURL: collisionURL,
    position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -.5 })),
    collisionless: true,  // So that avatar can walk through entity.
    script: "(" + entityScript + ")"
});

#8

Wow, this solved a big problem I was having with my domain. Thanks for asking the question, and thanks, @ctrlaltdavid for your scripting expertise.


#9

In theory, it should work without an OBJ file. However, it’s a current limitation of the system that it does need one.