Forum

Change Texture for multiple Objects via Script

14 January 2019 14:41
Hello everyone and good evening,

i have i small task to do and need some help.
I hope i can explain it well.

I want to make five buttons with html.
With these five buttons i want to change the texture of the Objects. All Objects have the same Material and the same Texture. So one Texture have to be changed. There are five different types of textures.

I guess it is a Switch scripted for Javascript, but i dont know how to start. Does anybody have some Informations for me? Maybe some Code-Example?
That would be very nice :)

Maybe this Tutorial will help to define my question.
link
Here it made with blender internal buttons (Objects).

Also my Project Data(It does not work with my Code):
my_project_cube.zip


I want HTML buttons
Have a nice day.
Kind regards,

Bani
14 January 2019 16:05
Kind regards,

Bani
14 January 2019 23:37
The method is called m_textures.replace_image().

I've uploaded an example which is the same as our previous discussion, but the HTML now switches textures instead of show/hide.

LINK

Source:
<!DOCTYPE html>

<html>

<head>

<title>my_texture_switch</title>

<meta charset="utf-8">

<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">

<link type="text/css" rel="stylesheet" href="my_texture_switch.min.css?v=14012019204142">

<script type="text/javascript" src="./b4w.simple.min.js?v=14012019204142"></script>

<script type="text/javascript" src="my_texture_switch.min.js?v=14012019204142"></script>

<script>

var objects = ["Cylinder","Cone","Sphere","Cube","Torus"];

var textures = ["t1.jpg","t2.jpg","t3.jpg","t4.jpg","t5.jpg"];

var img = [];

var m_scs = b4w.require("scenes");
var m_tex = b4w.require("textures");

function preload_images() {
  for (var i in textures) {
    img.push(new Image());
    img[i].onload = function() {
      console.log("image file successfully preloaded");
    }
    img[i].src = "assets/"+textures[i];
  }
}

function switch_texture(n) {
  for (var i in objects) {
    m_tex.replace_image(m_scs.get_object_by_name(objects[i]), "My_Texture", img[n]);
  }
}

</script>

</head>

<body onload="preload_images()">

<div id="main_canvas_container"></div>

<button onclick="switch_texture(0)" type="button" style="position:absolute;left:10px;top:10px">Gray Bricks</button>
<button onclick="switch_texture(1)" type="button" style="position:absolute;left:10px;top:40px">Blue Cross</button>
<button onclick="switch_texture(2)" type="button" style="position:absolute;left:10px;top:70px">Green Diamonds</button>
<button onclick="switch_texture(3)" type="button" style="position:absolute;left:10px;top:100px">Yellow Flowers</button>
<button onclick="switch_texture(4)" type="button" style="position:absolute;left:10px;top:130px">Red Tartan</button>
</body>
</html>


I used a very simple node material. The texture name must be the same as in the script (in this case it's "My_Texture"):

14 January 2019 23:40
Wow Blend4Life,

that helps me a lot.
So in the same procedure i can also change the Material, if i would?
Kind regards,

Bani
15 January 2019 00:04
It's a bit different because if you change a material, you would usually use m_material.inherit_material(), and then you need to name a "source object" from which to copy the material.

With replace_image, there is no source, you only state the target object. Also, the image is replaced ONLY for the target object even if all the other objects have the same material. This is very unintuitive because if you change the image in Blender, of course all the objects instantly update to the new image (because they all share the same material).

You can test this for yourself if you change the line
m_tex.replace_image(m_scs.get_object_by_name(objects[i]), "My_Texture", img[n]);
to
m_tex.replace_image(m_scs.get_object_by_name(objects[2]), "My_Texture", img[n]);
Now if you press the buttons, only the center object switches. This is not possible in Blender without having separate materials for every object.
15 January 2019 12:19
So i did it today and it works fine to me :D Thank you very much Blend4Life!!!!
Now i have the next Task to do:

The replaced Images should be changed, with custom, uploaded Images.
I think, the Source Path should be changed dynamically. How can i do that, with updating the Texture?
Kind regards,

Bani
15 January 2019 21:28
Well, depending on how you manage your upload, you either have a direct reference to the image (data) itself or you have a source path to an image file. In the former case, you just say
m_tex.replace_image(your_object_reference, "your_texture_name", your_image_reference);
and in the latter case, you do
var your_image = new Image();
your_image.onload = function() {
  m_tex.replace_image(your_object_reference, "your_texture_name", your_image);
}
your_image.src = "your_path_and_filename";
16 January 2019 09:36
Hey, thank you.
I will try it out later.

Here is a post with an example i made yesterday:

testingcanvas.zip
Kind regards,

Bani
16 January 2019 19:07
Hey Blend4life,

here is an Exampleproject:

my_Upload_Project.zip

This is the way i programmed the Upload. But specially i only want to change the sourcepath and the updating texture on the 3d Modell.
Later i will try to put some extra materials over the normal material node… but that is for the future.
I just simply want to have the possibillity, to change the Texture via runtime.
Kind regards,

Bani
16 January 2019 21:47
OK, this project is very messy and produces console errors.

- You should not use spaces and uppercase characters in file or project names.
- You should use proper indentation and syntax.
- You insert HTML before the body tag.
- You execute the same code twice, both in the HTML and in my_Upload_Project_2.js.
- You load my_Upload_Project_2.js twice, in the HTML head and body.
- You are confused about local and global scope, and you try to attach Event Handlers before the document is loaded, producing errors.

Also, if you want to manipulate objects dynamically in any way (that includes changing materials and textures), you must always set them to Dynamic Geometry & Materials in Blender under their Object Tab.

I attached a version where I removed the basic errors and inserted the code that puts the texture on the cube (in the FileReader's onload function, i.e. after the user's upload has finished loading):
  var filereader = new FileReader();
  filereader.onload = function(e) { 
    target.src = this.result;
    var m_scs = b4w.require("scenes");
    var m_tex = b4w.require("textures");
    m_tex.replace_image(m_scs.get_object_by_name("cube"), "logo", target);
  };
 
Please register or log in to leave a reply.