Texture paths [SOLVED]

Return to Scripting Issues

Texture paths [SOLVED]

Postby silveralex » Tue May 19, 2009 9:13 pm

I am trying to implement something I've seen in some commercial games. Basically a single model is used for a character (say a soldier). But there are several texture sets which are made for the model, so you can have differnt teams,colors, etc.

The textures are stored in a subfolder under the model's path.

What I'd like to do is programmatically allow the user select which texture to use by letting them specify a folder.

Now I haven't tried it yet, but think I figure out the setTexture sample code in the manual to switch this for simple models with 1 texture if it's always the same filename. seems simple enough.

But if some models have multiple textures, is there a way I can just change the paths used by all textures in a model?

Say the default textures are:
/std/body.tga
/std/helmet.tga
/std/boots.tga

the user chooses to use the set in /green_soldier/
I would need to load and set:
/green_soldier/body.tga
/green_soldier/helmet.tga
/green_soldier/boots.tga

so whats the best approach ? (assuming I don't know beforehand the name of the texture files or the number of files a model uses)
Last edited by silveralex on Mon Mar 05, 2012 8:40 pm, edited 2 times in total.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby treeform » Tue May 19, 2009 11:12 pm

find the proper mesh inside the character with char.find("**\propermesh")
set texture on that mesh with setTexture().

One problem you might run into if egg opt char optimized the textures some how into a single tex.

--------

In my game i also have "team stripes." I dont switch textures but use shader to color them properly at run time.
User avatar
treeform
 
Posts: 2106
Joined: Sat May 05, 2007 5:15 pm
Location: SF, CA

Postby silveralex » Wed May 20, 2009 12:29 pm

Hi, thx for the reply!

Is there a way to get a list of all the parts in the model that have textures? I could then interate through the list , updating the texture for each.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby silveralex » Tue May 26, 2009 8:55 pm

Still trying to work through this.

for example, if x is an Actor I've constructed:
print x.findAllTextures returns:
male_basic_bump
male_basic
which is the name of the 2 textures on this model (without the file extension, .png or paths)

print x.getTexture() returns:
None

As per my previous post, is there a way to return a list of the parts in the model that have textures? I could then interate through the list , updating the texture (using setTexture) for each with a new user-selected path.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby drwr » Tue May 26, 2009 9:00 pm

It's possible to iterate through all the parts that have textures, but you'd have to flag them all anyway. If you're going to flag them all, you already know what they are, don't you? Why not just iterate through the list of names that you flagged?

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby silveralex » Tue May 26, 2009 9:08 pm

Sorry, not understanding what you mean by "flagging them". How would I do that?

I wouldn't know beforehand which textures are present in the model, as we have a few different ones we're using (some with extra parts)
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby drwr » Tue May 26, 2009 10:06 pm

The answer is different depending on whether you're talking about Actors or ordinary models. With an Actor, you need to "flag" all the pieces that you will modify individually; otherwise all the pieces will all be combined into a single GeomNode. You would do this by passing the egg file through egg-optchar, with the -flag option. I believe this is described in the manual. With an ordinary model, you (usually) don't have to do this.

That being said, it is also possible to iterate through the model and find just the textures, as you suggested, and replace them one-at-a-time, even if you have not flagged any pieces. It is a little complicated, though, because you have to use the low-level state interface to pull out the individual states within a single GeomNode. Still, this code (untested) ought to do the trick. It should work equally well for an Actor or for an ordinary model.

Code: Select all
for np in model.findAllMatches('**/+GeomNode'):
    gn = np.node()
    for gi in range(gn.getNumGeoms()):
        state = gn.getGeomState(gi)
        ta = state.getAttrib(TextureAttrib.getClassType())
        if ta:
            for si in range(ta.getNumOnstages()):
                stage = ta.getOnStage(si)
                tex = ta.getOnTexture(stage)
                filename = tex.getFilename()
                filename2 = Filename('/my/new/path', filename.getBasename())
                tex2 = loader.loadTexture(filename2)
                ta = ta.addOnStage(ta.addOnStage(stage, tex2))
            state = state.setAttrib(ta)
            gn.setGeomState(gi, state)
           


David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby silveralex » Wed May 27, 2009 10:45 am

Thx so much for the code, I'll try it out!

I don't think I would have figured out the object hierarchy for a while :)
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby silveralex » Wed May 27, 2009 11:01 am

The code worked great!
I'm going to make it a callable function and put in some error-checking.

There were a couple of line I had to chg to get it to run, in case anyone needs something like this in the future (see below - I commented out the lines I changed and my corrected line is underneath - just typos i think)

Code: Select all
for np in model.findAllMatches('**/+GeomNode'):
    gn = np.node()
    for gi in range(gn.getNumGeoms()):
        state = gn.getGeomState(gi)
        ta = state.getAttrib(TextureAttrib.getClassType())
        if ta:
            #for si in range(ta.getNumOnstages()):
            for si in range(ta.getNumOnStages()):
                stage = ta.getOnStage(si)
                tex = ta.getOnTexture(stage)
                filename = tex.getFilename()
                filename2 = Filename('art/characters/batman/skins/standard', filename.getBasename())
                tex2 = loader.loadTexture(filename2)
                #ta = ta.addOnStage(ta.addOnStage(stage, tex2))
                ta = ta.addOnStage(stage, tex2)
            state = state.setAttrib(ta)
            gn.setGeomState(gi, state)


Thx again!
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby silveralex » Wed Feb 08, 2012 9:57 pm

More old code I'm revisiting.

The final code above is using addOnStage, so my understanding (which could be wrong) is that this is applying a second texture to the geomnode?

Is there a way I could simply replace the texture on the geomnode completely , not add a second texture. I use some gloss/normal maps and have noticed some strange effects , which I'm thinking may be caused by layering these textures rather than completely replacing them.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby silveralex » Thu Feb 09, 2012 9:50 am

Still looking at this.
Specifically, it seems that the basic (diffuse) texture I use is replaced OK, but I also have normal(bump) and gloss (reflection) textures which are specified in the egg file.

When I use the code above, I still see the effects of those textures in the model, even though I have a different set of normal and gloss textures in the new folder I'm specifying.

Not sure if those type of textures need to be handled differently? Or is there a way to explicitly clear them before I call addonStage for the new texture?

Appreciate any help.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby drwr » Fri Feb 10, 2012 6:24 pm

You have to find all of the TextureStages on the model. Each TextureStage can have a different texture. If you apply only a texture with the one-parameter setTexture() call, you have only replaced the default TextureStage, without changing the others.

The code you paste above is a very clumsy way to find all of the TextureStages. An easier way is to use model.findAllTextureStages().

Read up about multitexture in the manual to learn more about the way TextureStages work.

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby silveralex » Fri Feb 10, 2012 7:47 pm

Thanks, I'll check that out.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby silveralex » Mon Mar 05, 2012 2:19 pm

Just got back to this.

I think the problem I see (strange effects of bump or glow maps) is being caused by textures being applied in the wrong order.

Basically, the code above does not guarantee what order it will loop through e texturestages in.

Not at my pc right now, so I can't try solutions (will try later)
But is there a way to make sure the list of stages I get back is always in the same order?
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY

Postby silveralex » Mon Mar 05, 2012 8:40 pm

Never mind, it seems that some rogue alpha layers were causing the weird things I was seeing. So the code above seems good to go.
User avatar
silveralex
 
Posts: 235
Joined: Tue Apr 21, 2009 1:48 pm
Location: New York, NY


Return to Scripting Issues

Who is online

Users browsing this forum: Bing [Bot] and 0 guests