Page 1 of 1

How's them apples? XSI --> OGRE material file

Posted: Fri Jan 07, 2005 4:28 am
by Bill
Well this is creaping along by inches, but I got the SoftImage Material OpenGL Real Time shaders to write out to an OGRE material file.

Only two things are bogus:
shading phong - you can't pick the shader algorithm with the OpenGl shaders in XSI so I just selected phong.
tex_coord_set 0 - I haven't figured out how to properly reference the texture UV maps yet. (That comes next.)

Everything else comes from the XSI shaders.

Of course I haven't actually tested it yet. I only just got it to run without crashing. :-) It's been 6 years since I wrote in C++, but it's slowly coming back.


Anyway, without further adieu here is an output from my material exporter:

Code: Select all

material Scene/Material2
{
    technique
    {
        pass
        {
            shading phong
            lighting on
            ambient 0.300000 0.300000 0.300000 1.000000
            diffuse 0.500000 0.500000 0.500000 1.000000
            diffuse 0.000000 0.000000 0.000000 1.000000
            specular 0.700000 0.700000 0.700000 1.000000 10.000000
            depth_check on
            depth_write on
            cull_hardware none
            cull_software none
            scene_blend one zero

            texture_unit
            {
                texture Pictures\noIcon.pic 2d 
                colour_op modulate 
                tex_coord_set 0 
                filtering linear linear none
                max_anisotropy 1 
                env_map off 
                tex_address_mode clamp 
                scale 1.000000 1.000000
                rotate 0.000000 
                scroll 0.000000 0.000000
            }
        }
        pass
        {
            shading phong
            depth_check on
            depth_write on
            cull_hardware none
            cull_software none
            scene_blend one dest_alpha

            texture_unit
            {
                texture Pictures\noIcon.pic 2d 
                colour_op alpha_blend 
                tex_coord_set 0 
                filtering linear linear none
                max_anisotropy 1 
                env_map off 
                tex_address_mode clamp 
                scale 1.000000 1.000000
                rotate 0.000000 
                scroll 0.000000 0.000000
            }
        }
        pass
        {
            shading phong
            depth_check on
            depth_write on
            cull_hardware clockwise
            cull_software back
            scene_blend one dest_colour

            texture_unit
            {
                texture C:\Softimage\XSI_4.2\Application\rsrc\noIcon.pic  
                colour_op replace 
                tex_coord_set 0 
                filtering linear linear none
                max_anisotropy 1 

            texture_unit
            {
                texture Pictures\noIcon.pic 2d 
                colour_op modulate 
                tex_coord_set 0 
                filtering point anisotropic linear
                max_anisotropy 6 
                env_map off 
                tex_address_mode clamp 
                scale 1.000000 1.000000
                rotate 0.000000 
                scroll 0.000000 0.000000
            }
        }
    }
}
Not to shabby huh?

Posted: Fri Jan 07, 2005 2:40 pm
by sinbad
Ooo, very nice. I'd be interested in seeing the code if you're willing, since material export is on the TODO list for the XSI exporter.

Accessing multiple UVs in XSI is weird. Very weird. I actually raised a support request with SoftImage over it, and they came back with a very complete response, but you certainly have to go around the houses a lot. However, since you don't actually need the UV coordinates, just the coordset binding, it's a bit easier for tex_coord_set.

Multiple UVs are held in 'Cluster' objects under the PolygonMesh. There are many types of cluster, but the one you're looking for is 'sample', which in C++ is a constant 'siSampledPointCluster'. You then for some reason have to locate only the ones which have uv spaces associated with them. You can filter like this:

Code: Select all

    size_t numUVs = 0;
    CRefArray clusterRefArray;
    // Filter to 'sample' types
         xsiMesh.GetClusters().Filter(siSampledPointCluster,CStringArray(),L"",clusterRefArray);

        size_t numUVs = 0;
        CRefArray clusterRefArray;
        // Filter to 'sample' types
        xsiMesh.GetClusters().Filter(siSampledPointCluster,CStringArray(),L"",clusterRefArray);

        Cluster samplePointClusterUV;
        CRefArray uvClusterPropertiesRefArray;
        
        long i;
        for(i = 0; i < clusterRefArray.GetCount(); ++i)
        {
            Cluster cluster(clusterRefArray[i]);		
            // Now filter all the 'uvspace' children
            // there is one of these per UV set
            if(cluster.GetProperties().Filter(
                siClsUVSpaceTxtType, CStringArray(), L"", 
                uvClusterPropertiesRefArray) == CStatus::OK)
            {
                samplePointClusterUV = cluster;			
                break;
            }
        }

        // Ok, we now have our array of UV sets
        numUVs = uvClusterPropertiesRefArray.GetCount();

That tells you how many UV sets you have. My problem was linking this up to the vertices (which are stored elsewhere, and clusters only reference facets, which are quads - the link is difficult). Your problem will be finding how to link a texture_unit with the sample cluster. Not having looked at XSI materials yet I can't help you with that, but maybe the above helps for a bit of context.

Oh, and when I do implement the code to export multiple UVs, I intend to export them in order (if that helps).

Posted: Fri Jan 07, 2005 6:42 pm
by Bill
I'll be glad to share my code. It's pretty rough and messy at the moment, but you can have it. I have copied my code to http://www.cast.uark.edu/~wgj/OGREXSI/ . The thing your looking for is the writeOgreMaterial() comand in the OGERXSIParser.h file. There are also my eariler attemps; writeOgreMaterial2() which worked (sort of) off the regular XSI shaders; and writeOgreMaterial1() whch was just to get some sort of material file written for my meshes.

One thing you should find useful is my material parser parseMaterial() in the XSIParser.h file.

My stuff creates a dll that you have to load with the plugin manager. It's the old way of loading DLLs, but I didn't realize is was deprecated until after I got it figured out. I'll change it later once I get everything working. Right now every thing is written to a hard coded directory. After I get the UVs figure out I'll try to figure out the SoftImage GUI stuff.


Yeah, getting at the UV coords odd. What I did was use the PolygonMesh.GetTriangles() to get all the triangles and then for each triangle I used Triangle.GetUVArray(). And instead of getting all the UV coord sets for a point you only get one set. And the wierd thing is is that the set you get is the one you have selected in the Texture Editor.

Anyway, I also asked SoftImage about this and this is what they told me.

"The UV sets reside inside the cluster property. You need to filter the object's cluster for siSampledPointCluster. Then for each sample he needs to filter for siClsUVSpaceTxtType. this will return a collection of UV sets. each UVset will have the UV coords covering the objects polynodes."

Well, I'll work on this this weekend (or play the Guild Wars open beta)

Posted: Fri Jan 07, 2005 9:58 pm
by sinbad
Thanks, that'll come in handy.

That response from SoftImage pretty much equates to the code snippet I posted above :)

[Edit]Skimming the code, I used the same way of loading the plugin (just defining the right exports like 'XSILoadPlugin'). I didn't know there was another way, what do you mean?[/Edit]

Posted: Fri Jan 07, 2005 11:45 pm
by Bill
sinbad wrote: [Edit]Skimming the code, I used the same way of loading the plugin (just defining the right exports like 'XSILoadPlugin'). I didn't know there was another way, what do you mean?[/Edit]
In the documentation where is talks about this stuff (I don't want to look for it now), it says that this method is the old way. There is a new method that uses a different set of commands to register everything. Then you put the dll in certain directory and (I think) the dll is loaded when you launch XSI (or maybe when the project that has the dll directory is loaded). By the time I read that I already had the other stuff working so I didn't pay much attention. Besides the "old method" seems better for debugging since you have to reload the dll a lot.

Posted: Sat Jan 08, 2005 12:30 am
by Bill
Ok I think I had it all wrong. I went back through the docs and I think the way we did it is the new way as of 4.0. There are 2 kinds of dll plug-ins; self installing plug-ins and non-self installing plugins. The self installing plug-in are dropped in Application/Plugins directory and are loaded automatically when XSI is launched. Since I was using the plugin manager to load the plug-in I though I had created a non-self installing plug-in. Having just reviewed the manual I no longer think that. The same dlls we load with the plug-in manager will auto-load if we drop them in the directory. (I think)

Non self loading plugins (the old way) use the command XSI::CStatus XSIOnCommandCPP.


Anyway, I had it all backwards. Which is just fine with me as it's one less thing I have to do.