Placing trees and grass on a terrain using script ...

Hi,

Can somebody please tell me if its possible somehow to place trees and grasses on a terrain object using for example javascript or c# ?

I know that the height can allready be changed using script code, but how about placing grasses/trees ?

And how to paint textures on the terrain using code ?

Any help would be greatly appreciated.

Thanks,

Bart

Hi, I have made a script to paint on the terrain using .js, the reason is that I’m building a WorldBuilder, currently it is work in progress but you can get the paint script if you want.

/Aron

That would be very kind of you if I could have a look at it.

Thank you in advance
Where can I see the script ? You mail it to me or just put it online somewhere ?

wikiwikiwikiwiki? :slight_smile:

Hi,
Here is the script, it is a almost no comments in it, but I hope you will get it to work, You can see a web-player using the script here: http://arongranberg.com/unity/worldbuilder

var terrain : TerrainData;
var tex : Texture2D;//Splatmap 1
var tex2 : Texture2D;//Splatmap 2 (you must assignat least 5 textures in the terrain editor (the splat maps are placed in the terrainData asset))
var brsize  = 1;//Brush size
private var pixels : Color[];//Splat 1
private var pixels2 : Color[];//Splat 2
private var mouse : Vector3;
private var mouse2 : Vector3;//On terrain
var texpos : Rect;
var mask : LayerMask;//Set terrain layer to some layer and assign that to the LayerMask
private var perunit : float;
function Start () {
	worldsize = terrain.size;
	worldwidth = terrain.heightmapWidth;
	texwidth = tex.width;
	pixels = tex.GetPixels (0);
	pixels2 = tex2.GetPixels (0);
	perunit = worldsize.x/worldwidth;
}
function Update () {
	if (Input.GetKey("mouse 0")) {
		var hit : RaycastHit;
		var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		if (Physics.Raycast (ray,hit,1500,mask)) {
			if (Input.GetKey ("left shift")) {
					calcpos (hit.point,true);
			} else {
				calcpos (hit.point, false);
			}
		}
	}
}
function calcpos (pos : Vector3, pick) {
	var xb = 0;
	var yb = 0;
	xb = pos.x / perunit;
	yb = pos.z / perunit;
	if (pick) {
		GetColorx (xb,yb);
	} else {
		paintalpha0 (xb,yb);
	}
}
function paint (pos : Vector3) {
	var pos2 = (pos.y * tex.width) + pos.x;
	pos2 = Mathf.Round (pos2);
	pixels[pos2] = Color.red;
	tex.SetPixels (pixels); 
	tex.Apply();
}
static function GaussFalloff (distance : float , inRadius : float) {
	return Mathf.Clamp01 (Mathf.Pow (360.0, -Mathf.Pow (distance / inRadius, 2.5) - 0.01));
}
var maxx : float = 0.5;
var inRadius : float = 1;
var power : float = 0.01;
private var texwidth = 0;
private var falloff : float = 0;
private var posx : int = 0;
private var posy : int = 0;
private var distance : float = 0;
private var xb2 : int = 0;
private var yb2 : int = 0;
private var sqrMagnitude : float = 0;
private var begin : int = 0;
private var end : int = 0;
private var amount : float = 0;
var random : float = 0;
var col : Color[];
var coltex = 0;
private var splatmapn = 1;
private var rd : float = 0;
function paintalpha0 (xb,yb) {
	var ybworld = yb * texwidth;
	var sqrRad = inRadius * inRadius;
	var distance : float = 0;
	xb2 = xb;
	yb2 = yb;
	begin = (texwidth*(yb2-brsize))+(xb2-brsize);
	end = (texwidth*(yb2+brsize))-(texwidth-(xb+brsize));
	if (begin <= 0) {
		begin = 0;
	}
	if (end >= pixels.length) {
		end = pixels.length;	
	}
	splatmapn = Mathf.Floor(coltex/5) +1;
	for (i=begin;i<end;i++) {
		posy = Mathf.Floor(i/texwidth);//wich y verticle are we procesing
		posx = i - (posy*texwidth);
		if (posx < (xb2-brsize) || posx > (xb2+brsize)) {
			continue;
		}
		sqrMagnitude = (Vector3(posy,0,posx) - Vector3(yb,0,xb)).sqrMagnitude;
		if (sqrMagnitude > sqrRad)//If to far to the verticle skip to edit it
			continue;
		distance = Mathf.Sqrt(sqrMagnitude);//Distance to verticle
		falloff = GaussFalloff(distance, inRadius);
		if (random>0) {
			rd = Random.value * random;
			amount = falloff * power * Time.deltaTime * (rd +(1 - (rd/2)));
		} else {
			amount = falloff * power * Time.deltaTime;
		}
		//amount = falloff * power * Time.deltaTime * rd;
		//var col : Color = Color(amount * rc,amount * gc,-amount * bc,0);
		if (splatmapn == 1) {
			if (pixels[i].r < maxx  pixels[i].g < maxx  pixels[i].b < maxx) {
				//pixels[i] += col * amount;
				pixels[i] = Color.Lerp (pixels[i],col[coltex],amount);
				pixels2[i] = Color.Lerp (pixels2[i],Color(0,0,0,0),amount);
			}
		} else if (splatmapn == 2) {
			if (pixels2[i].r < maxx  pixels2[i].g < maxx  pixels2[i].b < maxx) {
				//pixels[i] += col * amount;
				pixels[i] = Color.Lerp (pixels[i],Color(0,0,0,0),amount);
				pixels2[i] = Color.Lerp (pixels2[i],col[coltex],amount);
			}
		}
		
	}
	var mipCount = tex.mipmapCount;
	for( var mip = 0; mip < mipCount; ++mip ) {
        tex2.SetPixels(pixels2, mip);
        tex.SetPixels(pixels, mip);
    }
	tex2.Apply();
	tex.Apply();
	
}
function GetColorx (xb,yb) {
	var pickcol = tex.GetPixel(xb,yb);
	col[0] = pickcol;
	coltex = 0;
}

Thank you,

This is wonderfull stuff to use in my terrain generation too.

Do you have any idea if its possible using similar techniques to paint for example trees and foliage on the terrain?

I know you could instantiate trees based on the terrain height, but I really mean painting so they also become part of the optimised terrain rendering algorithms.

Kind regards,

Bart

No, unfortunately I don’t… I’m working on the same thing… I’m building a WorldBuilder you see.

If you comes up with something can you post it in the forum? I will do the same if I find out how to do it.

/Aron

It looks like http://files.unity3d.com/joe/GenerateTrees.zip has more information about how to do this…

Hope this works

Yey, I made it… Thanks for the link, it was really usefull :smile:
Here is a web-player, go to the trees button.
http://arongranberg.com/unity/worldbuilder

Nice demo you have there.

However, it took me some time to be able to navigate correctly. It starts with an extremely high cliff :slight_smile:

Also, is it possible that the house model is absolutely not in proportion to the rest of the world/trees ?

Would you also be capable of putting grass this way?

Any possiblility to have a look at your code for this ?

Great work,

Greetz,
Bart

This would be a great addition to the wiki.

As a new unity user, it’s somewhat distressing to see all the code snippets and other gems that are buried deep in the forums. You just happen to stumble upon them as they never seems to have made it onto the wiki.

You sound like PacMan :slight_smile:

Sorry for placing a cliff at the start I had just been playing around with heightmaps.
Yes I think it can be done with grass too, I just have to find the right name for it,
like “GrassInstance”, they are not highlighted in Unitron.
Right now I shall try to create brushes, it shouldn’t be so hard.

BTW can someone give me an example of how to write data to an xml file? I want to be able to save large amounts of data easily.

PS: Coming up with a new demo soon.

/Aron