Rule based layer distribution for Torque3D terrains
by Konrad Kiss · 05/05/2009 (10:01 am) · 58 comments
Although Torque3D's terrain is the fastest one can create terrains with in Torque until now, the tools within allow for even more robust, automated solutions.
I've been experimenting with the terrain system from the inside this time, and came up with a rule based layer mask generator for Torque3D.
How does it help? The following terrain was painted by hand and took about 1.5 hours (the entire terrain, not this part only):

The second image was created from scratch (untextured heightmap) in about 3 minutes (!) with an extra layer added:

The difference is not only speed, but a more realistic distribution of terrain materials using this simple tool:

What it does is it takes the currently selected material, and paints it everywhere where the height is between the minimum and maximum height (z coordinate) and where the slope angle (in degrees) is within the given bounds.
The second image was generated by creating a snow layer everywhere (default settings). Then I checked the waterplane's z, and used that value +1 as max height for the pebbles on every slope.. That pretty much took care of everything below sea level. I added other layers with constraints, and finally made everything with a slope between 40-90 degrees a cliff. It's pretty easy to paint this way.
If you need to do custom painting - ie a riverbed - do that after you're done with the entire automatic generation, otherwise you might overwrite your layers.
Before implementing this resource, please note that:
1. Update: Using Ctrl-Z or Edit/Undo you can now undo your actions. For changes that affect the entire terrain - and also depending on your terrain's size, recording the action can take a significant time. But at least there's a way to revert to the previous state. If you'd rather keep it fast without undo, comment everything between the // undo >> and // undo << comments.
2. This feature is currently not directly wired into the editor. To use this feature, select a terrain layer in the Terrain Painter, open the console, type "autoLayers();" at the console and close the console. This is slow, but I am hoping that someone who can create a gui for this will do that eventually. I didn't feel like breaking up the beautiful new gui with some programmer art.. so until then - type away! Hey, maybe GG will like it and add it to the next Beta :) *hint*
Ok, now, the required changes:
source/gui/missionEditor/terrainEditor.cpp
tools/missionEditor/main.cs - add the following to the begining of initializeMissionEditor
create tools/missionEditor/gui/guiTerrainPainterProceduralGui.gui:
And you're done. Again, usage: This is not wired into the editor yet. To use this feature, select a terrain layer in the Terrain Painter, open the console, type "autoLayers();" at the console and close the console to see the panel where you can set the distribution parameters.
Enjoy!
Update: Added undo. If you'd rather keep it fast without undo, comment everything between the // undo >> and // undo << comments.
Update: Fixed a bug that was caused by using world space coords instead of object space coords when querying for normals of terrain squares.
Update: The dialog can now be closed with the close button if you change your mind.
I've been experimenting with the terrain system from the inside this time, and came up with a rule based layer mask generator for Torque3D.
How does it help? The following terrain was painted by hand and took about 1.5 hours (the entire terrain, not this part only):

The second image was created from scratch (untextured heightmap) in about 3 minutes (!) with an extra layer added:

The difference is not only speed, but a more realistic distribution of terrain materials using this simple tool:

What it does is it takes the currently selected material, and paints it everywhere where the height is between the minimum and maximum height (z coordinate) and where the slope angle (in degrees) is within the given bounds.
The second image was generated by creating a snow layer everywhere (default settings). Then I checked the waterplane's z, and used that value +1 as max height for the pebbles on every slope.. That pretty much took care of everything below sea level. I added other layers with constraints, and finally made everything with a slope between 40-90 degrees a cliff. It's pretty easy to paint this way.
If you need to do custom painting - ie a riverbed - do that after you're done with the entire automatic generation, otherwise you might overwrite your layers.
Before implementing this resource, please note that:
1. Update: Using Ctrl-Z or Edit/Undo you can now undo your actions. For changes that affect the entire terrain - and also depending on your terrain's size, recording the action can take a significant time. But at least there's a way to revert to the previous state. If you'd rather keep it fast without undo, comment everything between the // undo >> and // undo << comments.
2. This feature is currently not directly wired into the editor. To use this feature, select a terrain layer in the Terrain Painter, open the console, type "autoLayers();" at the console and close the console. This is slow, but I am hoping that someone who can create a gui for this will do that eventually. I didn't feel like breaking up the beautiful new gui with some programmer art.. so until then - type away! Hey, maybe GG will like it and add it to the next Beta :) *hint*
Ok, now, the required changes:
source/gui/missionEditor/terrainEditor.cpp
// >>>
//------------------------------------------------------------------------------
void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope )
{
if (!mActiveTerrain)
return;
S32 mat = getPaintMaterialIndex();
if (mat == -1)
return;
// undo >>
mUndoSel = new Selection;
// undo <<
U32 terrBlocks = mActiveTerrain->getBlockSize();
for (U32 y=0;y<terrBlocks;y++) {
for (U32 x=0;x<terrBlocks;x++) {
// get info
GridPoint gp;
gp.terrainBlock = mActiveTerrain;
gp.gridPos.set(x, y);
GridInfo gi;
getGridInfo(gp, gi);
if (gi.mMaterial==mat)
continue;
Point3F wp;
gridToWorld(gp, wp);
if (!(wp.z>=mMinHeight && wp.z<=mMaxHeight))
continue;
// objspace >>
// transform wp to object space
Point3F op;
mActiveTerrain->getWorldTransform().mulP(wp, &op);
Point3F norm;
mActiveTerrain->getNormal(Point2F(op.x, op.y), &norm, true);
// objspace <<
if (mMinSlope>0)
if (norm.z > mSin(mDegToRad(90.0f-mMinSlope)))
continue;
if (mMaxSlope<90)
if (norm.z < mSin(mDegToRad(90.0f-mMaxSlope)))
continue;
// ok, looks like we can change the material here
gi.mMaterialChanged = true;
// undo >>
mUndoSel->add(gi);
// undo <<
gi.mMaterial = mat;
setGridInfo(gi);
}
}
// undo >>
if(mUndoSel->size())
submitUndo( mUndoSel );
else
delete mUndoSel;
mUndoSel = 0;
// undo <<
scheduleMaterialUpdate();
}
ConsoleMethod( TerrainEditor, autoMaterialLayer, void, 6, 6, "(float minHeight, float maxHeight, float minSlope, float maxSlope)")
{
object->autoMaterialLayer( dAtof( argv[2] ), dAtof( argv[3] ), dAtof( argv[4] ), dAtof( argv[5] ) );
}
// <<<tools/missionEditor/main.cs - add the following to the begining of initializeMissionEditor
// >>>
exec("./gui/guiTerrainPainterProceduralGui.gui" );
// <<<create tools/missionEditor/gui/guiTerrainPainterProceduralGui.gui:
//--- OBJECT WRITE BEGIN ---
%guiContent = new GuiControl(TerrainPainterProceduralGui) {
canSaveDynamicFields = "0";
isContainer = "1";
Profile = "GuiDefaultProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "0 0";
Extent = "1024 768";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
new GuiWindowCtrl() {
canSaveDynamicFields = "0";
isContainer = "1";
Profile = "GuiWindowProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "285 83";
Extent = "175 209";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
resizeWidth = "0";
resizeHeight = "0";
canMove = "1";
canClose = "1";
canMinimize = "0";
canMaximize = "0";
minSize = "50 50";
EdgeSnap = "1";
canCollapse = "0";
CollapseGroup = "-1";
CollapseGroupNum = "-1";
closeCommand = "Canvas.popDialog(TerrainPainterProceduralGui);";
text = "Generate layer mask";
new GuiButtonCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiButtonProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "19 164";
Extent = "140 30";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "generateProceduralTerrainMask();";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
text = "Generate";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "0";
};
new GuiTextCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "15 37";
Extent = "33 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
text = "HEIGHT";
maxLength = "1024";
};
new GuiTextCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "59 37";
Extent = "23 14";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
text = "Min.";
maxLength = "1024";
};
new GuiTextCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "59 62";
Extent = "23 14";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
text = "Max.";
maxLength = "1024";
};
new GuiTextEditCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "97 35";
Extent = "66 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Variable = "$TPPHeightMin";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
maxLength = "1024";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
passwordMask = "*";
};
new GuiTextEditCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "97 60";
Extent = "66 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Variable = "$TPPHeightMax";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
maxLength = "1024";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
passwordMask = "*";
};
new GuiTextCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "15 101";
Extent = "33 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
text = "SLOPE";
maxLength = "1024";
};
new GuiTextCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "59 101";
Extent = "23 14";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
text = "Min.";
maxLength = "1024";
};
new GuiTextCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "59 126";
Extent = "23 14";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
text = "Max.";
maxLength = "1024";
};
new GuiTextEditCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "97 99";
Extent = "66 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Variable = "$TPPSlopeMin";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
maxLength = "1024";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
passwordMask = "*";
};
new GuiTextEditCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = "97 124";
Extent = "66 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Variable = "$TPPSlopeMax";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
maxLength = "1024";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
passwordMask = "*";
};
};
};
//--- OBJECT WRITE END ---
$TPPHeightMin = -10000;
$TPPHeightMax = 10000;
$TPPSlopeMin = 0;
$TPPSlopeMax = 90;
function autoLayers() {
Canvas.pushDialog(TerrainPainterProceduralGui);
}
function generateProceduralTerrainMask() {
Canvas.popDialog(TerrainPainterProceduralGui);
ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax);
}And you're done. Again, usage: This is not wired into the editor yet. To use this feature, select a terrain layer in the Terrain Painter, open the console, type "autoLayers();" at the console and close the console to see the panel where you can set the distribution parameters.
Enjoy!
Update: Added undo. If you'd rather keep it fast without undo, comment everything between the // undo >> and // undo << comments.
Update: Fixed a bug that was caused by using world space coords instead of object space coords when querying for normals of terrain squares.
Update: The dialog can now be closed with the close button if you change your mind.
About the author
Lead Developer at Bitgap Games (www.bitgap.com) currently working on Xenocell (www.xenocell.com) a massively multiplayer action strategy game based on Torque 3D technology.
#42
If any one is wondering, this does compile under 1.1 B2. One thing to note, Don't for get to add the prototype to terrainEditor.h
Konrad, thanks again for this kick ass resource!
08/23/2010 (12:47 am)
Booked marked this time...If any one is wondering, this does compile under 1.1 B2. One thing to note, Don't for get to add the prototype to terrainEditor.h
Konrad, thanks again for this kick ass resource!
#43
Pasted here for convenience and future reference
That completes the Resource installation as per Konrad's instructions. The only changes were taking
account for the renamed files/directories and the missing step for modifying the header file.
But lets go ahead and add a button to the TerrainPainter window so that you don't have to type "autoLayers();" in the console. Open up TerrainPainterWindow.ed.gui and find the EPainterPreview window section. Add the following to the end (as the last child) of the EPainterPreview control:
11/07/2010 (7:33 pm)
In the forum thread associated with this Resource someone had a problem implementing this in 1.1 B3 so I said I'd install a fresh copy of Beta3 and update the install instructions for it.- Add the autoMaterialLayer function and console method - no changes. Note that source/gui/missionEditor/terrainEditor.cpp is now source/gui/worldEditor/terrainEditor.cpp
- Don't forget to add the function prototype to the header file. In source/gui/worldEditor/terrainEditor.h add this line to the TerrainEditor class (in public section):
- Create the guiTerrainPainterProceduralGUI.gui file inside of tools/WorldEditor/gui/ Note that MissionEditor directory has been renamed WorldEditor
- Add the exec statement for the guiTerrainPainterProceduralGUI.gui to tools/WorldEditor/main, somewhere near the top of initializeWorldEditor() Note that initializeMissionEditor has been renamed initializedWorldEditor
void TerrainEditor::autoMaterialLayer(F32, F32, F32, F32);
That completes the Resource installation as per Konrad's instructions. The only changes were taking
account for the renamed files/directories and the missing step for modifying the header file.
But lets go ahead and add a button to the TerrainPainter window so that you don't have to type "autoLayers();" in the console. Open up TerrainPainterWindow.ed.gui and find the EPainterPreview window section. Add the following to the end (as the last child) of the EPainterPreview control:
new GuiButtonCtrl() {
canSaveDynamicFields = "0";
isContainer = "0";
Profile = "GuiButtonProfile";
HorizSizing = "left";
VertSizing = "bottom";
Position = "100 229";
Extent = "50 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "autoLayers();";
tooltipprofile = "GuiToolTipProfile";
hovertime = "1000";
text = "AutoPaint";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "0";
};
#44
11/07/2010 (7:53 pm)
Thank you, Michael!
#45
Also, I added a feature using this resource so that I can now specify a "chance/vertex" of painting each vertex. (as in 1 in 10 means it will randomly choose 1 in every 10 verticies on the terrain to paint) Should I post how I did that here?
12/02/2010 (3:43 am)
Thanks for the resource!Also, I added a feature using this resource so that I can now specify a "chance/vertex" of painting each vertex. (as in 1 in 10 means it will randomly choose 1 in every 10 verticies on the terrain to paint) Should I post how I did that here?
#46
12/12/2010 (12:27 am)
Jack, does that effectively implement the 'density' setting when auto painting a layer, making it possible to mix two material layers that are within the same angle/height parameters ?
#47
Sorry I'm late responding. Not sure what you mean by the density thing, but it will let you mix two layers withing the same angle/height paramiters. Its just 3 lines of c++ code and a gui button and option that randomly decide weather to place the texture or not when going through each individual vetex on the terrain. This is the effect:
12/26/2010 (7:40 am)
@andy:Sorry I'm late responding. Not sure what you mean by the density thing, but it will let you mix two layers withing the same angle/height paramiters. Its just 3 lines of c++ code and a gui button and option that randomly decide weather to place the texture or not when going through each individual vetex on the terrain. This is the effect:
#48
You can of course make either texture appear more often (more "dense"?)
If you would like me to post the code, just tell me.
Edit:
I just looked at the code again and realized its actually about 10 lines to add/edit, not 3. =P still, its fairly simple.
12/26/2010 (7:46 am)
@andy(continued):You can of course make either texture appear more often (more "dense"?)
If you would like me to post the code, just tell me.
Edit:
I just looked at the code again and realized its actually about 10 lines to add/edit, not 3. =P still, its fairly simple.
#49
01/26/2011 (1:45 pm)
Jack, I'm interested in your code :-)
#50
I can see the button, albeit hard to press unless you get the exact right pixel.
However nothing happens.
Can you tell me exactly where to add the extra line in step 2?:
01/26/2011 (2:03 pm)
I have followed the above steps, I'm using Torque3d v1.1 beta 3.I can see the button, albeit hard to press unless you get the exact right pixel.
However nothing happens.
Can you tell me exactly where to add the extra line in step 2?:
Quote:# Don't forget to add the function prototype to the header file. In
source/gui/worldEditor/terrainEditor.h add this line to the TerrainEditor class (in public section):
void TerrainEditor::autoMaterialLayer(F32, F32, F32, F32);
#51
I'll go find the changes I had to make. I might not have enough time to get it all together tonight (I'm kind of buisy), but I'll definetly post by tomorrow night.
01/26/2011 (2:49 pm)
@Giorgio:I'll go find the changes I had to make. I might not have enough time to get it all together tonight (I'm kind of buisy), but I'll definetly post by tomorrow night.
#52
01/26/2011 (3:20 pm)
Tnx Jack :-)
#53
I placed mine in the
01/26/2011 (7:20 pm)
@Skipper:I placed mine in the
class TerrainEditor : public EditTSCtrlpart of terrainEditor.h after
void submitMaterialUndo( String actionName );
void onMaterialUndo( TerrainBlock *terr ); just before private:
#54
First:
in source/gui/missionEditor/terrainEditor.cpp
at the very top of the file or after the other includes, add:
After that, change the following:
from:
after:
after:
from:
Next, in sourceguiworldEditorterrainEditor.h
after:
01/27/2011 (1:29 pm)
Here is how to mix textures:First:
in source/gui/missionEditor/terrainEditor.cpp
at the very top of the file or after the other includes, add:
#include <cstdlib> #include <ctime>
After that, change the following:
from:
void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope )to:
void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope, U32 Chance )
after:
S32 mat = getPaintMaterialIndex(); if (mat == -1) return;add:
srand((unsigned)time(0)); int chanceVertex;
after:
if (gi.mMaterial==mat) continue;add:
chanceVertex = (rand() % Chance); if (chanceVertex != 0) continue;
from:
ConsoleMethod( TerrainEditor, autoMaterialLayer, void, 6, 6, "(float minHeight, float maxHeight, float minSlope, float maxSlope)")
{
object->autoMaterialLayer( dAtof( argv[2] ), dAtof( argv[3] ), dAtof( argv[4] ), dAtof( argv[5] ) );
}to:ConsoleMethod( TerrainEditor, autoMaterialLayer, void, 7, 7, "(float minHeight, float maxHeight, float minSlope, float maxSlope)")
{
object->autoMaterialLayer( dAtof( argv[2] ), dAtof( argv[3] ), dAtof( argv[4] ), dAtof( argv[5] ), dAtof( argv[6] ));
}Next, in sourceguiworldEditorterrainEditor.h
after:
class TerrainEditor : public EditTSCtrl
{
// XA: This methods where added to replace the friend consoleMethods.
public:
void attachTerrain(TerrainBlock *terrBlock);
void detachTerrain(TerrainBlock *terrBlock);add:void autoMaterialLayer(F32, F32, F32, F32, U32);
#55
After that, open tools/missionEditor/gui/guiTerrainPainterProceduralGui.gui (the actual file, this time) and make these changes:
After:
from:
Thats all the changes. The way it works is kind of backwards. The higher the number you give it, the less often the texture will appear. I was originally planing on reversing that(so you could specify something like 45/100), but I decided I liked it beter this way because I could make the texture be as unlikely to appear as I wanted. If you want to make it work in a more sensible manner, feel free to do so and post it if you want.
Anyways, if anything does not work, please tell me so I can correct it. This is the first time I have ever posted any code, so I have probably made spme mistakes. =P
01/27/2011 (2:26 pm)
The last of the changes are all in script. Open tools/missionEditor/gui/guiTerrainPainterProceduralGui.gui in the GUI editor. coppy and paste one of Konrad's entry fields, but change the "variable" field to $TPPChance.After that, open tools/missionEditor/gui/guiTerrainPainterProceduralGui.gui (the actual file, this time) and make these changes:
After:
$TPPSlopeMax = 90;add:
$TPPChance = 1;
from:
function generateProceduralTerrainMask() {
Canvas.popDialog(TerrainPainterProceduralGui);
ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax);
}to:function generateProceduralTerrainMask() {
Canvas.popDialog(TerrainPainterProceduralGui);
ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax, $TPPChance);
}Thats all the changes. The way it works is kind of backwards. The higher the number you give it, the less often the texture will appear. I was originally planing on reversing that(so you could specify something like 45/100), but I decided I liked it beter this way because I could make the texture be as unlikely to appear as I wanted. If you want to make it work in a more sensible manner, feel free to do so and post it if you want.
Anyways, if anything does not work, please tell me so I can correct it. This is the first time I have ever posted any code, so I have probably made spme mistakes. =P
#56
06/04/2011 (10:45 am)
can confirm this works in 1.1 final without any issues
#57
06/04/2011 (11:02 am)
Thanks Andy! I'm trying hard to put some time aside and update all my resources - one less to worry about.
#58
06/04/2011 (4:13 pm)
Jacks mod is working too for the ammount that it paints down
Torque Owner Travis Evans
Gamer's High
EDIT:
Scratch that.. Forgot to select the Debug Build
... this really should be integrated in 1.1!
EDIT:
I've added this to my menu.ed.cs around line 139:
(tools/worldEditor/scripts/menu.ed.cs)