twSurfaceReference Object
by Ken Finney · 12/13/2002 (3:12 pm) · 36 comments
Download Code File
The twSurfaceReference object is a TGE enhancement used to create an accessible reference to the texture/surface characteristics of any point on a terrain.
The example included provides code fragments that allows you to modify the fxGrassReplicator to use this capability.
You must have the fxGressReplicator by Bendik Stang already installed in your game.
You can also apply the same changes to all of the replicator objects created by Melv May to get them to work the same way.
This resource assumes that you are familiar with the fxGrassReplicator, TGE, VC++, C++ programming, TGE script programming and the example scripts. If you are familiar with these things, then you should be able to resolve any conflicts that arise with these changes. If you have made changes or enhancements to any of the TGE source code or scripts, I can't warrant that this resource will work.
Installation
============
Back up your game source code and scripts prior to installation of this enhancement.
Engine Source changes
---------------------
1. Copy the files:
twSurfaceReference.cc
twSurfaceReference.h
from the twStructureReference.zip into the engine directory where your
fxGrassReplicator files reside.
2. Add both files to your TGE project.
3. Open fxGrassReplicator.cc
3a. Add this include to near the end of the includes at the top,
BEFORE the include for fxGrassReplicator.h.
3b. Add this function to any place you like within the file:
3c. Add the following lines to the end of the function initPersistFields()
3d. In the function CreateGrass() AFTER these lines:
add the following fragment:
3e. In the function packUpdate() AFTER these lines:
add the following fragment:
3f. In the function unpackUpdate() AFTER these lines:
add the following fragment:
4. Open fxGrassReplicator.h
4a. AFTER these lines:
add the following fragment:
4b. AFTER these lines:
add the following fragment:
4c. AFTER these lines:
add the following line:
5. Open /engine/console/simBase.h
and add the following line in the nameSpace Sim block somewhere near line 509 (put it as the last xxxxSet entry)
6. Open /engine/console/simBase.cc
and add the following line in the nameSpace Sim block somewhere near line 19 (put it as the last xxxxSet entry)
7. Open /engine/console/simManager.cc
and add the following line in function void init() somewhere near line 269 (put it as the last xxxxSet entry)
8. Do a clean build of your project.
Script Integration changes
---------------------
9. Open /example/common/editor/ObjectBuilderGui.gui
(somewhere near line 460, after // Environment )
and add this function:
10. Open /example/common/editor/EditorGui.cs
(in function Creator::init( %this ) where 'n' is the next number in the sequence
of array assignments)
11. Open /example/common/client/missionDownload.cs
In function clientCmdMissionStartPhase3(%seq,%missionName) somewhere near line 65
of array assignments)
AFTER
add this line BEFORE any other Start*(); function calls:
Using in a mission file
=======================
12. Add to your mission like any other object. Examples of a twSurfaceRefence mission
object and a modified fxGrassReplicator object are contained in the file 'samples.txt'
in the twSurfaceReference.zip file.
13. Set up your reference surface:
Place the SurfaceReference object over the precise surface that you want to
reference later for your grass. Select a type from the SurfaceType drop-down menu.
14. Place your grass:
14a. Place a modified fxGrassReplicator object in an appropriate location. Make sure that there
is some surface texture the same as you referenced in step 13 above. Select the same
SurfaceType from the drop down menu. Hit 'Apply'.
14b. To make sure your grass does NOT appear on a given referenced surface, then check the
'SurfaceExclusionMode' box. Hit 'Apply'.
NOTES:
- In regular placement mode, the twSurfaceReference looks for texture alphas that are EXACTLY the same for the given type in both the referencer and the grass object at time of placement.
- In exclusion mode, the twSurfaceReference looks for texture alphas that are COMPLETELY different for the given type in both the referencer and the grass object at time of placement.
- The function 'GetTerrainTextures' is an adaptation of code written by James Holmes for his Terrain Path Following add-on.
- the screenshot (small as it is) shows twSurfaceReference being used by fxGrassReplicator, fxFoliageReplicator, AND fxShapeReplicator: a tree-line road (shapes), several hedge-lines (shapes, grass and foliage) and a few copses and spinneys of trees.
[edit]:fixed the incorrect function reference in the instructions at step 3d. should be CreateGrass and not the other.
[edit]:fixed typo in the file name in step 10.
[edit]:added omitted step 4c.
[edit]:added missing semicolon in step 7.
The twSurfaceReference object is a TGE enhancement used to create an accessible reference to the texture/surface characteristics of any point on a terrain.
The example included provides code fragments that allows you to modify the fxGrassReplicator to use this capability.
You must have the fxGressReplicator by Bendik Stang already installed in your game.
You can also apply the same changes to all of the replicator objects created by Melv May to get them to work the same way.
This resource assumes that you are familiar with the fxGrassReplicator, TGE, VC++, C++ programming, TGE script programming and the example scripts. If you are familiar with these things, then you should be able to resolve any conflicts that arise with these changes. If you have made changes or enhancements to any of the TGE source code or scripts, I can't warrant that this resource will work.
Installation
============
Back up your game source code and scripts prior to installation of this enhancement.
Engine Source changes
---------------------
1. Copy the files:
twSurfaceReference.cc
twSurfaceReference.h
from the twStructureReference.zip into the engine directory where your
fxGrassReplicator files reside.
2. Add both files to your TGE project.
3. Open fxGrassReplicator.cc
3a. Add this include to near the end of the includes at the top,
[b]
#include "twSurfaceReference.h"
[/b]BEFORE the include for fxGrassReplicator.h.
3b. Add this function to any place you like within the file:
[b]
//--------------------------------------------
// GetTerrainTextures
// (adapted from original code written by James Holmes)
//
// Get the terrain texture under an x,y coord
//
// Fills an array with the alpha value of each of the
// textures under that point.
//
// distance - How far to look down for the terrain block
// pt - Point in world space
// alphas - U8 array of size NUM_SURFACES
//
bool fxGrassReplicator::GetTerrainTextures(float distance, Point3F& pt, U8 *alphas)
{
RayInfo rInfo;
if (gClientContainer.castRay(pt, Point3F(pt.x, pt.y, pt.z - distance ), TerrainObjectType, &rInfo))
{
U32 CollisionType = rInfo.object->getTypeMask();
if (CollisionType & TerrainObjectType)
{
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);
return true;
}
}
return false;
}
[/b]3c. Add the following lines to the end of the function initPersistFields()
[b] addField( "SurfaceExclusionMode", TypeBool, Offset( mFieldData.mSurfaceExclusionMode, fxGrassReplicator ) ); addField( "SurfaceType", TypeEnum, Offset(mFieldData.mTheSurface, fxGrassReplicator ), 1, &gSurfaceTypeTable ); [/b]
3d. In the function CreateGrass() AFTER these lines:
[i] if ((CollisionType & WaterObjectType) && !mFieldData.mAllowWaterSurface && !gClientContainer.castRay( GrassStart, GrassEnd, FXGRASSREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue; [/i]
add the following fragment:
[b]
if ((twSurfaceReference::ESurfaceType)mFieldData.mTheSurface) // if we are checking for specific surfaces and not just 'any'
{
if ( BaseSurfaces[(twSurfaceReference::ESurfaceType)mFieldData.mTheSurface].isAvailable)
{
CollisionResult = false;
U8 alphas[TerrainBlock::MaterialGroups];
// Checks if the new position is over a blended terrain texture (a 'surface' ) that is *exactly* the same as the surface where
// the specified SurfaceReference marker was placed.
if (GetTerrainTextures(4000.0f, GrassStart, alphas))
{
bool skip = mFieldData.mSurfaceExclusionMode;
for (int i=0; i < TerrainBlock::MaterialGroups; i++)
{
if (alphas[ i] != BaseSurfaces[(twSurfaceReference::ESurfaceType)mFieldData.mTheSurface].alphas[ i])
{
skip = !mFieldData.mSurfaceExclusionMode; // even one non-match means this is not the same surface
break;
}
}
if (skip) continue; // don't place grass here
}
}
}
[/b]3e. In the function packUpdate() AFTER these lines:
[i]
stream->writeFlag(mFieldData.mIsSquare);
stream->write(mFieldData.mRotateAngle);
[/i]add the following fragment:
[b]
stream->writeFlag(mFieldData.mSurfaceExclusionMode); // allow/disallow toggle
stream->write( mFieldData.mTheSurface ); // the surface reference
[/b]3f. In the function unpackUpdate() AFTER these lines:
[i]
mFieldData.mIsSquare = stream->readFlag();
stream->read(&mFieldData.mRotateAngle); // if not; use this angle
[/i]add the following fragment:
[b]
mFieldData.mSurfaceExclusionMode = stream->readFlag(); // Allow/Disallow toggle
stream->read( &mFieldData.mTheSurface); // the surface reference
[/b]4. Open fxGrassReplicator.h
4a. AFTER these lines:
[i] bool mIsSquare; F32 mRotateAngle; [/i]
add the following fragment:
[b]
bool mSurfaceExclusionMode; // if 1 then allow, if 0 then disallow
U32 mTheSurface;
[/b]4b. AFTER these lines:
[i] mIsSquare = true; mRotateAngle = 0.0f; [/i]
add the following fragment:
[b]
mSurfaceExclusionMode = false;
mTheSurface = (U32)twSurfaceReference::eAny;
[/b]4c. AFTER these lines:
[i] public: fxGrassReplicator(); ~fxGrassReplicator();" [/i]
add the following line:
[b]
bool GetTerrainTextures(float,Point3F&, U8 *);
[/b]5. Open /engine/console/simBase.h
and add the following line in the nameSpace Sim block somewhere near line 509 (put it as the last xxxxSet entry)
[b]
DeclareNamedSet(twSurfaceSet) //(Note: no semi-colon)
[/b]6. Open /engine/console/simBase.cc
and add the following line in the nameSpace Sim block somewhere near line 19 (put it as the last xxxxSet entry)
[b]
ImplementNamedSet(twSurfaceSet) //(Note: no semi-colon)
[/b]7. Open /engine/console/simManager.cc
and add the following line in function void init() somewhere near line 269 (put it as the last xxxxSet entry)
[b]
InstantiateNamedSet(twSurfaceSet); // Now there IS a semi-colon
[/b]8. Do a clean build of your project.
Script Integration changes
---------------------
9. Open /example/common/editor/ObjectBuilderGui.gui
(somewhere near line 460, after // Environment )
and add this function:
[b]
function ObjectBuilderGui::buildtwSurfaceReference(%this)
{
%this.className = "twSurfaceReference";
%this.process();
}
[/b]10. Open /example/common/editor/EditorGui.cs
(in function Creator::init( %this ) where 'n' is the next number in the sequence
of array assignments)
[b]
%Environment_Item[n] = "twSurfaceReference";
[/b]11. Open /example/common/client/missionDownload.cs
In function clientCmdMissionStartPhase3(%seq,%missionName) somewhere near line 65
of array assignments)
AFTER
[i]
onPhase2Complete();
[/i]add this line BEFORE any other Start*(); function calls:
[b] StartSurfaceReferencer(); [/b]
Using in a mission file
=======================
12. Add to your mission like any other object. Examples of a twSurfaceRefence mission
object and a modified fxGrassReplicator object are contained in the file 'samples.txt'
in the twSurfaceReference.zip file.
13. Set up your reference surface:
Place the SurfaceReference object over the precise surface that you want to
reference later for your grass. Select a type from the SurfaceType drop-down menu.
14. Place your grass:
14a. Place a modified fxGrassReplicator object in an appropriate location. Make sure that there
is some surface texture the same as you referenced in step 13 above. Select the same
SurfaceType from the drop down menu. Hit 'Apply'.
14b. To make sure your grass does NOT appear on a given referenced surface, then check the
'SurfaceExclusionMode' box. Hit 'Apply'.
NOTES:
- In regular placement mode, the twSurfaceReference looks for texture alphas that are EXACTLY the same for the given type in both the referencer and the grass object at time of placement.
- In exclusion mode, the twSurfaceReference looks for texture alphas that are COMPLETELY different for the given type in both the referencer and the grass object at time of placement.
- The function 'GetTerrainTextures' is an adaptation of code written by James Holmes for his Terrain Path Following add-on.
- the screenshot (small as it is) shows twSurfaceReference being used by fxGrassReplicator, fxFoliageReplicator, AND fxShapeReplicator: a tree-line road (shapes), several hedge-lines (shapes, grass and foliage) and a few copses and spinneys of trees.
[edit]:fixed the incorrect function reference in the instructions at step 3d. should be CreateGrass and not the other.
[edit]:fixed typo in the file name in step 10.
[edit]:added omitted step 4c.
[edit]:added missing semicolon in step 7.
About the author
#22
04/22/2003 (1:02 am)
Cool resource. Thanks!
#23
These are the steps I follow to set up a scene where the grass keeps to the grass texture area and off the path texture:
1. Paint the landscape (or section thereof) with Grass texture
2. Paint a line with Dark Scorched Planet texture (looks like dark mud)
3. Drop a twsurfacereference object on the Grass texture area, calling it 'g1' and designating it as 'Grass' in object's properties
4. Drop a twsurfacereference object on the Path texture area, calling it 'p1' and designating it as 'Path' in object's properties
5. Drop a fxgrass object in the same area as #3 and set its properties...including setting area to 'Grass'
6. Expect the path to be free of grass!
Alas, my expectations are not met...grass appears all around the radius...
Any suggestions?
04/22/2003 (12:59 pm)
Perhaps someone could give me a hand with this...These are the steps I follow to set up a scene where the grass keeps to the grass texture area and off the path texture:
1. Paint the landscape (or section thereof) with Grass texture
2. Paint a line with Dark Scorched Planet texture (looks like dark mud)
3. Drop a twsurfacereference object on the Grass texture area, calling it 'g1' and designating it as 'Grass' in object's properties
4. Drop a twsurfacereference object on the Path texture area, calling it 'p1' and designating it as 'Path' in object's properties
5. Drop a fxgrass object in the same area as #3 and set its properties...including setting area to 'Grass'
6. Expect the path to be free of grass!
Alas, my expectations are not met...grass appears all around the radius...
Any suggestions?
#24
Open twSurfaceReference.cc
at about line 400 add
// Restore out nice and friendly canonical state.
glMatrixMode(GL_PROJECTION);
glPopMatrix();
Before
glMatrixMode(GL_MODELVIEW);
dglSetViewport(viewport);
Recompile and it should work with no errors this time around.
05/30/2003 (4:02 pm)
For you folks having trouble with the unbalanced the xform stack errorOpen twSurfaceReference.cc
at about line 400 add
// Restore out nice and friendly canonical state.
glMatrixMode(GL_PROJECTION);
glPopMatrix();
Before
glMatrixMode(GL_MODELVIEW);
dglSetViewport(viewport);
Recompile and it should work with no errors this time around.
#25
Really nice and instructive ressource ! Thanks much !
Oupss. It's probably only with GCC3 but I get this compile error. I tryed lot of things but I'm still confuse with those Point3F, U8 things :( . Could someone be nice and help me with this please ? :) Everything else compile fine, only this.
edit : My prob is in void twSurfaceReference::GetSurface(void)
on the line :
This don't seems to follow this function rules (?):
06/19/2003 (6:54 am)
Ken,Really nice and instructive ressource ! Thanks much !
Oupss. It's probably only with GCC3 but I get this compile error. I tryed lot of things but I'm still confuse with those Point3F, U8 things :( . Could someone be nice and help me with this please ? :) Everything else compile fine, only this.
--> Compiling game/fx/twSurfaceReference.cc game/fx/twSurfaceReference.cc: In member function `bool twSurfaceReference::getTerrainTextures(float, Point3F&, U8*)': game/fx/twSurfaceReference.cc:146: warning: passing `float' for argument 1 of ` Point2I::Point2I(int, int)' game/fx/twSurfaceReference.cc:146: warning: passing `float' for argument 2 of ` Point2I::Point2I(int, int)' game/fx/twSurfaceReference.cc: In member function `void twSurfaceReference::GetSurface()': game/fx/twSurfaceReference.cc:157: no matching function for call to ` twSurfaceReference::getTerrainTextures(float, Point3F, U8*&)' game/fx/twSurfaceReference.cc:124: candidates are: bool twSurfaceReference::getTerrainTextures(float, Point3F&, U8*) game/fx/twSurfaceReference.cc: In member function `virtual void twSurfaceReference::renderObject(SceneState*, SceneRenderImage*)': game/fx/twSurfaceReference.cc:397: warning: assignment to `U32' from `F32' game/fx/twSurfaceReference.cc:397: warning: argument to `unsigned int' from ` F32' make[1]: *** [out.GCC3.RELEASE/game/fx/twSurfaceReference.obj] Error 1 make: *** [default] Error 2
edit : My prob is in void twSurfaceReference::GetSurface(void)
on the line :
if(getTerrainTextures(300.0f, getPosition(), BaseSurfaces[(ESurfaceType)mFieldData.mTheSurfaceRef].alphas) )
This don't seems to follow this function rules (?):
bool twSurfaceReference::getTerrainTextures(float distance, Point3F& pt, U8 *alphas)
#26
to get it to compile on linux / gcc, change the call Gilles posted above to:
Also, add
04/24/2004 (11:03 am)
Two fixes:to get it to compile on linux / gcc, change the call Gilles posted above to:
if(getTerrainTextures(300.0f, (const Point3F&)getPosition(), (U8*)BaseSurfaces[(ESurfaceType)mFieldData.mTheSurfaceRef].alphas) )and change the function declaration to:
bool twSurfaceReference::getTerrainTextures(float distance, const Point3F& pt, U8 *alphas)
Also, add
glMatrixMode(GL_PROJECTION); glPopMatrix();before
glMatrixMode(GL_MODELVIEW); dglSetViewport(viewport);- I got an assertion otherwise in DEBUG...
#27
12/24/2004 (5:55 pm)
Great resource.
#28
09/17/2005 (1:54 pm)
Heh. Well, I finally found my way back here and found out about the bug fixes all this time later. Thanks guys. I've incorporated them into a 1.1 version of the TWSR and uploaded the new zip file.
#29
05/03/2006 (8:02 pm)
I'm using 1.4 and can't seem to get the SimBase.h part to work. I am a newbie coder so perhaps I just don't know where to find/put it. Anyone else had this problem?
#30
Basically, this is where I started:
www.garagegames.com/mg/forums/result.thread.php?qt=67828
10/02/2007 (3:16 pm)
I am trying to get the name of the texture the control object is standing on at any given moment. Will this resource allow me to do that and how?Basically, this is where I started:
www.garagegames.com/mg/forums/result.thread.php?qt=67828
#31
10/03/2007 (1:50 pm)
I had some problems my first time trying this resource. Mainly, I added all the included files in the zip file in my project, then I went through all the steps listed above, and it turns out that a lot of the steps you have listed were already implemented from installing the fxGrassReplicator resource which you said was required for this to work, so I put it in. Then I went through all your steps you had listed not realizing some of them were already in there, so I had 3 of the steps doubled up. I cleaned it up and the build was successful.
#32
I need to get the name of a given terrain texture based on the player's position!
10/03/2007 (2:03 pm)
'GetTerrainTextures' doesn't work in script?I need to get the name of a given terrain texture based on the player's position!
#33
There are three different textures, oner at road1, another at road2 and the third at road3.
But what I get is the grass just excluded from road1.
Cheers,
Andy
12/22/2007 (1:11 am)
Can this resource exclude grass from more than one texture surface? e.g.new twSurfaceReference(road1) {
canSaveDynamicFields = "1";
position = "6.62973 62.6466 78.6283";
rotation = "1 0 0 0";
scale = "1 1 1";
ShowPlacementArea = "1";
PlacementAreaHeight = "25";
PlacementColour = "0.4 0 0.8 1";
SurfaceType = "Grass";
};
new twSurfaceReference(road2) {
canSaveDynamicFields = "1";
position = "-1.04135 102.702 78.946";
rotation = "1 0 0 0";
scale = "1 1 1";
ShowPlacementArea = "1";
PlacementAreaHeight = "25";
PlacementColour = "0.4 0 0.8 1";
SurfaceType = "Grass";
};
new twSurfaceReference(road3) {
canSaveDynamicFields = "1";
position = "51.9662 -38.7847 77.1799";
rotation = "1 0 0 0";
scale = "1 1 1";
ShowPlacementArea = "1";
PlacementAreaHeight = "25";
PlacementColour = "0.4 0 0.8 1";
SurfaceType = "Grass";
};
new fxGrassReplicator(grass1) {
canSaveDynamicFields = "1";
position = "6.44916 -42.0729 90.711";
rotation = "1 0 0 0";
scale = "1 1 1";
UseDebugInfo = "0";
DebugBoxHeight = "1";
HideGrass = "0";
ShowPlacementArea = "1";
PlacementAreaHeight = "100";
PlacementColour = "0.4 0 0.8 1";
Seed = "1376312589";
GrassFile = "~/data/shapes/foliage/fxFoliageTextures/flower.png";
GrassCount = "50000";
GrassRetries = "100";
InnerRadiusX = "0";
InnerRadiusY = "0";
OuterRadiusX = "512";
OuterRadiusY = "512";
MinWidth = "4";
MaxWidth = "6";
MinHeight = "1";
MaxHeight = "2";
FixAspectRatio = "0";
FixSizeToMax = "0";
OffsetZ = "0";
RandomFlip = "0";
UseCulling = "1";
CullResolution = "32";
ViewDistance = "70";
ViewClosest = "1";
FadeInRegion = "20";
FadeOutRegion = "1";
AlphaCutoff = "0.5";
GroundAlpha = "0.9";
SwayOn = "1";
SwaySync = "0";
SwayMagSide = "0.1";
SwayMagFront = "0.2";
MinSwayTime = "4";
MaxSwayTime = "15";
LightOn = "1";
LightSync = "0";
MinLuminance = "0.7";
MaxLuminance = "1";
LightTime = "10";
AllowOnTerrain = "1";
AllowOnInteriors = "0";
AllowOnStatics = "0";
AllowOnWater = "0";
AllowWaterSurface = "0";
AllowedTerrainSlope = "20";
FoilageColourTop = "0.3 0.8 0.1 1";
FoilageColourBtm = "0.2 0.6 0 1";
UseColour = "0";
IsRandomRot = "1";
IsSquareArea = "1";
RotationAngle = "0";
SurfaceExclusionMode = "1";
SurfaceType = "Grass";
};There are three different textures, oner at road1, another at road2 and the third at road3.
But what I get is the grass just excluded from road1.
Cheers,
Andy
#34
01/07/2008 (7:38 am)
Looking awsome!
#35
Could anyone point me in the right direction to do this? I want it to work for the fxShapeReplicator.
Nevermind, got it working....this is a really handy resource...thanks!
God Bless!
J
05/09/2008 (6:53 am)
Quote:You can also apply the same changes to all of the replicator objects created by Melv May to get them to work the same way.
Could anyone point me in the right direction to do this? I want it to work for the fxShapeReplicator.
Nevermind, got it working....this is a really handy resource...thanks!
God Bless!
J

Torque Owner Daniel Neilsen
Fatal (e:\torque\engine\scenegraph\scenestate.cc @ 117)
Error, object of class twSurfaceReference either unbalanced the xform stack, or didnt reset the viewport. mv(2 2) proj (1 2) t0(1 1), t1(1 1) (0 22 800 578:0 22 800 578)
Any ideas anyone? I used the grass resource version 1.1 and, just in case overwrote it with this resource. I have checked all instructions and am using latest HEAD (yes I did a clean build).