Game Development Community

Dynamically painting terrain texture?

by Norv Brooks · in Torque Game Engine · 08/19/2006 (1:05 pm) · 12 replies

What I want to accomplish is that after a wildfire (represented by fire particle emitters) pass through an area, I want the terrain to look burned. What I'm trying to find out is if it's possible to do terrain texture painting on the fly. I understand that in "Bit Shifter" there are viruses represented on the terrain which are dynamically changed. Some steps to achieve a "Bit Shifter" like solution have been given to me by Paul Dana of Plastic Games, His suggestions can be found at my post thread : www.garagegames.com/mg/forums/result.thread.php?qt=49319
However, my software engineering skills are not advanced enough to utilize his suggestions without a little direction as to which ".cc" files to look in and maybe some sample code. Any help would be appreciated.
Norv

#1
08/30/2006 (10:00 pm)
Hi Norv,

I've done something similar to this. Instead of wildfire, I have little critters that go around colouring the terrain red or blue or whatever.

My game just adjusts the alpha blend of textures on the terrain the exact way that the Terrain Texture Painter tool does. You could start with function PaintMaterialAction::process() in terrainActions.cc if you want to see how that happens.

I haven't solved the networking issue. Of course, as is, Torque won't send terrain texture changes to a client. (But Paul's bitshifter has proved this is possible in the thread you posted.)

I could probably send you some code with a little time to go back and look at what I did.
#2
08/31/2006 (7:16 am)
Nicholas - thanks for the info. I looked at "terrainActions.cc" briefly. It looks like it responds to a mouse click. Is that what your game does? If you can send the code you referred to, I would appreciate it.
#3
09/02/2006 (1:09 am)
PaintMaterialAction::process() is called when you click the mouse with the texture painter tool. It's a good starting point to see what the editor does, and how you might copy it.

Anyhow, I have extracted a snippet of code from my project that should get you started.
users.on.net/~njsand/dynamicTerrainTextureTest.cc (That url won't exist for ever - it's experimental code.)

Add that to your Torque 1.4 project and recompile.

You should then have a console function: setMaterialAlphas(), which you can use like so:
setmaterialalphas("250.0 250.0", 127, 128) // Blend between first two textures.
setmaterialalphas("250.0 250.0", 85, 85, 85) // Blend between first three textures.

Note that the first argument is a world position, not a terrain grid coordinate.

It's all a hack ripped off from the texture painter tool, but it seems to work for me.

Here is a picture showing a grass patch in the middle of the starter.fps village, which I set with this function: users.on.net/~njsand/textureTest.jpg

Finally, I seem to recall the torque terrain code doesn't blend more than 4 textures nicely, and if you try it you might get weird and ugly visual glitches. But 4 is plenty for most maps anyway I guess.

Edit: url of jpg
#4
09/02/2006 (2:01 am)
Thanks Nicholas, thats great stuff.
#5
09/02/2006 (7:53 am)
Nicholas, thanks for the code. Your screenshot looks like the effect I'm looking for. I'll give it a try as soon as I can and let you know how it works.
Thanks,
Norv
#6
09/04/2006 (11:17 am)
Nicholas - I got your code to work without much difficulty. The thing that is an issue for me is that though world coordinates are passed as the first parameter in setMaterialAlphas they get converted within the code to the nearest grid coordinates. This causes some difficulty when trying to line it up behind the wildfires. Also, it too large an area. I search but so far I have not be able to find how many terrain blocks are controlled by one set of grid coordinates. It seems like I read somewhere that the terrain blocks are 8 x 8 pixels in size. If I could reduce the size of the area the texture painter tool is using through script I might be able to adjust the positioning to grid coordinates to work satifactorily.

Thanks for your help.
Norv
#7
09/04/2006 (5:19 pm)
Hi Norv,

Torque's terrain texture blending doesn't happen at a resolution lower than 1 grid square. In other words, you can't change the texture for only a fraction of 1 grid square - it has to be all or nothing. (At least for the terrain textures themselves - there may be other solutions such as decals that I'm not familiar with right now.)

Quote:I search but so far I have not be able to find how many terrain blocks are controlled by one set of grid coordinates.
A terrain block and a grid square are the same thing in my mind. So a grid coordinate identifies 1 terrain block and 1 terain block only.

You can make the terrain blocks (or grid squares or whatever ya wanna call 'em) smaller relative to everything else in the world (such as the Player) with the TerrainBlock::squareSize parameter in the mission file. But that means you end up with a smaller world.
#8
09/05/2006 (10:46 am)
Nicholas - thanks for clearing up the understanding of grid square/terrain block. I tried chaning TerrainBlock::squareSize from "8" to "4" and it crashed. Tried changing to "6" but didn't really give me the look I wanted, especially the other areas of terrain & models. So, I tried "7" which surprised me and work. I didn't think it would like an odd number. Still didn't really solve the issue. I was able to adjust the world coordinates that I passed in setMaterialAlphas and that helped some. But the burned area still extends outside of the fire perimeter. Especially in the initial stages of the wildfire. So, I thought maybe before using setMaterialAlphas I could check and see if the burned area texture exceeded fire perimeter. Notice how in the first picture below the red outline burned texture is considerably outside the fire perimeter, but in the second picture it's pretty well within the perimeter.
members.dslextreme.com/users/vronsoftware/burnedArea1.jpgmembers.dslextreme.com/users/vronsoftware/burnedArea2.jpgSo, I was thinking maybe I could use your function worldToTerrainPos(Point2f pos, TerrainBlock *b) to determing the world coordinates of the grid boundaries and then check to see if the boundaries exceed the fire perimeter world coordinates.

Point2I worldToTerrainPos(Point2F pos, TerrainBlock *b) 
{
    Point3F offset;
    b->getTransform().getColumn(3, &offset);
    pos -= Point2F(offset.x, offset.y);

    float invSquareSize = 1.0f / (float)b->getSquareSize();
    float xp = pos.x * invSquareSize;
    float yp = pos.y * invSquareSize;
    int x = (S32)mFloor(xp);
    int y = (S32)mFloor(yp);

    x &= TerrainBlock::BlockMask;
    y &= TerrainBlock::BlockMask;

    return Point2I(x, y);
}
The first parameter Point2F pos is world coordinates, right? Does "pos -= Point2F(offset.x, offset.y);" convert the coordinate to grid? Is invSquareSize the grid dimensions in units?

Thanks for your interest and help.
Norv
#9
09/10/2006 (9:53 pm)
Hi Norv,

TerrainEditor::gridToWorld() and TerrainEditor::worldToGrid() should help you converting from and to grid/world coordinates. (Actually the worldToTerrainPos above is practically identical to TerrainEditor::worldToGrid(), probably because that's where I took it in the first place ;)

As for how they work, they're just coordinate conversions between two cartesian planes. The terrain grid is just another cartesian (i.e., x/y) plane with an offset from the origin in another x/y plane. Hope that helps ;)

I'm curious, how do your fires spread? How will you know if a grid square is entirely within the fire perimeter? Do your fires spread as known "shapes", or are they random, or what?

P.S., Happy to help!
#10
09/11/2006 (8:42 am)
Nicholas - thanks for your response. First, the fire perimeter will be random. It will be influenced by - is the particular fire element (particle emitter) burning uphill or downhill; is it burning with the wind, crosswind or against the wind; and what type of fuel is burning (grass, heavy brush, trees, etc). I have not yet built these variables into my wildfire algorithms.
As to how will I determine if grid square is within the fire perimeter, I haven't written that algorithm yet (trying to get the airplane which transports the smokejumpers to the wildire scene to fly across the screen at the present time). What I intend to do is find the world coordinates of the grid square and then calculate the four corner world coordinates of the grid square. Then run a "for" loop to see how many of the wildfire particle emitters' world coordinates fall within those boundaries. And then probably accept 80% or 90% as an OK to go ahead and paint terrain; otherwise, hold off until the fire perimeter expands some more. My thinking on determining the four corners of the grid square is that if the size in "terrainBlock is set to "8" that means an 8 x 8 area of 8 x 8 pixels areas. However, I think world coordinates are based on units and I'm not sure how units relate to pixels.

That's where I'm headed.
Norv
#11
09/11/2006 (8:55 am)
Neat stuff!
just out of curiosity, is this networked ?
#12
09/11/2006 (11:02 am)
Orion - SmokeJumpers is designed as a single player game - no plan for networking.
Thanks for interest.
Norv