Terrain texture properties
by Lidwine Simon · in Torque Game Engine · 06/05/2004 (11:26 am) · 19 replies
Hi,
I was searching how to add properties to the textures (to decrease maxWheelSpeed on sand for example), and it seems the infrastructure was already there but not used. I don't know if it was a good idea to use it (maybe some old hack?), but with some code it works. If it may help someone, I post it :
in terrain/terrData.cc, in terrainBlock::onAdd(), replace
with
and replace
with
I add a "speed" property for the sand in this file :
To add this new parameter, in dgl/materialPropertyMap.h, after the line
To access this new parameter, in dgl/materialPropertyMap.cc, in MaterialPropertyMap::addMapping(..), after
and after
Now, to get the texture and its properties under the car, in game/vehicle/wheeledVehicle.cc, add
and you can use it with code like
I m not proud of this code, seems like a hack, but it works...
sorry for bad english!
I was searching how to add properties to the textures (to decrease maxWheelSpeed on sand for example), and it seems the infrastructure was already there but not used. I don't know if it was a good idea to use it (maybe some old hack?), but with some code it works. If it may help someone, I post it :
in terrain/terrData.cc, in terrainBlock::onAdd(), replace
StringTableEntry fn = mMaterialFileName[0];
with
for (int i=0; i<TerrainBlock::MaterialGroups; i++)
{
//StringTableEntry fn = mMaterialFileName[0];
StringTableEntry fn = mMaterialFileName[i];
if (fn != NULL)
{and replace
mMPMIndex[0] = pMatMap->getIndexFromName( fn );
with
mMPMIndex[i] = pMatMap->getIndexFromName( fn );
}
else
mMPMIndex[i] = -1;
}So you get the index of the textures and their properties defined in the file ~/data/terrain/propertyMap.csI add a "speed" property for the sand in this file :
addMaterialMapping( "racing/data/terrains/highplains/grass" , "sound: 0" , "color: 0.46 0.36 0.26 0.4 0.0" ); addMaterialMapping( "racing/data/terrains/highplains/sand" , [b]"speed:15"[/b], "sound: 0" , "color: 0.46 0.36 0.26 0.4 0.0" );
To add this new parameter, in dgl/materialPropertyMap.h, after the line
ColorF puffColor[2];add
F32 speed;
To access this new parameter, in dgl/materialPropertyMap.cc, in MaterialPropertyMap::addMapping(..), after
pEntry->matFlags = 0;add
pEntry->speed = 40;
and after
pEntry->detailMapName = StringTable->insert(pColon);
}addelse if (dStrnicmp(param, "speed:", dStrlen("speed:")) == 0) {
// Set the detail map
const char* pSpeed = dStrchr(param, ':');
pSpeed++;
while (*pSpeed == ' ' || *pSpeed == '\t')
pSpeed++;
pEntry->speed = dAtof(pSpeed);
}Now, to get the texture and its properties under the car, in game/vehicle/wheeledVehicle.cc, add
S32 WheeledVehicle::getTerrainMapIndex(float distance, Point3F& pt)
{
RayInfo rInfo;
U8 alphas[TerrainBlock::MaterialGroups];
int mapIndex = -1;
if (gClientContainer.castRay(pt,
Point3F(pt.x, pt.y, pt.z - distance ),
TerrainObjectType, &rInfo)) {
TerrainBlock* ter = static_cast<TerrainBlock*>(rInfo.object);
Point2I gPos;
const MatrixF & mat = ter->getTransform();
Point3F origin;
mat.getColumn(3, &origin);
F32 squareSize = (F32) ter->getSquareSize();
F32 halfSquareSize = squareSize / 2;
float x = (pt.x - origin.x + halfSquareSize) / squareSize;
float y = (pt.y - origin.y + halfSquareSize) / squareSize;
ter->getMaterialAlpha(Point2I(x,y), alphas);
MaterialPropertyMap* matMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
if (matMap != NULL)
{
U8 maxAlpha = alphas[0];
U8 maxAlpha2;
int indexTexture = 0;
for (int i=1; i<TerrainBlock::MaterialGroups; i++)
{
maxAlpha2 = getMax(alphas[i],maxAlpha);
if (maxAlpha2 != maxAlpha)
{
indexTexture = i;
maxAlpha = maxAlpha2;
}
}
mapIndex = ter->mMPMIndex[indexTexture];
}
}
return mapIndex;
}(Thanks for the getTerrainTexture function!)and you can use it with code like
MaterialPropertyMap* matMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
S32 mapIndex = getTerrainMapIndex(2.0f,rInfo2.point);
if (mapIndex != -1)
{
const MaterialPropertyMap::MapEntry *pEntry = matMap->getMapEntryFromIndex(mapIndex);
if (pEntry != NULL)
{
F32 new_speed = pEntry->speed;
.......
}
}I m not proud of this code, seems like a hack, but it works...
sorry for bad english!
About the author
#2
06/05/2004 (12:29 pm)
I'll test this code tonight... but you may have just fixed the footpuff color problem that has been around for 2 years
#3
I got the materialmapping working with the player .
Really great Lidwine i cant thank you enoth for this,i think i have to buy you a beer Later :):)
06/05/2004 (6:41 pm)
Wow Super Great :)I got the materialmapping working with the player .
Really great Lidwine i cant thank you enoth for this,i think i have to buy you a beer Later :):)
#4
Below are the changes:
In terrain/terrData.cc, in terrainBlock::onAdd(), replace
with
and replace
with
Now the big change is in the getTerrainMapIndex function, we need a generic function that can be used anywhere. So what we do is this:
in terrData.h add the function declaration:
before:
After adding the function declaration
Now in terrData.cc we need to add the following function:
Usage will depend on the class you're using this with.
For example with the player you might do something like:
06/05/2004 (10:44 pm)
OK made some changes to kick this over to being more general.Below are the changes:
In terrain/terrData.cc, in terrainBlock::onAdd(), replace
StringTableEntry fn = mMaterialFileName[0];
with
for (int i = 0; i < TerrainBlock::MaterialGroups; i++)
{
StringTableEntry fn = mMaterialFileName[i];
if (fn != NULL)
{and replace
mMPMIndex[0] = pMatMap->getIndexFromName( fn );
with
mMPMIndex[i] = pMatMap->getIndexFromName( fn ); } else mMPMIndex[i] = -1; }
Now the big change is in the getTerrainMapIndex function, we need a generic function that can be used anywhere. So what we do is this:
in terrData.h add the function declaration:
before:
void setBaseMaterial(U32 x, U32 y, U8 matGroup); U8 *getMaterialAlphaMap(U32 matIndex);
After adding the function declaration
void setBaseMaterial(U32 x, U32 y, U8 matGroup); S32 getTerrainMapIndex(Point3F& pt); U8 *getMaterialAlphaMap(U32 matIndex);
Now in terrData.cc we need to add the following function:
S32 TerrainBlock::getTerrainMapIndex(Point3F& pt)
{
U8 alphas[MaterialGroups];
int mapIndex;
const MatrixF & mat = getTransform();
Point3F origin;
mat.getColumn(3, &origin);
F32 squareSize = (F32) getSquareSize();
F32 halfSquareSize = squareSize / 2;
float x = (pt.x - origin.x + halfSquareSize) / squareSize;
float y = (pt.y - origin.y + halfSquareSize) / squareSize;
getMaterialAlpha(Point2I(x,y), alphas);
MaterialPropertyMap* matMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
if (matMap != NULL)
{
U8 maxAlpha = alphas[0];
U8 maxAlpha2;
int indexTexture = 0;
for (int i=1; i<MaterialGroups; i++)
{
maxAlpha2 = getMax(alphas[i],maxAlpha);
if (maxAlpha2 != maxAlpha)
{
indexTexture = i;
maxAlpha = maxAlpha2;
}
}
mapIndex = mMPMIndex[indexTexture];
}
return mapIndex;
}Usage will depend on the class you're using this with.
For example with the player you might do something like:
Point3F rot, pos;
RayInfo rInfo;
MatrixF mat = getRenderTransform();
mat.getColumn(1, &rot);
mat.mulP(Point3F(offset,0.0f,0.0f), &pos);
if (gClientContainer.castRay(Point3F(pos.x, pos.y, pos.z + 0.01f),
Point3F(pos.x, pos.y, pos.z - 2.0f ),
TerrainObjectType, &rInfo))
{
if( rInfo.object->getTypeMask() & TerrainObjectType)
{
TerrainBlock* tBlock = static_cast<TerrainBlock*>(rInfo.object);
S32 mapIndex = tBlock->getTerrainMapIndex(rInfo.point);
if (mapIndex != -1)
{
MaterialPropertyMap* pMatMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
const MaterialPropertyMap::MapEntry* pEntry = pMatMap->getMapEntryFromIndex(mapIndex);
if(pEntry)
{
..........................
}
}
}
}
#6
Very nice work - this will work out fine on stuff I'm working on
06/06/2004 (1:59 am)
Post as resource please and you get a 5 from me!Very nice work - this will work out fine on stuff I'm working on
#8
06/14/2004 (11:36 am)
Added update to allow for arbitrary terrain properties to head...
#9
Also, the SceneImmerse engine had the capacity to make different footfall sounds depending on terrain, TERRAIN_SAND, TERRAIN_METAL etc. This could do that too, no?
08/13/2004 (10:20 am)
Can this be used to change player/vehicle movement speeds over different types of terrain?? :)Also, the SceneImmerse engine had the capacity to make different footfall sounds depending on terrain, TERRAIN_SAND, TERRAIN_METAL etc. This could do that too, no?
#10
08/13/2004 (1:00 pm)
Yes to both. I think Tribes 2 did have code to do the latter feature; not sure it made it into the current incarnation of Torque, though.
#12
// Footstep Sounds
FootSoftSound = FootLightSoftSound;
FootHardSound = FootLightHardSound;
FootMetalSound = FootLightMetalSound;
FootSnowSound = FootLightSnowSound;
FootShallowSound = FootLightShallowSplashSound;
FootWadingSound = FootLightWadingSound;
FootUnderwaterSound = FootLightUnderwaterSound;
That is sound from texture, isn't it? It's in the .cs but I can't find any link or chain through to actual code. Is it a lost Tribes2 feature maybe?
08/16/2004 (7:14 pm)
Incidentlally, I've seen these in a player block:// Footstep Sounds
FootSoftSound = FootLightSoftSound;
FootHardSound = FootLightHardSound;
FootMetalSound = FootLightMetalSound;
FootSnowSound = FootLightSnowSound;
FootShallowSound = FootLightShallowSplashSound;
FootWadingSound = FootLightWadingSound;
FootUnderwaterSound = FootLightUnderwaterSound;
That is sound from texture, isn't it? It's in the .cs but I can't find any link or chain through to actual code. Is it a lost Tribes2 feature maybe?
#13
You set what sounds playing in propertymap.cs
like this
FootSoftSound = sound: 0
FootHardSound = sound: 1
..
08/17/2004 (12:05 pm)
@AndrewYou set what sounds playing in propertymap.cs
like this
addMaterialMapping("texture" , "sound:0" ," color:0.46 0.46 0.46 0.4 0.0 ");FootSoftSound = sound: 0
FootHardSound = sound: 1
..
#14
10/26/2005 (12:31 pm)
This code is in Torque. (Resolving issue #16.)
#15
One thing I plan to change about it is to add some sort of material datablock, similar to what TSE does I think, then map that material datablock to the texture. That way, if you have multiple rock textures, but they should all have the same sorts of properties, sounds footpuffs etc, you'd only have to change the values in one spot when tweaking later on.
so it would be something more like
10/26/2005 (12:46 pm)
I've been doing something like this in my game, but for more properties. One thing I plan to change about it is to add some sort of material datablock, similar to what TSE does I think, then map that material datablock to the texture. That way, if you have multiple rock textures, but they should all have the same sorts of properties, sounds footpuffs etc, you'd only have to change the values in one spot when tweaking later on.
so it would be something more like
datablock MaterialDataBlock(MaterialRock)
{
sound = blahprofile;
color = "blahblah";
slipperiness = infinity;
otherproperty = othervalue;
};
addMaterialMapping("rock1", MaterialRock);
addMaterialMapping("rock2", MaterialRock);
addMaterialMapping("rock3", MaterialRock);
addMaterialMapping("rock4", MaterialRock);
#16
i.e.
Under these circumstances the getIndexFromName does not locate the index because the
bool TerrainBlock::onAdd() strips the path off.
To fix, modify the bool TerrainBlock::onAdd()
11/19/2005 (7:08 pm)
My propertymap.cs uses full paths to distinguish terrain textures of the same name from each other.i.e.
addMaterialMapping( "~/data/terrains/grassland/sand" , "sound: 0" , "color: 1.0 0.50 0.16 0.8 0.0" );
Under these circumstances the getIndexFromName does not locate the index because the
bool TerrainBlock::onAdd() strips the path off.
To fix, modify the bool TerrainBlock::onAdd()
for (int i = 0; i < TerrainBlock::MaterialGroups; i++)as follows
for (int i = 0; i < TerrainBlock::MaterialGroups; i++)
{
StringTableEntry fn = mMaterialFileName[i];
if (fn != NULL)
{
if(!dStrncmp(fn, "terrain.", 8))
fn += 8;
char nameBuff[512];
/*
dStrcpy(nameBuff, mTerrFileName);
const char *p = dStrrchr(fn, '/');
if(p) p++;
else p = nameBuff;
mMPMIndex[i] = pMatMap->getIndexFromName( p );
*/
//duncan auto-Foliage mod - getIndexFromName requires the whole path - "~/data/terrains/grassland/sand"
nameBuff[0] = '~';
const char *p = dStrchr(fn, '/');
if(p)dStrcpy(&nameBuff[1], p);
else dStrcpy(nameBuff,fn);
mMPMIndex[i] = pMatMap->getIndexFromName( nameBuff );
}
else mMPMIndex[i] = -1;
}
#17
Running the stock demo, I 'thought' I had footstep sounds playing. I added in the Tim A. Environment Pack I and it had some textures with common names. I believe "grass" is the culprit here/now for this example. It overwrote my default texture in that mission and that seemed to break the functionality, while the other mission files I maintain in my assets it didn't. Fine, great, I expect that. What's odd is that even if the mission doesn't contain any of the textures with the addMaterialMapping properties in it, the sounds play. My example for this is the BraveTree Environment Pack I, Plateau mission. I get footstep sounds in that mission, without any of the textures in the Terrain Texture Editor having been reference in the addMaterialMapping properties file???? And to fix my Stronghold.mis file I had to use full paths to the textures!!??!! I don't understand textures and the Editor/MissionTree structure.
And what is the difference between the textures in the Terrain Texture Editor and the Terrain Texture Painter??? I find having two GUI's a bit confusing[v1.3], and don't understand fully how they function. I noticed that I had paths that were 'bad'/nonexistent and the textures seemed to be in the mission, while I've had other textures not be in the right folder and they appear as grey space on the terrain...it seemed to be dependent on which Editor they appear in?? Not entire sure about that...
Also, on the Editor/Creator: I notice that when I invoke the Mission Editor, it compiles and loads some files and then I always get a warning about the "grass" texture not being found?? Even though it's in the right location??? Is this a hard coded C++ thing??
some of my MissionEditor/Creator questions about texturing...
Thanks, sorry to go off topic a little...
Rex
02/08/2006 (9:28 am)
I noticed something odd about propertyMap.cs and the textures/mission/terrain files.Running the stock demo, I 'thought' I had footstep sounds playing. I added in the Tim A. Environment Pack I and it had some textures with common names. I believe "grass" is the culprit here/now for this example. It overwrote my default texture in that mission and that seemed to break the functionality, while the other mission files I maintain in my assets it didn't. Fine, great, I expect that. What's odd is that even if the mission doesn't contain any of the textures with the addMaterialMapping properties in it, the sounds play. My example for this is the BraveTree Environment Pack I, Plateau mission. I get footstep sounds in that mission, without any of the textures in the Terrain Texture Editor having been reference in the addMaterialMapping properties file???? And to fix my Stronghold.mis file I had to use full paths to the textures!!??!! I don't understand textures and the Editor/MissionTree structure.
And what is the difference between the textures in the Terrain Texture Editor and the Terrain Texture Painter??? I find having two GUI's a bit confusing[v1.3], and don't understand fully how they function. I noticed that I had paths that were 'bad'/nonexistent and the textures seemed to be in the mission, while I've had other textures not be in the right folder and they appear as grey space on the terrain...it seemed to be dependent on which Editor they appear in?? Not entire sure about that...
Also, on the Editor/Creator: I notice that when I invoke the Mission Editor, it compiles and loads some files and then I always get a warning about the "grass" texture not being found?? Even though it's in the right location??? Is this a hard coded C++ thing??
some of my MissionEditor/Creator questions about texturing...
Thanks, sorry to go off topic a little...
Rex
#18
03/02/2006 (2:49 pm)
Are these updates in TGE 1.4?
#19
03/02/2006 (4:45 pm)
The stuff prior to Ben's post is in TGE1.4
Torque 3D Owner Stephen Zepp