How can I get InteriorInstance.setSkinBase to work?
by Masser · in Torque Game Engine · 11/10/2007 (11:02 am) · 22 replies
I have been trying to come up with a good solution for DIF skinning -- ideally, a way to create an InteriorInstance object in a MIS file and assign a texture (ie. stucco.wall.jpg) to an existing material (base.wall.jpg) as the game loads. I hope to do this with an attribute of the InteriorInstance object, for instance:
new InteriorInstance() {
canSaveDynamicFields = "1";
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile = "~/data/interiors/stucco.wall.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
I was in the process of trying to learn from a resource I found:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11178
..when I discovered an already existing method (in my TGE 1.5.2 source), called "setSkinBase" which accepts a basename as a parameter. I was very excited because that resource looks a little old and I thought maybe this had been implemented as a result. However, according to my experience so far and the following documentation this feature "does not work":
http://tdn.garagegames.com/wiki/Torque_Console_Objects_6
I'm still a bit new to the Torque community so I went looking for CVS/SVN access (I've only worked form the installer SDK so far) to find a possible fix. I'm under the assumption that this type of access no longer exists. Can someone please help me with answers to a couple of questions:
1) Does the setSkinBase method really work (and I've just been misusing it)? If so, please provide an example of its usage.
2) Does SVN access still exist and how do I get to it? Has the setSkinBase issue been fixed in newer source?
Thanks.
new InteriorInstance() {
canSaveDynamicFields = "1";
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile = "~/data/interiors/stucco.wall.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
I was in the process of trying to learn from a resource I found:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11178
..when I discovered an already existing method (in my TGE 1.5.2 source), called "setSkinBase" which accepts a basename as a parameter. I was very excited because that resource looks a little old and I thought maybe this had been implemented as a result. However, according to my experience so far and the following documentation this feature "does not work":
http://tdn.garagegames.com/wiki/Torque_Console_Objects_6
I'm still a bit new to the Torque community so I went looking for CVS/SVN access (I've only worked form the installer SDK so far) to find a possible fix. I'm under the assumption that this type of access no longer exists. Can someone please help me with answers to a couple of questions:
1) Does the setSkinBase method really work (and I've just been misusing it)? If so, please provide an example of its usage.
2) Does SVN access still exist and how do I get to it? Has the setSkinBase issue been fixed in newer source?
Thanks.
#2
1) StaticShape.setSkinName(skinPrefix);
2) InteriorInstance.setSkinBase(basename);
I'm assuming by what you said that the parameter passed is identical in both cases -- the prefix of the skin (ie. "stucco" to refer to "stucco.wall.jpg"). I've tested with all textures in the same folder and using an almost identical approach. Shapes work and Interiors don't.
If I had my way, I'd just love to have an approach like I said above -- a settable Skin attribute for each object to affect the object when the mission loads (as well as after). It would be nice if it could affect multiple materials on the same object. Has anyone witnessed #2 working?
11/10/2007 (7:07 pm)
Thank you. Yeah, that's basically what I did and it didn't work. I may have made a mistake but I don't think so. The two approaches are slightly different (different names anyway). They are:1) StaticShape.setSkinName(skinPrefix);
2) InteriorInstance.setSkinBase(basename);
I'm assuming by what you said that the parameter passed is identical in both cases -- the prefix of the skin (ie. "stucco" to refer to "stucco.wall.jpg"). I've tested with all textures in the same folder and using an almost identical approach. Shapes work and Interiors don't.
If I had my way, I'd just love to have an approach like I said above -- a settable Skin attribute for each object to affect the object when the mission loads (as well as after). It would be nice if it could affect multiple materials on the same object. Has anyone witnessed #2 working?
#3
Anyways, I just examined the code (as opposed to glancing at it) and it seems the textures need to be named differently!
It seems that the base textures must be named like: "wall.blnd" <-- notice blnd and not base
and the skin must be named: "wall.stucco"
These are the material names, I know nothing of how DIFs work so I assume this is the same as the texture name, just add .jpg to the above names for your textures.....
11/10/2007 (8:22 pm)
Since models can have more than one texture I'd prefer something like "setSkin(%originalTexture, %newTexture)".Anyways, I just examined the code (as opposed to glancing at it) and it seems the textures need to be named differently!
It seems that the base textures must be named like: "wall.blnd" <-- notice blnd and not base
and the skin must be named: "wall.stucco"
These are the material names, I know nothing of how DIFs work so I assume this is the same as the texture name, just add .jpg to the above names for your textures.....
#4
I created a brand new DIF in Constructor (very simple -- a cube) and applied a texture called "wall.blnd.jpg". I then exported it using "export to DIF" the way I always do. I then created another texture, called it "wall.plaster.jpg" and placed it in the same folder as the DIF and original texture. When I placed the DIF using the Mission Editor, it comes up with no texture at all -- it's just gray. The console complains "Cannot locate texture: WALL.BLND". It is there (same folder) and I even tried renaming it to all caps (didn't know it was case sensitive) and it still can't find it. If I take the same brush in Constructor, rename the SAME image to "wood.jpg", apply it and export the same way... the texture shows just fine in Mission Editor. It seems like it's having a problem with the "." in the image name.
By the way, if I try to us:
1550.setSkinBase("plaster");
from the console on the DIF (which initializes gray), it doesn't change to the texture either. Just so I'm sure we are on the same page... you were suggesting that I apply a texture called "wall.blnd.jpg" as the base and "wall.plaster.jpg" as the skin (both located together with the DIF they're applied to), right?
Thanks.
11/11/2007 (6:33 pm)
Brian: Thank you. I'm going to kick myself when I realize what dumb mistake I'm making, but...I created a brand new DIF in Constructor (very simple -- a cube) and applied a texture called "wall.blnd.jpg". I then exported it using "export to DIF" the way I always do. I then created another texture, called it "wall.plaster.jpg" and placed it in the same folder as the DIF and original texture. When I placed the DIF using the Mission Editor, it comes up with no texture at all -- it's just gray. The console complains "Cannot locate texture: WALL.BLND". It is there (same folder) and I even tried renaming it to all caps (didn't know it was case sensitive) and it still can't find it. If I take the same brush in Constructor, rename the SAME image to "wood.jpg", apply it and export the same way... the texture shows just fine in Mission Editor. It seems like it's having a problem with the "." in the image name.
By the way, if I try to us:
1550.setSkinBase("plaster");
from the console on the DIF (which initializes gray), it doesn't change to the texture either. Just so I'm sure we are on the same page... you were suggesting that I apply a texture called "wall.blnd.jpg" as the base and "wall.plaster.jpg" as the skin (both located together with the DIF they're applied to), right?
Thanks.
#5
Can you provide me with your very simple test? I will be happy to try to step through the code to figure out what is going on.
You can try naming it "wall.base.jpg", I don't know why "blnd" appears in the code. Maybe I'm reading it wrong.
11/12/2007 (5:24 am)
Thats what I was going after. I'm a little upset it didn't work. I wish somebody who's done this before would speak up. :)Can you provide me with your very simple test? I will be happy to try to step through the code to figure out what is going on.
You can try naming it "wall.base.jpg", I don't know why "blnd" appears in the code. Maybe I'm reading it wrong.
#6
...hmm...never heard of setSkinBase?? I'll have to check that function? Must be new in the 1.5.* version??
...wow, it really is there?!! I hadn't purchased the 1.5 upgrade till very recently.
Looks like the string might have a maximum length restriction?? to 6 characters..?? seems to bail if name if over 6 characters long.....p-l-a-s-t-e-r is 7 characters in the string.
Also, try switching the base namingConvention position. I've found ShapeBase setSkinName; to work under the namingConvention of BASE.textureName.EXT... Try your textures named like this: "stucco.wall.EXT", "plstr.wall.EXT", with the base texture named as "base.wall.EXT.".
11/12/2007 (5:34 am)
That Class of object[Interior], I believe, doesn't not have the method/function[setSkinName], so I don't believe it will ever work[on DIFFs], until you change Source code. I 'think' setSkinName is scoped to the ShapeBase Class. Check your Source code.......hmm...never heard of setSkinBase?? I'll have to check that function? Must be new in the 1.5.* version??
...wow, it really is there?!! I hadn't purchased the 1.5 upgrade till very recently.
Looks like the string might have a maximum length restriction?? to 6 characters..?? seems to bail if name if over 6 characters long.....p-l-a-s-t-e-r is 7 characters in the string.
Also, try switching the base namingConvention position. I've found ShapeBase setSkinName; to work under the namingConvention of BASE.textureName.EXT... Try your textures named like this: "stucco.wall.EXT", "plstr.wall.EXT", with the base texture named as "base.wall.EXT.".
#7
base.t.jpg
blnd.t.jpg
new.t.jpg
t.base.jpg
t.blnd.jpg
t.new.jpg
I created 4 DIF's, one for each of the base texture naming approaches and applied textures accordingly:
DIF1 = base.t.jpg
DIF2 = t.base.jpg
DIF3 = blnd.t.jpg
DIF4 = t.blnd.jpg
In-game, DIF's 1, 2 and 3 appeared correctly, but #4 complained about not finding the image again. When I tried the approach:
1551.setSkinBase("new");
...on each of the DIF's, NONE of them worked (Note: The call was accepted in the console with no errors but the texture didn't change). Unless my syntax in the function call above is wrong (needs a path? no quotes?), I'm pretty confident that the report that this doesn't work is correct. Is it possible that, unlike StaticShape.setSkinName (which can be set anywhere from what I can tell), setSkinBase needs to be called at a different time (prior to mission load? not sure how this would work, but...)?
I can't think of a better test than this. I just keep feeling like I'm missing something very obvious.
11/12/2007 (8:22 am)
Those are interesting theories so I put them to the test. I created a series of textures in the various combinations and made sure none was more than 6 characters:base.t.jpg
blnd.t.jpg
new.t.jpg
t.base.jpg
t.blnd.jpg
t.new.jpg
I created 4 DIF's, one for each of the base texture naming approaches and applied textures accordingly:
DIF1 = base.t.jpg
DIF2 = t.base.jpg
DIF3 = blnd.t.jpg
DIF4 = t.blnd.jpg
In-game, DIF's 1, 2 and 3 appeared correctly, but #4 complained about not finding the image again. When I tried the approach:
1551.setSkinBase("new");
...on each of the DIF's, NONE of them worked (Note: The call was accepted in the console with no errors but the texture didn't change). Unless my syntax in the function call above is wrong (needs a path? no quotes?), I'm pretty confident that the report that this doesn't work is correct. Is it possible that, unlike StaticShape.setSkinName (which can be set anywhere from what I can tell), setSkinBase needs to be called at a different time (prior to mission load? not sure how this would work, but...)?
I can't think of a better test than this. I just keep feeling like I'm missing something very obvious.
#8
The method in InteriorInstance isn't checking the right path for the texture! I will try to post a fix here soon.
11/12/2007 (4:39 pm)
Okay, I think I know what is going on..The method in InteriorInstance isn't checking the right path for the texture! I will try to post a fix here soon.
#9
Replace InteriorInstance::renewOverlays() with this and recompile.
It should now include the path of the interior in the search. So.. texture have to be in the same folder as the .dif (this could be changed in code). This still uses the "name.blnd" as the base and "name.skin" as the skin name.
I ran a very simple test. Using Constructor I made a cube and applied the texture "wall.blnd.jpg" to it. I then exported it and loaded my engine, creating the object in world. Finally I set the skin base to "stucco" (my other texture's name is "wall.stucco.jpg") and watched as it instantly changed.
Here is the updated code:
As a note this is a crippled system that breaks after the first run ... The idea is that you should never have to reskin a dif more than once. If you do need to, some extra work must be done.
11/13/2007 (1:24 am)
Okay, here it is.Replace InteriorInstance::renewOverlays() with this and recompile.
It should now include the path of the interior in the search. So.. texture have to be in the same folder as the .dif (this could be changed in code). This still uses the "name.blnd" as the base and "name.skin" as the skin name.
I ran a very simple test. Using Constructor I made a cube and applied the texture "wall.blnd.jpg" to it. I then exported it and loaded my engine, creating the object in world. Finally I set the skin base to "stucco" (my other texture's name is "wall.stucco.jpg") and watched as it instantly changed.
Here is the updated code:
void InteriorInstance::renewOverlays()
{
StringTableEntry baseName = dStricmp(mSkinBase, "base") == 0 ? "blnd" : mSkinBase;
char resourcePath[256];
dStrncpy(resourcePath, mInteriorFileName, 256);
char *p = dStrrchr(resourcePath, '/');
if (p)
*(++p) = 0;
else
resourcePath[0] = 0;
for (U32 i = 0; i < mMaterialMaps.size(); i++)
{
MaterialList* pMatList = mMaterialMaps[i];
for (U32 j = 0; j < pMatList->mMaterialNames.size(); j++)
{
const char* pName = pMatList->mMaterialNames[j];
const U32 len = dStrlen(pName);
if (len < 6)
continue;
const char* possible = pName + (len - 5);
if (dStricmp(".blnd", possible) == 0)
{
char newName[256];
AssertFatal(len < 200, "InteriorInstance::renewOverlays: Error, len exceeds allowed name length");
dStrncpy(newName, pName, possible - pName);
newName[possible - pName] = '[[6281028964480]]';
dStrcat(newName, ".");
dStrcat(newName, baseName);
char fullName[256];
dStrcpy(fullName, resourcePath);
dStrcat(fullName, newName);
TextureHandle test = TextureHandle(fullName, MeshTexture, false);
if (test.getGLName() != 0)
{
pMatList->mMaterials[j] = test;
}
else
{
dStrncpy(newName, resourcePath, 256 - len);
dStrcat(newName, pName);
pMatList->mMaterials[j] = TextureHandle(newName, MeshTexture, false);
}
}
}
}
}As a note this is a crippled system that breaks after the first run ... The idea is that you should never have to reskin a dif more than once. If you do need to, some extra work must be done.
#10
If we have to go into code and make changes for it to work at all, maybe it makes sense to do it right (of course, that's easy for me to say with my limited C++ skills). Here are my thoughts:
1) It makes sense to use the same naming convention for skins, in general. base.meterialname.jpg is familiar for DTS, so it should make sense to use it on DIF's too. Also, I just find that this convention reads well -- for instance, base.shoes.jpg, red.shoes.jpg, green.shoes.jpg, etc. The BLND thing just seems confusing and I don't get its point (if you see it differently, let me know).
2) Why not skin the object, inline, in the MIS file? In the interest of true re-use, we all would like a world where we could create a DTS or DIF and apply skins to it all day long. It uses less objects, I suspect would have a smaller memory footprint (although I'm not sure) and makes for a faster art pipeline (you don't have to reskin and resave in Constructor just to change a texture -- I loved this about UnrealEd). If your game is an online game, this becomes a MUST. How about an approach like I describe above, mixed with the current approach for BOTH DTS and DIF? For instance (this as the initial state of the object):
new InteriorInstance() {
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile = "~/data/interiors/stucco.wall.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
...combined with a scriptable counterpart:
InteriorInstance.setSkinName("~/data/interiors/torched.wall.jpg");
Notice I used the same method name used on the StaticShape object? Much like the StaticShape implementation, it would look for a match in the naming convention of the file provided and materials on the object and skin the appropriate material.
3) Perhaps applying multiple skins could take an approach like:
new InteriorInstance() {
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile[0] = "~/data/interiors/stucco.wall.jpg";
skinFile[1] = "~/data/interiors/tile.floor.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
..and do the same in StaticShape. Currently, if you have a StaticShape with MULTIPLE materials and you use the setSkinName method, it can only be used once (I believe) and it automatically searches for the other material of the same mask, which may not be appropriate. For instance, if I have DTS house (for discussion) with two materials -- wall and roof -- and I setSkinName("brick"); it looks for "brick.wall.jpg" and "brick.floor.jpg". This could use a rewrite like above.
I don't know if any of this is possible, but it does seem close to other approaches I've seen already in the code and the general idea is very valuable, I think. What do you think? Possible? Advisable?
Brian: Also when you use the approach in your code to reskin a DIF, does it force a scene relight? What effect does this have on lighting?
I think that's partially where I was going with the #2 suggestion -- to skin AT mission load so lighting can take place.
11/13/2007 (1:46 pm)
Thank you so much Brian. I'll give this a shot.If we have to go into code and make changes for it to work at all, maybe it makes sense to do it right (of course, that's easy for me to say with my limited C++ skills). Here are my thoughts:
1) It makes sense to use the same naming convention for skins, in general. base.meterialname.jpg is familiar for DTS, so it should make sense to use it on DIF's too. Also, I just find that this convention reads well -- for instance, base.shoes.jpg, red.shoes.jpg, green.shoes.jpg, etc. The BLND thing just seems confusing and I don't get its point (if you see it differently, let me know).
2) Why not skin the object, inline, in the MIS file? In the interest of true re-use, we all would like a world where we could create a DTS or DIF and apply skins to it all day long. It uses less objects, I suspect would have a smaller memory footprint (although I'm not sure) and makes for a faster art pipeline (you don't have to reskin and resave in Constructor just to change a texture -- I loved this about UnrealEd). If your game is an online game, this becomes a MUST. How about an approach like I describe above, mixed with the current approach for BOTH DTS and DIF? For instance (this as the initial state of the object):
new InteriorInstance() {
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile = "~/data/interiors/stucco.wall.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
...combined with a scriptable counterpart:
InteriorInstance.setSkinName("~/data/interiors/torched.wall.jpg");
Notice I used the same method name used on the StaticShape object? Much like the StaticShape implementation, it would look for a match in the naming convention of the file provided and materials on the object and skin the appropriate material.
3) Perhaps applying multiple skins could take an approach like:
new InteriorInstance() {
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile[0] = "~/data/interiors/stucco.wall.jpg";
skinFile[1] = "~/data/interiors/tile.floor.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
..and do the same in StaticShape. Currently, if you have a StaticShape with MULTIPLE materials and you use the setSkinName method, it can only be used once (I believe) and it automatically searches for the other material of the same mask, which may not be appropriate. For instance, if I have DTS house (for discussion) with two materials -- wall and roof -- and I setSkinName("brick"); it looks for "brick.wall.jpg" and "brick.floor.jpg". This could use a rewrite like above.
I don't know if any of this is possible, but it does seem close to other approaches I've seen already in the code and the general idea is very valuable, I think. What do you think? Possible? Advisable?
Brian: Also when you use the approach in your code to reskin a DIF, does it force a scene relight? What effect does this have on lighting?
I think that's partially where I was going with the #2 suggestion -- to skin AT mission load so lighting can take place.
#11
The engine doesn't automatically relight, you need to do that (I clicked the button in the editor, you'll have to do it some other way).
Sometimes you might not need to relight, since only the texture is changing, I dunno...
Anyways, it should be a pretty simple process to get it into the datablock.
11/13/2007 (4:28 pm)
I think I can implement something like that pretty easily. I'll give it some thought. That sounds alot better than the way it currently works.The engine doesn't automatically relight, you need to do that (I clicked the button in the editor, you'll have to do it some other way).
Sometimes you might not need to relight, since only the texture is changing, I dunno...
Anyways, it should be a pretty simple process to get it into the datablock.
#12
Thanks again.
EDIT: Still working on it. It wasn't as straight forward as I had hoped. In the meanwhile, Brian, I had a thought... I wonder if attributes like this are possible:
skinFile["wall"] = "~/data/interiors/stucco.wall.jpg";
..where "wall" is the material name (as in "base.wall.jpg").
Then the approach could be:
new InteriorInstance() {
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile["wall"] = "~/data/interiors/stucco.jpg";
skinFile["floor"] = "~/data/interiors/tile.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
This approach encourages more reuse because it does not tie you to the naming convention for the file (so the same brick.jpg could be used as a wall, a floor and across different types of objects) and it allows you to skin a particular material if you choose, again using the same texture across multiple objects -- path is given so it doesn't have to assume they're always in the same directory. I haven't had much time to think about the pros and cons of this idea yet, but I thought I'd share it anyway.
11/13/2007 (7:26 pm)
Brian: Excellent! Your code definitely works. Now, it may be that I created a simpler example (only a simple cube in my DIF with a 64px texture) but I can change it several times and it never seems to crash -- from texture 1 to 2 to 3 and back to 1. I will definitely see what I can learn from your example and give this a go on my own. I'll see if I can get any of my ideas to work. It's about time I throw off the C++ intimidation and finally give this a try (it's not completely foreign -- just been a long time). I'll report back if I get anywhere.Thanks again.
EDIT: Still working on it. It wasn't as straight forward as I had hoped. In the meanwhile, Brian, I had a thought... I wonder if attributes like this are possible:
skinFile["wall"] = "~/data/interiors/stucco.wall.jpg";
..where "wall" is the material name (as in "base.wall.jpg").
Then the approach could be:
new InteriorInstance() {
position = "121.267 -106.427 210.77";
rotation = "1 0 0 0";
scale = "1 1 1";
interiorFile = "~/data/interiors/wall.dif";
skinFile["wall"] = "~/data/interiors/stucco.jpg";
skinFile["floor"] = "~/data/interiors/tile.jpg";
useGLLighting = "0";
showTerrainInside = "0";
};
This approach encourages more reuse because it does not tie you to the naming convention for the file (so the same brick.jpg could be used as a wall, a floor and across different types of objects) and it allows you to skin a particular material if you choose, again using the same texture across multiple objects -- path is given so it doesn't have to assume they're always in the same directory. I haven't had much time to think about the pros and cons of this idea yet, but I thought I'd share it anyway.
#13
I'm not sure about the best way to implement the hash-array, skinFile. Are hash arrays supported already? Maybe something like:
new InteriorInstance() {
interiorFile = "~/data/interiors/wall.dif";
skinFile = "wall, ~/data/interiors/stucco.jpg";
skinFile = "floor, ~/data/interiors/tile.jpg";
};
Each time skinFile is a set a function would be called that inserts it into an array.
Then we can apply the skins within the onNewDataBlock method and all should be well...................
11/14/2007 (9:06 pm)
I like where you are going with this.I'm not sure about the best way to implement the hash-array, skinFile. Are hash arrays supported already? Maybe something like:
new InteriorInstance() {
interiorFile = "~/data/interiors/wall.dif";
skinFile = "wall, ~/data/interiors/stucco.jpg";
skinFile = "floor, ~/data/interiors/tile.jpg";
};
Each time skinFile is a set a function would be called that inserts it into an array.
Then we can apply the skins within the onNewDataBlock method and all should be well.........
#14
new InteriorInstance() {
interiorFile = "~/data/interiors/wall.dif";
skinBase = "tile";
};
This allows you to set a new base, much like the skinName in StaticShape. It turns "wall.blnd.jpg" into "wall.tile.jpg". But, just like the setSkinBase function it wasn't functioning out of the box. I think someone disabled this functionality intentionally. Maybe they found issues with the whole approach. I need to test more. Anyway, if you just combine your fix above with one more line in initPersistFields:
addField("skinBase", TypeFilename, Offset(mskinBase, InteriorInstance));
...you're in business. This approach, much like the StaticShape approach, sets the skinBase for ALL textures on the DIF so if you have "floor.blnd.jpg" and "ceiling.blnd.jpg", Torque goes looking for "floor.tile.jpg" and "ceiling.tile.jpg".
I was hoping you might take another look at this to see if you can get my approach to work, where we specify a given "base" and it skins ONLY that base? If I had my way:
1) The naming convention would be identical to StaticShape and the files would be "base.wall.jpg" and not "wall.blnd.jpg". It's just is unnecessarily confusing and prohibits art reuse.
2) We might use an approach where we specify the particular base to be skinned in the MIS property, for instance "skinBase["wall"] = "tile";" where "wall" is the prefix? Ideally, we would just specify an entire filename and path (so a wall texture could be a floor or a ceiling too and bases don't matter) but I don't know of another index to use to identify the material (e.g. skinBase[0] = "mygame/data/interiors/tile.wall.jpg";). To answer your question about array, I found a similar usage in the Sky object. Look at "cloudHeightPer[0] = "0.1"; ". Of course, I didn't have the slightest idea how to make this work with my C++ limitations.
What do you think?
11/29/2007 (9:32 am)
Brian: I made a small amount of progress but my limited C++ skill is holding me back. I thought you would like to know that there seems to already be a property to skin a DIF called "skinBase" which can be added to the InteriorInstance, like:new InteriorInstance() {
interiorFile = "~/data/interiors/wall.dif";
skinBase = "tile";
};
This allows you to set a new base, much like the skinName in StaticShape. It turns "wall.blnd.jpg" into "wall.tile.jpg". But, just like the setSkinBase function it wasn't functioning out of the box. I think someone disabled this functionality intentionally. Maybe they found issues with the whole approach. I need to test more. Anyway, if you just combine your fix above with one more line in initPersistFields:
addField("skinBase", TypeFilename, Offset(mskinBase, InteriorInstance));
...you're in business. This approach, much like the StaticShape approach, sets the skinBase for ALL textures on the DIF so if you have "floor.blnd.jpg" and "ceiling.blnd.jpg", Torque goes looking for "floor.tile.jpg" and "ceiling.tile.jpg".
I was hoping you might take another look at this to see if you can get my approach to work, where we specify a given "base" and it skins ONLY that base? If I had my way:
1) The naming convention would be identical to StaticShape and the files would be "base.wall.jpg" and not "wall.blnd.jpg". It's just is unnecessarily confusing and prohibits art reuse.
2) We might use an approach where we specify the particular base to be skinned in the MIS property, for instance "skinBase["wall"] = "tile";" where "wall" is the prefix? Ideally, we would just specify an entire filename and path (so a wall texture could be a floor or a ceiling too and bases don't matter) but I don't know of another index to use to identify the material (e.g. skinBase[0] = "mygame/data/interiors/tile.wall.jpg";). To answer your question about array, I found a similar usage in the Sky object. Look at "cloudHeightPer[0] = "0.1"; ". Of course, I didn't have the slightest idea how to make this work with my C++ limitations.
What do you think?
#15
I missed your last post until just now!
Anyways, I'll see if I can't spend some time on a better skinning system for you soon.
The array you mention is just a plain index array, not a hash array so it won't quite work how it would be needed. I really don't think we can index something like that in a datablock.
What do you think of this method? I don't know when I'll have time to implement it but I'll see what I can do.
optionally specifying full filenames would work as well:
12/08/2007 (8:24 am)
Hi Masser,I missed your last post until just now!
Anyways, I'll see if I can't spend some time on a better skinning system for you soon.
The array you mention is just a plain index array, not a hash array so it won't quite work how it would be needed. I really don't think we can index something like that in a datablock.
What do you think of this method? I don't know when I'll have time to implement it but I'll see what I can do.
new InteriorInstance() {
interiorFile = "~/data/interiors/wall.diff";
skinBase[0] = "wall";
skinMaterial[0] = "stucco";
skinBase[1] = "floor";
skinMaterial[1] = "cement";
skinBase[2] = "ceiling";
skinMaterial[2] = "tile";
};
input:
wall.base.jpg or wall.jpg
floor.base.jpg or floor.jpg
ceiling.base.jpg or ceiling.jpg
output:
wall.stucco.jpg
floor.cement.jpg
ceiling.tile.jpgoptionally specifying full filenames would work as well:
new InteriorInstance() {
interiorFile = "~/data/interiors/wall.diff";
skinBase[0] = "wall";
skinMaterial[0] = "myWallTexture";
skinBase[1] = "floor";
skinMaterial[1] = "myFloorTexture";
skinBase[2] = "ceiling";
skinMaterial[2] = "myCeilingTexture";
};
input:
wall.base.jpg or wall.jpg
floor.base.jpg or floor.jpg
ceiling.base.jpg or ceiling.jpg
output:
myWallTexture.jpg
myFloorTexturejpg
myCeilingTexture.jpg
#16
skinFile[0] = "mygame.fps/data/interiors/tile.jpg";
skinFile[1] = "mygame.fps/data/interiors/brick.jpg";
I basically threw out all of the renewOverlays() code, introduced my own array and completely sidestepped that "base/blnd" junk that really didn't belong IMO (it's a good naming convention but really inhibits re-use across objects). It gave me free reign to put my images where I want (no more "base" naming -- just a full path to the image you want).
It worked like a charm but upon further testing, it seems very unstable. I have to ask a dumb C++ question: I'm trying to get to the pre-existing textures assigned to each material (the ones used before the reskinning takes place) and I don't know how to reference it. I think it's in pMatList->mMaterials. It seems to contain an array of material objects and each contains a texFileName property, which has what I want. Assuming I'm iterating through the MaterialList (e.g. pMatList->mMaterials[j]), how do I reference this property? if you debug the existing interiorinstance.cc (breakpoint within renewOverlays()) and put a Watch on pMatList->mMaterials, you'll see what I mean.
Oh, one more thing... do you know what code is necessary in renewOverlays() to allow me to specify RELATIVE filepaths, like "~/data/interiors/tile.jpg" instead of "mygame.fps/data/interiors/tile.jpg"? I could only get the latter to work. I have to feed it to "TextureHandle([file path here], MeshTexture, false)". If there is an example in another class (not using the ResourceManager), please let me know where.
12/09/2007 (11:31 am)
Brian: I took a new approach since we last posted: Since the Constructor export files (the TXT file created at export) seemed to list a predictable material order, I didn't see any harm in taking a different approach. I discovered (like you said) that if I was going to have any array examples to work from, I would have to index it with the number instead of a string. So I went with:skinFile[0] = "mygame.fps/data/interiors/tile.jpg";
skinFile[1] = "mygame.fps/data/interiors/brick.jpg";
I basically threw out all of the renewOverlays() code, introduced my own array and completely sidestepped that "base/blnd" junk that really didn't belong IMO (it's a good naming convention but really inhibits re-use across objects). It gave me free reign to put my images where I want (no more "base" naming -- just a full path to the image you want).
It worked like a charm but upon further testing, it seems very unstable. I have to ask a dumb C++ question: I'm trying to get to the pre-existing textures assigned to each material (the ones used before the reskinning takes place) and I don't know how to reference it. I think it's in pMatList->mMaterials. It seems to contain an array of material objects and each contains a texFileName property, which has what I want. Assuming I'm iterating through the MaterialList (e.g. pMatList->mMaterials[j]), how do I reference this property? if you debug the existing interiorinstance.cc (breakpoint within renewOverlays()) and put a Watch on pMatList->mMaterials, you'll see what I mean.
Oh, one more thing... do you know what code is necessary in renewOverlays() to allow me to specify RELATIVE filepaths, like "~/data/interiors/tile.jpg" instead of "mygame.fps/data/interiors/tile.jpg"? I could only get the latter to work. I have to feed it to "TextureHandle([file path here], MeshTexture, false)". If there is an example in another class (not using the ResourceManager), please let me know where.
#17
but re getting the original texture names of materials on an interior, this might help:
12/09/2007 (11:45 am)
I don't know anything about renewOverlays,but re getting the original texture names of materials on an interior, this might help:
for (U32 i = 0; i < mMaterialMaps.size(); i++)
{
MaterialList* pMatList = mMaterialMaps[i];
for (U32 j = 0; j < pMatList->mMaterialNames.size(); j++)
{
const char* pName = pMatList->mMaterialNames[j];
// do stuff
}
}
#18
12/09/2007 (2:08 pm)
Orion: Exactly. That's how I get the names of the textures, but now I need the complete path. It doesn't look as though TextureHandle accepts anything other than a full path to the file. pMatList->mMaterials seems to contain the entire path (texFileName). Of course, I may be wrong with my limited C++ debugging skills.
#19
yes - we either require the full path to the new texture to be passed in,
or assume the new texture file is a sibling of the DIF file and generate the full path based on mInteriorRes.getFilePath().
- which is definitely a bit limiting.
12/09/2007 (2:25 pm)
Ah gotcha; sorry.yes - we either require the full path to the new texture to be passed in,
or assume the new texture file is a sibling of the DIF file and generate the full path based on mInteriorRes.getFilePath().
- which is definitely a bit limiting.
#20
However, do you know how to retrieve that property I referred to above? If we had that it would provide the texture wherever it is and not assume the same directory. If memeory servers (not in front of my dev system), in Watch List it looked like pMatList->mMaterials.mArray.object.textFileName. How would I reference that in code?
12/09/2007 (5:25 pm)
That's actually not a bad move. It's better than what I have now and in the case of re-applying the existing textures (which is why I needed it -- for materials not specified) it might get the job done.However, do you know how to retrieve that property I referred to above? If we had that it would provide the texture wherever it is and not assume the same directory. If memeory servers (not in front of my dev system), in Watch List it looked like pMatList->mMaterials.mArray.object.textFileName. How would I reference that in code?
Torque Owner Michael Bacon
Default Studio Name
Make your dif with a certain texture. You must name the texture starting with "base." so for example: "base.wall.jpg". Then create your skins and nam e them with the same ending. In your case. "stucco.wall.jpg". Make sure these textures are in the same folder.
Then just call setSkinBase("stucco"); on your object.
The naming is the hardest part I think but once you get that down it should work.
Still, maybe its broken for difs.
2. No, there is no longer a source repository. And no, there is no newer source than 1.5.2 unless you get some kind of prerelease.
*Edit: Just like to say that I really don't like the skinning methods implemented here and would be happy to change them if anyone gives me a design for a better method.