Horde3D

Next-Generation Graphics Engine
It is currently 27.04.2024, 10:15

All times are UTC + 1 hour




Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: 28.02.2010, 19:01 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
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

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Last edited by philipppixel on 05.03.2010, 20:17, edited 3 times in total.

Top
 Profile  
Reply with quote  
PostPosted: 28.02.2010, 23:33 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
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.


Top
 Profile  
Reply with quote  
PostPosted: 01.03.2010, 19:47 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
Hi Volker, thanks for the quick reply. I'm going to try that.

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Top
 Profile  
Reply with quote  
PostPosted: 01.03.2010, 21:40 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
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 :). The sampler called "albedoMap" points to the texture "models/man/civil01.jpg", which I really, really like to exchange by a different UV map, located at "models/man/civil02.jpg". That second UV map needs necessarily to have the exact proportions as the first one since I don't change any model data. To be exact, I just copy-edited the JPG under a new name.

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

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Top
 Profile  
Reply with quote  
PostPosted: 02.03.2010, 00:20 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Thanks for the sum up. Why is cloning the material not working? What did you do?


Top
 Profile  
Reply with quote  
PostPosted: 02.03.2010, 08:36 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
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

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Top
 Profile  
Reply with quote  
PostPosted: 03.03.2010, 19:17 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
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?

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Top
 Profile  
Reply with quote  
PostPosted: 04.03.2010, 10:45 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
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.


Top
 Profile  
Reply with quote  
PostPosted: 04.03.2010, 21:22 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
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 ;) So I am very sorry if I bug you with this problem. Nevertheless I've put now debug prints to the statements and the values seem to me not unexpected. This is the code I used until now:

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

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Top
 Profile  
Reply with quote  
PostPosted: 04.03.2010, 23:04 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
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.


Attachments:
Sample.jpg
Sample.jpg [ 37.54 KiB | Viewed 16186 times ]
Top
 Profile  
Reply with quote  
PostPosted: 05.03.2010, 20:17 
Offline

Joined: 22.11.2009, 16:14
Posts: 25
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

_________________
philipppixel
8=:(=)D { Save the Giraffes )


Top
 Profile  
Reply with quote  
PostPosted: 05.03.2010, 21:41 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
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.


Top
 Profile  
Reply with quote  
 Post subject: python code
PostPosted: 05.04.2010, 00:53 
Offline

Joined: 25.03.2010, 03:58
Posts: 13
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)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 36 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group