Home › Forums › Programming › Replacing the non-primary material on a multi-material object
- This topic has 2 replies, 2 voices, and was last updated 3 years, 11 months ago by jem.
-
AuthorPosts
-
2020-12-12 at 6:20 pm #36440jemCustomer
I need to replace the non-primary material on a multi-material object. The replace material puzzle will only replace the first material in an object. I think that I have a reasonable solution, but I would like someone with more v3d API experience to critique my code. Here is the solution that I put together
function prepareExternalInterface(app) { app.ExternalInterface.replaceMaterialByName = function (oldMatName, newMatName, objName) { v3d.apps[0].scene.getObjectByName(objName).traverse(child => { if (child.material) { console.log(child.material.name); if (child.material.name === oldMatName) { console.log("replacing " + oldMatName + " with " + newMatName + " on " + child.name); child.material = v3d.SceneUtils.getMaterialsByName(v3d.apps[0], newMatName)[0]; } } }); } }
Is there a better way to do this? Also, I did not .clone() the new material before applying it to the target object. In some of the three.js examples that I found, the authors would clone the material before assigning the clone to the object. Is this necessary?
This code is in my prepareExternalInterface(). I am using “v3d.apps[0]” to obtain a reference to the current 3d app. This assumes that there is only one 3d app on the page (which might not be true). Is there a more robust way to obtain the handle of the current 3d app?
Thanks!Attachments:
You must be logged in to view attached files.Jeremy Wernick
2020-12-13 at 7:23 am #36452Alexander KovelenovStaffHi Jeremy,
You code is OK, but you can simplify it a bit as well as fix possible issue with several apps with this code by using this code:
app.ExternalInterface.replaceMaterialByName = function (oldMatName, newMatName, objName) { app.scene.getObjectByName(objName).traverse(child => { if (child.material) { console.log(child.material.name); if (child.material.name === oldMatName) { console.log("replacing " + oldMatName + " with " + newMatName + " on " + child.name); child.material = v3d.SceneUtils.getMaterialsByName(app, newMatName)[0]; } } }); }
Cloning you materials is not required, it’s used to fix possible issues when you modify your material or mesh, e.g cases with changing color, node material animation, morphing etc.
2020-12-14 at 6:53 pm #36493jemCustomerHi Alexander,
Thank you for the suggestions and improvements!
I may try to implement this code as a puzzle piece using the new functionality in 3.6.Jeremy Wernick
-
AuthorPosts
- You must be logged in to reply to this topic.