Orbiter-Forum [API Question] Set Material to a group at runtime
 Register Blogs Orbinauts List Social Groups FAQ Projects Mark Forums Read

 Orbiter SDK Orbiter software developers post your questions and answers about the SDK, the API interface, LUA, meshing, etc.

 02-08-2019, 07:05 PM #1 fred18 Addon Developer Set Material to a group at runtime Hi guys, you can see i'm developing in this days from the questions I keep asking here Correct me if I'm wrong: you can not change the material index of a group in a mesh at runtime, right? WHAT I AM TRYING TO DO: highlight a meshgroup, pretty much similar to what the D3D9 debug mesh controls does. But I want multiple groups selection. I already implemented an HighlightMesh function which highlights the entire mesh very well, but for single groups the story is a bit different. I tried to use the same method (change the emissive set of the material) but when multiple groups share the same material also the groups that are not selected are highlighted. So I thought of adding a material at the bottom of the list and then point the highlighted group to that, and I was in the middle of that when I realized that the GROUPEDITSPEC does not have any flag about materials... I can get the material index from the GROUPREQUESTSPEC but I cannot change it, and this is probably a show stopper for this option because I see no other way to do it. Can anyone confirm this or point me on another path to get it? As always thanks to anyone who will reply! Fred EDIT: Also I was thinking that if this is not possible I don't understand the point of the oapiAddMaterial function. if then I can set nothing to use it why should I add a material to a mesh? Last edited by fred18; 02-08-2019 at 10:07 PM.
 02-09-2019, 10:03 AM #2 jarmonik Beta Tester Hi Fred, There is a good propability that you can change the mesh group material index by using oapiMeshGroup() function. It should be possible to propagate the change to a graphics client by using VESSEL::MeshModified() but that will delete the old mesh and reconstruct a new one from scratch, so, it would be very slow operation and might have an impact in animations as well since the animation matrices are stored in a mesh. We could add a gcAPI function to set the data directry to a DEVMESH but in that case a different codes would be required for inline and d3d9.
 02-09-2019, 11:14 AM #3 fred18 Addon Developer You are right, I was just testing with D3D9 and it wasn't working. So the issue is that with inline client works very well and easily, but with D3D9 no luck, MeshModified doesn't make any difference there, I don't know why. I tried many things, including getting a group with oapiMeshGroupEx from a devmesh (I found on the forum that it works) but that is fine just to GET informations, if you try to apply something like changing the MtrlIdx it CTDs immediately...
02-09-2019, 12:19 PM   #4
jarmonik
Beta Tester

Quote:
Originally Posted by fred18
So the issue is that with inline client works very well and easily, but with D3D9 no luck, MeshModified doesn't make any difference there, I don't know why.

I found a potential bug from the client that could have effected MeshModified() method. I quess nobody's been using that before. Also, to get a mesh handle for oapiMeshGroup() function VESSEL::GetMeshTemplate() should be used. Could you check that "MeshModified Event = 0x%X" is written in the D3D9ClientLog in /Modules/D3D9Client

Are you developping on Beta or 2016 ?

Here is a new binary for Beta that "should" be working.
Attached Files
 D3D9Client.zip (498.2 KB, 6 views)

 02-09-2019, 12:30 PM #5 jarmonik Beta Tester There is also this note: PHP Code:  /**     * \brief Make a copy of one of the vessel's mesh templates.     * \param idx mesh index     * \return handle of copied mesh     * \note Meshes loaded with \ref oapiLoadMeshGlobal are templates shared     *   between all vessel instances and should never be modified by individual     *   vessels. If a vessel needs to modify its meshes, it should operate on     *   a copy of the template.     */    MESHHANDLE CopyMeshFromTemplate (UINT idx) const;  
 02-09-2019, 12:57 PM #6 fred18 Addon Developer Quote: Originally Posted by jarmonik  Also, to get a mesh handle for oapiMeshGroup() function VESSEL::GetMeshTemplate() should be used. yes, I use that, in D3D9 the meshhandle returned by GetMesh is always NULL Quote: Originally Posted by jarmonik  Could you check that "MeshModified Event = 0x%X" is written in the D3D9ClientLog in /Modules/D3D9Client Actually I cannot see any call to that even though its returned value is 0. Quote: Originally Posted by jarmonik  Are you developping on Beta or 2016 ? Actually for 2016. I always do it first for 2016 and then I go for the Beta, in order not to rely on APIs that are not there yet in 2016. Quote: Originally Posted by jarmonik  Here is a new binary for Beta that "should" be working. Thanks!!! it will take some time to pass the project to the Beta folder because I'm really bad with VC properties, but I will test it as soon as i get it done. Quote: Originally Posted by jarmonik  There is also this note: PHP Code:  /**      * \brief Make a copy of one of the vessel's mesh templates.      * \param idx mesh index      * \return handle of copied mesh      * \note Meshes loaded with \ref oapiLoadMeshGlobal are templates shared      *   between all vessel instances and should never be modified by individual      *   vessels. If a vessel needs to modify its meshes, it should operate on      *   a copy of the template.      */     MESHHANDLE CopyMeshFromTemplate (UINT idx) const;   I know this, I think it is because theoretically if you modify a meshtemplate and there are other instances of the mesh in the sim you will see also the other getting modified. The curious part is that it is not happening. I'm using a the loadmesh clbk in oapiloadmeshglobal to get the meshes rotated properly before they get passed to D3D9, but if I reload the mesh or if I edit it (materials, or vertex editing) nothing happens to the other instances... I also thought that I haven't seen any addon to use that function, even though we all should use it: the right procedure I think it would be to load a mesh from a mesh manager with oaploadmeshglobal, to make a copy with copymeshfromtemplate and then to add the copy to the vessel, but I never saw this in any addon or example
02-09-2019, 01:18 PM   #7
jarmonik
Beta Tester

Quote:
Originally Posted by fred18
Actually I cannot see any call to that even though its returned value is 0.
If you are not seeing "MeshModified Event" Logged to a log. Then the event wont fire. Based on my understanding calling MeshModified() should fire EVENT_VESSEL_MODMESHGROUP to notify client about it.

But anyway, here's the binary for 2016

I have some other matters to attend to, so, I won't be in the forums this evening.
.
Attached Files
 D3D9Client.zip (511.3 KB, 7 views)

 Thanked by:
 02-09-2019, 02:45 PM #8 fred18 Addon Developer Ok, so: - MeshModified is now regularly call, I can see it in the log. - There is no visual change in D3D9, looks like nothing is happening BUT if I use GetMeshTemplate also in the inline client nothing happens, even if I call MeshModified. If I use GetMesh it works in the inline, but of course the result is NULL in the D3D9. It seems a dead end. The only way I know to edit the groups in DevMeshes is through GRPEDITSPEC but it's not possible to set the material there. so not much to do right now. The only way I see at the moment maybe a bit crazy but is this: in loadclbk of oapiloadmeshglobal create copies of all the materials so each group will have its own, then highlight through that. I don't know if that's going to have serious impact on the performance: having 400 materials instead of 20 changes a lot in terms of performance? I think not: it occupies more memory but the calculations that need to be done are always the same, right?
 02-09-2019, 03:14 PM #9 Donamy Beta Tester Are you trying to change materials, that have been set for multiple groups ? Like reflective parts that shouldn't be ? If they are the ISS A2Z original meshes. I could separate those in the mesh for you. Then it would be up to others, to do the same with their addons.
 Thanked by:
 02-09-2019, 03:17 PM #10 fred18 Addon Developer Quote: Originally Posted by Donamy  Are you trying to change materials, that have been set for multiple groups ? Like reflective parts that shouldn't be ? If they are the ISS A2Z original meshes. I could separate those in the mesh for you. Then it would be up to others, to do the same with their addons. yes, but not for appearence looking. I'm working on the insim animation definitions, so I want that when the user select a group to animate it will highlight itself. It is already a working option for the entire mesh, but I'm trying to implement this also for the single groups. BTW I'm making progress with animations: it seems to work quite well, I can create animations and modify them insim, so this could e a good option to add. Let's see if I manage to get there
 Thanked by:
 02-09-2019, 06:37 PM #11 jarmonik Beta Tester Quote: Originally Posted by fred18  I don't know if that's going to have serious impact on the performance: having 400 materials instead of 20 changes a lot in terms of performance? I think not: it occupies more memory but the calculations that need to be done are always the same, right? No, there shouldn't be any performance impact from that. However, the MeshModified() would be very heavy. There is something wrong in there but I don't know what. GetMesh() doesn't work since it gives NULL. So, does CopyMeshFromTemplate() create a new copy everytime it's called or does it give a HANDLE to the same local copy everytime ? Well, that probably doesn't matter since the MeshModified() approach is pretty bad anyways.
 02-09-2019, 08:36 PM #12 fred18 Addon Developer IT WORKS!!!!!!!!!!!!!!!!!!!!! Group36 of unity mesh highlighted in red: Here's the brief description of how I made it, below the commented code: whenever a mesh is loaded it passes through the loadmeshclbk function which manipulates the mesh handle before either pass it to the D3D9 or to the orbiter core. In this function the following happens: if we are with the inline client the function create a new material definition (actually three, one for each highlight color possible) and append it to the material list of the mesh. when there is a call to highlight the group then the system simply change the material index of the live mesh (GetMesh) to the new one created. When the group shall not be highlighted anymore it just revert to the original index, getting it from the mesh template. With D3D9 is a bit more complicated: when a mesh is loaded each group gets assigned to a new material with the identical definition of its own. Then the first original materials are deleted, so we now have a mesh with n groups and n materials. Now, when a call to highlight the group arrives the system manipulates the material of the group and changes its emissive part. Now it's possible, since each material is assigned to just one group no more issues happens. When the system asks to revert, the material is reverted to the original one getting it from the template... and that's it! here's the code, for the function called within oapiloadmeshglobal: Code: void MeshManager::LoadingRearrangeMaterials(MESHHANDLE msh) { if (UsingD3D9()) { //If D3D9 DWORD groups_count = oapiMeshGroupCount(msh); DWORD initial_material_count = oapiMeshMaterialCount(msh); //Get Initial Material Count to be used afterwards for cleanup for (DWORD i = 0; i < groups_count; i++) { //for every group MESHGROUP *mg = oapiMeshGroup(msh, i); // get the group DWORD matidx = mg->MtrlIdx; // get its original material index; MATERIAL *mat = oapiMeshMaterial(msh, matidx); //get the group material DWORD newmatidx = oapiAddMaterial(msh, mat); //add a copy of the material at the bootm mg->MtrlIdx = newmatidx; //set the group material to the copy just added } for (DWORD i = 1; i < initial_material_count; i++) { //delete all the initial materials since now all the groups point to the copies oapiDeleteMaterial(msh, i); } } else { //if NOT D3D9 COLOUR4 colred = { 1,0,0,1 }; //Red Color COLOUR4 colgreen = { 0,1,0,1 }; //Green Color COLOUR4 colblue = { 0,0,1,1 }; //Blue Color matred = new MATERIAL; //Create the tree new materials matred->ambient = colred; matred->diffuse = colred; matred->emissive = colred; matred->specular = colred; matred->power = 0; matgreen = new MATERIAL; matgreen->ambient = colgreen; matgreen->diffuse = colgreen; matgreen->emissive = colgreen; matgreen->specular = colgreen; matgreen->power = 0; matblue = new MATERIAL; matblue->ambient = colblue; matblue->diffuse = colblue; matblue->emissive = colblue; matblue->specular = colblue; matblue->power = 0; DWORD green_idx = oapiAddMaterial(msh, matgreen); //Add the new materials to the mesh DWORD blue_idx = oapiAddMaterial(msh, matblue); DWORD red_idx = oapiAddMaterial(msh, matred); delete matred; //cleanup delete matgreen; delete matblue; } return; } and for the highlight group function: Code: bool MeshManager::HighlightMeshGroup(UINT msh_idx, UINT grp_idx, bool Highlight) { DEVMESHHANDLE devmsh_h = SB1->GetDevMesh(SB1->visual, msh_idx); //let's get the devmesh from the vessel MESHHANDLE temp_msh_h = SB1->GetMeshTemplate(msh_idx); //let's get the template mesh from the vessel to have the original values if (temp_msh_h == NULL) { return false; }// you'll never know... MESHGROUP *mg = oapiMeshGroup(temp_msh_h, grp_idx); //Get the original mesh group if (UsingD3D9()) { // if D3D9 DWORD matidx = mg->MtrlIdx; //Get The original material index MATERIAL *mat = oapiMeshMaterial(temp_msh_h, matidx); //Get the original material definition MATERIAL *mat2 = new MATERIAL; //Create the new material for the excahnge mat2->ambient = mat->ambient; //Set all the values of the new material exactly as the original mat2->diffuse = mat->diffuse; mat2->emissive = mat->emissive; mat2->specular = mat->specular; mat2->power = mat->power; if (Highlight) { //if Highlight if (HighLightColor == HIGHLIGHTCOLORRED) { mat2->emissive.r = 1; // Set the emissive color of the new material at maximum } else if (HighLightColor == HIGHLIGHTCOLORBLUE) { mat2->emissive.b = 1; } else if (HighLightColor == HIGHLIGHTCOLORGREEN) { mat2->emissive.g = 1; } } oapiSetMaterial(devmsh_h, matidx, mat2); //change the material to the new one. if not highlight the original will then be restored delete mat2; //cleanup } else { //if Inline client MESHHANDLE msh_h = SB1->GetMesh(SB1->visual, msh_idx); //Get the Live mesh from the sim if (msh_h == NULL) { return false; }// you'll never know... DWORD mat_count = oapiMeshMaterialCount(msh_h); //Get the material count to know the know the index MESHGROUP *mg_inline = oapiMeshGroup(msh_h, grp_idx); //Get the meshgroup from the live sim if (Highlight) { //if highlight if (HighLightColor == HIGHLIGHTCOLORRED) { mg_inline->MtrlIdx = mat_count -1; //change the material index to the one created at the beginning } else if (HighLightColor == HIGHLIGHTCOLORBLUE) { mg_inline->MtrlIdx = mat_count - 2; } else if (HighLightColor == HIGHLIGHTCOLORGREEN) { mg_inline->MtrlIdx = mat_count - 3; } } else { mg_inline->MtrlIdx = mg->MtrlIdx; //if not highlight just restore with the template index } } return true; } Last edited by fred18; 02-09-2019 at 08:42 PM.
 Thanked by:

 Posting Rules BB code is On Smilies are On [IMG] code is On HTML code is Off You may not post new threads You may not post replies You may not post attachments You may not edit your posts
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home Orbiter-Forum.com     Announcements     Meets & Greets Orbiter Space Flight Simulator     Orbiter Web Forum         OFMM         Orbiter Forum Space Station         Simpit Forum     General Questions & Help     MFD Questions & Help     Hardware & Software Help     Tutorials & Challenges     Orbiter SDK     Orbiter Visualization Project     Orbiter Beta » Orbiter Project Orbiter Addons     OrbitHangar Addons & Comments     Addons     Addon Development     Addon Requests     Addon Support & Bugs         Addon Developer Forums             Project Apollo - NASSP     Orbiter Lua Scripting Far Side of the Moon     Spaceflight News     Math & Physics     Astronomy & the Night Sky     Backyard Rocketry     Brighton Lounge     International Forum

All times are GMT. The time now is 03:18 AM.