Horde3D http://horde3d.org/forums/ |
|
changing textures w/ h3dFindResElem/h3dSetResParamI [SOLVED] http://horde3d.org/forums/viewtopic.php?f=2&t=1110 |
Page 1 of 1 |
Author: | philipppixel [ 28.02.2010, 19:01 ] |
Post subject: | changing textures w/ h3dFindResElem/h3dSetResParamI [SOLVED] |
Hi all, I work now a little while with Horde3D and it's a great framework. But a thing I could not get working is to replace a model texture in-situ. Although I follow the instructions given here: http://www.horde3d.org/wiki/index.php5?title=Horde3D_Wiki:HOWTO and here: http://www.horde3d.org/forums/viewtopic.php?f=1&t=923, I just fail at making it work. I take this fails mainly because the API is unclear in that point, and I do calls with wrong parameters or sth. This is what I do at class creation time: Code: _modelRes = h3dAddResource(H3DResTypes::SceneGraph, "models/man/man.scene.xml", 0); //load alternative texture _tex2 = h3dAddResource(H3DResTypes::Texture, "models/man/civil02.jpg", 0); bool loaded = h3dutLoadResourcesFromDisk(::Values::CONTENT_DIR); if(! loaded) std::cout << "could not load enemy ressources" << std::endl; later then, in a certain condition, I want to exchange the texture Code: int idx = h3dFindResElem(_modelRes, H3DMatRes::SamplerElem, H3DMatRes::SampNameStr, "albedoMap"); H3DRes texRes = h3dGetResParamI(_modelRes, H3DMatRes::SamplerElem, idx, H3DMatRes::SampTexResI); std::cout << "found index " << idx << " tex2 is " << _tex2 << std::endl; //idx yields always -1 h3dSetResParamI(texRes, H3DMatRes::SamplerElem, idx, H3DMatRes::SampTexResI, _tex2); As in the code denoted, h3dFindResElem() returns always -1, which seems to state sth. like "not found". The current texture keeps the same. The EngineLog doesn't show any errors beside these, although I just don't call h3dGetResElemCount() in my code. Code: 5.794 Invalid elem in h3dGetResElemCount 5.794 Invalid elem or param in h3dGetResParamI 5.795 Invalid resource handle in h3dSetResParamI can anyone help here? Thanks in advance edit: I am using Horde3D from SF in Revision 213, which must be Version 1 Beta 4 |
Author: | Volker [ 28.02.2010, 23:33 ] |
Post subject: | Re: changing textures with h3dFindResElem and h3dSetResParamI |
Based on your variable names I guess you are querying a Material param (sampler) from a model resource. That won't work. Instead you have to specify the material resource handle. |
Author: | philipppixel [ 01.03.2010, 19:47 ] |
Post subject: | Re: changing textures with h3dFindResElem and h3dSetResParamI |
Hi Volker, thanks for the quick reply. I'm going to try that. |
Author: | philipppixel [ 01.03.2010, 21:40 ] |
Post subject: | Re: changing textures with h3dFindResElem and h3dSetResParamI |
Hi all, I just wanted to share the code that worked for me. Since Google didn't find any similar code on the interweb, I post it here for community's reference. Again: I intend to dynamically change the UV Map (aka albedo map) of the Chicago guy. If you look into the model scene definition "man.scene.xml" you will find a structure like this (I abbreviated for clarity's sake): Code: <Model name="man" geometry="models/man/man.geo" otherAttributesgohere> <!-- lots of "Join" elements here --> <Mesh name="body" lodLevel="1" material="models/man/civilian1.material.xml" otherAttributesgohere/> <Mesh name="body" material="models/man/civilian1.material.xml" otherAttributesgohere /> <Mesh name="body" lodLevel="2" material="models/man/civilian1.material.xml" otherAttributesgohere /> <Mesh name="body" lodLevel="3" material="models/man/civilian1.material.xml" otherAttributesgohere /> </Model> This is a scene model with four meshes of which I'd like to access the second one. The mash's associated material "civilian1.material.xml" looks like this (again abbreviated): Code: <Material> <Shader source="shaders/model.shader" /> <!-- here go shader flags --> <Sampler name="albedoMap" map="models/man/civil01.jpg" /> </Material> Slowly I arrive at my target ![]() So and here is what I do in my program code: Code: //earlier I load the second texture like this _tex2 = h3dAddResource(H3DResTypes::Texture, "models/man/civil02.jpg", 0); ... //get the mesh element from the scene model H3DNode mesh = h3dGetNodeChild(_model, 1); //starting at zero, access the second mesh //access the mesh's material int meshMaterial = h3dGetNodeParamI(mesh, H3DMesh::MatResI); //get the the ressource index for the UV map int idx = h3dFindResElem(meshMaterial, H3DMatRes::SamplerElem, H3DMatRes::SampNameStr, "albedoMap"); //pull the texture ressource from the material by using the found index H3DRes texRes = h3dGetResParamI(meshMaterial, H3DMatRes::SamplerElem, idx, H3DMatRes::SampTexResI); //set the 2nd texture back to the mesh material h3dSetResParamI(meshMaterial, H3DMatRes::SamplerElem, idx, H3DMatRes::SampTexResI, _tex2); Voilá, it is done. The only drawback is that all instances of that Chicago guy have now the second texture on themselves. To avoid this, cloning utilizing h3dCloneResource() is necessary, but until now I just fail to make it right. Hope this helps, cheers |
Author: | Volker [ 02.03.2010, 00:20 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI [Solved] |
Thanks for the sum up. Why is cloning the material not working? What did you do? |
Author: | philipppixel [ 02.03.2010, 08:36 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI [Solved] |
It's been a pleasure to make the sum up. I just recall to search the web for an actual example. Well, I believe that the failure to clone is again my fault, understanding the mechanics of H3D in that part. Anyways I'll post some code tonight. Perhaps I miss an important part again. cheers |
Author: | philipppixel [ 03.03.2010, 19:17 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI [Solved] |
Volker wrote: Thanks for the sum up. Why is cloning the material not working? What did you do? Hi, finally I managed to get my hands on the code again... In order to have only one Chicago guy changed (frankly, that guy needs a name. I call him... Buster) I use this Code: Quote: H3DRes modelResNew = h3dCloneResource(_modelRes, ""); std::cout << "old modelRes " << _modelRes << std::endl; std::cout << "cloned modelRes " << modelResNew << std::endl; h3dRemoveNode(_model); _model = h3dAddNodes(H3DRootNode, modelResNew); std::cout << "new model" << _model << std::endl; //overwrite member for latter access _modelRes = modelResNew; //here starts the code posted at 02.03.2010 //get the mesh element from the scene model H3DNode mesh = h3dGetNodeChild(_model, 1); //starting at zero, access the second mesh I try to clone the original Model resource since there is only one cloning method which expects an H3DRes. Then I remove the model from the world. In turn I add a new model with the changed model resource. Finally I overwrite the model resource because I may want to change it again. Then I proceed fetching the mesh as I showed in my earlier post. Nevertheless, the debug prints in the above code give the following output, which definitely explain, why my I now have no model at all anymore: Code: old modelRes 132 cloned modelRes 0 new model0 Any ideas? |
Author: | Volker [ 04.03.2010, 10:45 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI |
What is _modelRes? If it is a scene graph resource, it seems that we don't support cloning of scene graph resources currently. But for you purpose that isn't necessary anyway. Because you want to have one of the characters with a different texture you have to clone the material resource that references the texture and is used by the model and not the scene graph resource. Then you have to assign the cloned material resource to the mesh node (not resource) using Code: h3dSetNodeParamI( meshNode, H3DMesh::MatResI, clonedMaterialResource ); after that you can change the texture of the cloned material resource as you have done it already. |
Author: | philipppixel [ 04.03.2010, 21:22 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI |
Volker wrote: What is _modelRes? If it is a scene graph resource, it seems that we don't support cloning of scene graph resources currently. But for you purpose that isn't necessary anyway. Because you want to have one of the characters with a different texture you have to clone the material resource that references the texture and is used by the model and not the scene graph resource. Then you have to assign the cloned material resource to the mesh node (not resource) using Code: h3dSetNodeParamI( meshNode, H3DMesh::MatResI, clonedMaterialResource ); after that you can change the texture of the cloned material resource as you have done it already. Hi Volker, thanks for the patience you brought. You are right, I tried to clone a scene graph resource. So I followed your advice with different sequences of when I set the material resource back to the mesh. Unfortunately there seems to be an change-all-textures-or-change-nothing in place ![]() Code: //_texture2 = h3dAddResource(H3DResTypes::Texture, "models/man/civil02.jpg", 0); //_model = h3dAddResource(H3DResTypes::SceneGraph, "models/man/man.scene.xml", 0); //bool loaded = h3dutLoadResourcesFromDisk(::Values::CONTENT_DIR); //extract mesh from model scene graph H3DNode mesh = h3dGetNodeChild(_model, 1); std::cout << "found mesh " << mesh << std::endl; //extract mesh material from mesh int meshMaterial = h3dGetNodeParamI(mesh, H3DMesh::MatResI); std::cout << "found material " << meshMaterial << std::endl; //hey cloning works really :) H3DRes clonedMaterialResource = h3dCloneResource(meshMaterial, ""); std::cout << "clone material " << clonedMaterialResource << std::endl; //set new material resource back to mesh h3dSetNodeParamI(mesh, H3DMesh::MatResI, clonedMaterialResource); //extract mesh material again: meshMaterialNew == clonedMaterialResource int meshMaterialNew = h3dGetNodeParamI(mesh, H3DMesh::MatResI); std::cout << "found materialnew " << meshMaterialNew << std::endl; //fetch index from mesh material int idx = h3dFindResElem(meshMaterialNew, H3DMatRes::SamplerElem, H3DMatRes::SampNameStr, "albedoMap"); std::cout << "found index " << idx << std::endl; //index is 0 //replace texture resource inside material resource h3dSetResParamI(meshMaterialNew, H3DMatRes::SamplerElem, idx, H3DMatRes::SampTexResI, _texture2); This code yields in the following debug out: Code: found mesh 472 found material 146 clone material 181 found materialnew 181 found index 0 Given that index 0 is a proper first index I don't see why this code shouldn't work. Checking the EngineLog I don't find any warnings or errors in that term. Did I missed something again? Since my deadline comes rushed up and in order to get things done I should try to switch material.xmls instead of textures (although this situation really bugs me). cheers |
Author: | Volker [ 04.03.2010, 23:04 ] | ||
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI | ||
I finally tested it myself and the following code added to the chicago sample worked for me: Code: // after the initialization of the particles in crowd.cpp line 64 Particle special = _particles.back(); H3DRes manRes = h3dFindResource( H3DResTypes::Material, "models/man/civilian1.material.xml" ); H3DRes newRes = h3dCloneResource( manRes, "newManRes" ); H3DRes newTex = h3dAddResource( H3DResTypes::Texture, "models/man/civil01Special.jpg", 0 ); h3dutLoadResourcesFromDisk( _contentDir.c_str() ); h3dSetResParamI( newRes, H3DMatRes::SamplerElem, 0, H3DMatRes::SampTexResI, newTex ); int i = 0; int childMesh = 0; while( ( childMesh = h3dGetNodeChild( special.node, i++ ) ) != 0 ) h3dSetNodeParamI( childMesh, H3DMesh::MatResI, newRes ); I don't know why you commented your first lines where you load the additional texture, but apart from that, I guess one of the problems in your code is that you only change the mesh of one LOD. So your texture swap may be visible only if the corresponding LOD is active.
|
Author: | philipppixel [ 05.03.2010, 20:17 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI |
Volker wrote: I finally tested it myself and the following code added to the Chicago sample worked for me: - - - -x8 snip - - I don't know why you commented your first lines where you load the additional texture, but apart from that, I guess one of the problems in your code is that you only change the mesh of one LOD. So your texture swap may be visible only if the corresponding LOD is active. Wow, it worked and I didn't realize it! Please accept my apologies if I wasted your time. You have been very kind to test my code, for which I am very grateful. I understand that LOD stands for "Level of Detail". The lack of my understanding the LOD concept may play an important role here. I just wonder what the difference between all used LODs is then, because the used material.xml keeps the same? I take this has to do with that following parameters but that would certainly make an extra topic ![]() There is a simple answer why I commented the first three lines. I wanted to show of what kind the used variables are, also indicating that I use that code already elsewhere. Attachment: yoda-proceedsat.jpg
|
Author: | Volker [ 05.03.2010, 21:41 ] |
Post subject: | Re: changing textures w/ h3dFindResElem/h3dSetResParamI |
philipppixel wrote: Wow, it worked and I didn't realize it! Please accept my apologies if I wasted your time. You have been very kind to test my code, for which I am very grateful. I understand that LOD stands for "Level of Detail". The lack of my understanding the LOD concept may play an important role here. I just wonder what the difference between all used LODs is then, because the used material.xml keeps the same? Although in the sample every LOD has the same material, one could change it to realize e.g. smaller textures, shaders without skinning or some other faster but less beautiful material when having lower level of detail. |
Author: | sellee [ 05.04.2010, 00:53 ] |
Post subject: | python code |
Code: #change helmet texture
helmetTex = h3d.addResource(h3d.ResTypes.Texture,"models/knight/helmet.tga",0) h3d.utils.loadResourcesFromDisk("Content") h3d.findNodes(self._knight, 'helmet', h3d.NodeTypes.Mesh) helmet = h3d.getNodeFindResult(0) matRes = h3d.getNodeParamI(helmet,h3d.Mesh.MatResI) idx = h3d.findResElem(matRes,h3d.MatRes.SamplerElem,h3d.MatRes.SampNameStr,"albedoMap") h3d.setResParamI(matRes, h3d.MatRes.SamplerElem, idx ,h3d.MatRes.SampTexResI, helmetTex) |
Page 1 of 1 | All times are UTC + 1 hour |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |