Changing a 3D object's skin/ material with button press


#1

Hey there,

I know this is probably super simple, but my knowledge with scripting/ TypeScript is pretty minimal - so any pointers in the right direction would be really handy!

Essentially I have a simple cube (for now) which is just a 3D object with a UV mapped texture from Blender. I’d really like to be able to cycle through a variety of other textures by either tapping on the cube or a separate button.

I’ve had a look at the two posts:


and

They both look like they should be relevant to me but I’m not sure how I might use a pointerdown script on a button to change the skin of the cube symbol/ material. (Or if that’s even the way to go!)


Global variable scope
Getting a variable value from a different object?
#2

Hi Sophie,

What you could do is create two separate buttons (one for each texture).

In each button’s ‘pointerDown’ script you’d create a reference to the cube by dragging it into the script before the main function and selecting ‘Insert local variable’, like so:

You’d also want to create a variable for your image texture in the same way.

Then, in the actual 'pointerDown’ function, you can then change the cube’s skin to a new image texture.

The following docs page explains how to do this:

Also, if you’re unfamiliar with scripting, I’d suggest having a look at these pages on our docs, as they’ll be very handy:

If you run into any issues, you can always send us an email at support@zappar.com.

Hope this helps,
Seb


#3

Hey again Seb, thanks for the reply!

I think I largely understand how to insert local variables, it’s just getting them to interact once they’re all in the script.

You mentioned a docs page but then didn’t quite link it, I had another hunt around the site and came across some pages for skin and materials, but also this: https://docs.zap.works/studio/scripting/reference/imagetexture/ where the example points out largely what I’d like to do.

The issue I seem to be repeatedly getting is "Property X does not exist on type ‘root__Cube__sym’

ZapparStudio"


#4

Hi again Sophie,

My apologies for not sending that link through.

You’re very close to the correct implementation, it looks like there’s just one change that needs to be made

Instead of using 'myObject.materials’, you should use 'myObject.skin’, and then pass through the texture file as an argument like so:

myObject.skin (myTexture);

This should give you the functionality you’re looking for.

As a side note, I can see that you’re using an older version of Studio. We recently released an updated version, which you can download at the link below:

https://my.zap.works/studio/

Thanks,
Seb


#5

Thanks for all of this direct help!

Have updated Studio to the latest version… No luck on changing to ‘myObject.skin’ however, the editor insists that there’s no such thing on ‘root__Cube__sym’


#6

Very strange, could you send your project’s zpp file over to support@zappar.com please?

I can have a look at it and reply to you through there.

Thanks,
Seb


Blocked message on App
#7

Hi Sophie,

I’ve created an example zpp file, to show how you can go about doing this.

I figured it could benefit others so I’ve posted it on here instead, if you don’t mind.

Firstly, there’s a couple of things to note:

  • I’ve used a pod file, rather than an obj or fbx, but it should work with either.
  • The shading effect on the model was done manually by using a photo editor on the object’s UV map. It is not a result of dynamic lighting within Studio.

Now, for the actual steps.

  1. Import your 3D model to your scene, and double click on the resulting symbol in the 'Symbol Definitions’ panel.

image

  1. Import the texture files you’ll be using by dragging them into the 3D symbol’s 'Media Library’ panel.

image

  1. In the hierarchy, right click the 3D model’s node and select ‘New > Script > blank’.

image

  1. At the top of the script, create references for the texture files you want the object to switch between.
    Do this by creating a new ‘Z.ImageTexture’ object, and passing in the texture file’s name as the argument. E.g. ‘var newImageTexture = Z.ImageTexture (“myTextureFile”);

  2. Below the variables, create a new function and use the parent object’s ‘.skin’ function to change the object’s texture, passing in a previously created ‘Z.ImageTexture’ as the argument.
    E.g. ‘export function myTextureChangeFunction() {
    parent.skin (newImageTexture)}

    Create a new function for each texture file you’d like to apply to the model.

  • Remember to use the ‘export’ keyword before the function’s declaration so that we can call them from the parent symbol (more on this later).

image

  1. That’s all within the 3D model’s subsymbol, so head back to the parent symbol. Create an instance of the 3D object by dragging it into the ‘Hierarchy’ from the ‘Symbol Definitions’ panel.

image

  • For purposes of this demo, I’ve created a simple button by dragging in a ‘Plane’ from the ‘Media Library’ and adding a ‘pointerdown’ script to it, but feel free to add the following code to your own button.
  1. At the top of the script, create a new variable that references the 3D object’s instance by dragging the instance’s node in the hierarchy to the script, and selecting ‘Insert local variable’.

AddObjectRef

  1. Finally, we can use the variable we’ve just created to access and call the function that we coded within the 3D model’s symbol. E.g. ‘myVariable.nodes.myScript.myTextureChangeFunction();

image

  • If we hadn’t used the ‘export’ keyword before when declaring our function, we would be able to access the script, but not call the function.
    Without that keyword, the function only has ‘local’ scope, but by using ‘export’ we ensure it has ‘global’ scope, so that it can be called from its parent symbol.
    There’s a helpful docs page with more info on subsymbol communication:
    https://docs.zap.works/studio/subsymbols/subsymbol-communication/

I’ve attached this example project’s zpp file for anyone who’d like to have a closer look at how it works.

Change3DModelTexture.zpp (236.4 KB)

Edit: I’ve uploaded the assets used in the example, here’s the link.

https://drive.google.com/open?id=1zw7FWJIvcIA2t5vonUV-GAHXQ4BFON3I

Hope this proves helpful to some of you.
Seb


#8

Thank you Seb!!!


#9

Hello Seb, I test it and is a fantastic way of changing the “DiffuseMap” or main texture.
Is there a function to change “Normal Map”, “Ambient Map”,… and so on? also to change Material?
I look at normalMap(…) but I couldn’t realice how to do it.

Do you know how to do it?

Thank you in advance!!!


#10

Hi @joseluis.navarro,

Something like this should work -

This will update the main_mat materials diffuseMap with the image taken from the Media Library upon runtime.

Hope this helps.

George


#11

Thank you George!!