0 registered members (),
1,094
guests, and 1
spider. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Slope Blendmap Generator
#434076
12/11/13 19:43
12/11/13 19:43
|
Joined: Aug 2002
Posts: 3,258 Mainz
oliver2s
OP
Expert
|
OP
Expert
Joined: Aug 2002
Posts: 3,258
Mainz
|
This code generates a blendmap out of a given heightmap. The angles which defines a slope (between 0-90 degrees) can be adjusted via function parameter.
BMAP* bmap_heightmap_to_normalmap(BMAP* bmap_hmap_,BMAP* bmap_nmap_,var factor_);
//Make Blendmap from Heightmap on slopes
///////////////////////////////
// bmap_hmap_ -> heightmap
// bmap_blendmap_ -> blendmap which will be painted or NULL for creating new blendmap
// color_ -> color which will be painted in blendmap on slopes
// gradientMin_ -> angle of slopes where painting should begin (range 0-90)
// gradientMax_ -> angle of slopes where painting should stop (range 0-90)
///////////////////////////////
BMAP* bmap_heightmap_to_blendmap_slopes(BMAP* bmap_hmap_,BMAP* bmap_blmap_,COLOR* color_,var gradientMin_,var gradientMax_)
{
//clear up gradients
var gradient_min_=gradientMin_;
var gradient_max_=gradientMax_;
if(gradient_max_<gradient_min_)
{
gradient_max_=gradientMin_;
gradient_min_=gradientMax_;
}
gradient_min_=clamp(gradient_min_,0,90);
gradient_max_=clamp(gradient_max_,0,90);
if(gradient_min_==gradient_max_){ return NULL; }
//store color
COLOR c1_;
c1_.red=color_.red;
c1_.green=color_.green;
c1_.blue=color_.blue;
//get size
var size_x_=bmap_width(bmap_hmap_);
var size_y_=bmap_height(bmap_hmap_);
//create tmp normalmap bmap
BMAP* normalmap_=bmap_heightmap_to_normalmap(bmap_hmap_,NULL,1);
//create temp bitmap for blendmap
BMAP* blendmap_=bmap_createblack(size_x_,size_y_,24);
//search slopes within the given range on normalmap
int py; for(py=0;py<size_y_;py++)
{
int px; for(px=0;px<size_x_;px++)
{
//get normalmap pixel
COLOR c_;
var format=bmap_lock(normalmap_,0);var alpha_;
var pixel=pixel_for_bmap(normalmap_, px, py);
pixel_to_vec(c_,alpha_,format,pixel);
bmap_unlock(normalmap_);
//convert normalmap pixel to normal vector
VECTOR n;
n.x = 2.0*(c_.red-128);
n.y = 2.0*(c_.green-128);
n.z = 2.0*(c_.blue-128);
//normalize to 0-1
vec_normalize(n,1);
//get Euler angle
var angle = 90-asinv(abs(n.z));
//if angle is between given angles, paint blendmap
if(angle>=gradient_min_ && angle<=gradient_max_)
{
//paint given color to blendmap
var format=bmap_lock(blendmap_,0);
var pixel=pixel_for_vec(c1_,100,format);
pixel_to_bmap(blendmap_, px, py, pixel);
bmap_unlock(blendmap_);
}
}
}
//remove tmp normalmap
bmap_purge(normalmap_);
bmap_remove(normalmap_);
//return new created blendmap if no target bitmap was passed to function
if(bmap_blmap_==NULL){return blendmap_;}
else
{
//otherwise copy created blendmap to target bitmap
bmap_blit(bmap_blmap_,blendmap_,NULL,vector(bmap_width(bmap_blmap_),bmap_height(bmap_blmap_),0));
//delete temp bitmap
bmap_purge(blendmap_);
bmap_remove(blendmap_);
//return
return bmap_blmap_;
}
}
BMAP* bmap_heightmap_to_normalmap(BMAP* bmap_hmap_,BMAP* bmap_nmap_,var factor_)
{
//get size
var size_x_=bmap_width(bmap_hmap_);
var size_y_=bmap_height(bmap_hmap_);
BMAP* normalmap_=bmap_createblack(size_x_,size_y_,24);
int py; for(py=0;py<size_y_;py++)
{
int px; for(px=0;px<size_x_;px++)
{
//get height of 3 neighbor pixels
COLOR color_;
var c1,c2,c3;
var format=bmap_lock(bmap_hmap_,0);var alpha_;
var pixel=pixel_for_bmap(bmap_hmap_, clamp(px-1,0,size_x_), clamp(py-1,0,size_y_));
pixel_to_vec(color_,alpha_,format,pixel); c1=color_.red;
var pixel=pixel_for_bmap(bmap_hmap_, clamp(px+1,0,size_x_), clamp(py-1,0,size_y_));
pixel_to_vec(color_,alpha_,format,pixel); c2=color_.red;
var pixel=pixel_for_bmap(bmap_hmap_, clamp(px-1,0,size_x_), clamp(py+1,0,size_y_));
pixel_to_vec(color_,alpha_,format,pixel); c3=color_.red;
bmap_unlock(bmap_hmap_);
//build temporary points that makes a triangle
VECTOR v1,v2,p1,p2,p3;
p1.x=0;p1.y=0;p1.z=c1*factor_;
p2.x=32;p2.y=0;p2.z=c2*factor_;
p3.x=0;p3.y=32;p3.z=c3*factor_;
//get first vector for cross product (p2-p1)
v1.x=p2.x-p1.x;
v1.y=p2.y-p1.y;
v1.z=p2.z-p1.z;
//get second vector for cross product (p3-p1)
v2.x=p3.x-p1.x;
v2.y=p3.y-p1.y;
v2.z=p3.z-p1.z;
//calculate cross product of v1 and v2
VECTOR n;
vec_cross(n,v1,v2);
//normalize to color range 0-255
vec_normalize(n,255);
//convert vector into normalmap color
n.x=n.x/2 + 128;
n.y=n.y/2 + 128;
n.z=n.z/2 + 128;
//copy color
COLOR color1_;
color1_.red=n.x;
color1_.green=n.y;
color1_.blue=n.z;
//get height of another 3 neighbor pixels
COLOR color_;
var c1,c2,c3;
var format=bmap_lock(bmap_hmap_,0);var alpha_;
var pixel=pixel_for_bmap(bmap_hmap_, clamp(px+1,0,size_x_), clamp(py+1,0,size_y_));
pixel_to_vec(color_,alpha_,format,pixel); c1=color_.red;
var pixel=pixel_for_bmap(bmap_hmap_, clamp(px-1,0,size_x_), clamp(py+1,0,size_y_));
pixel_to_vec(color_,alpha_,format,pixel); c2=color_.red;
var pixel=pixel_for_bmap(bmap_hmap_, clamp(px+1,0,size_x_), clamp(py-1,0,size_y_));
pixel_to_vec(color_,alpha_,format,pixel); c3=color_.red;
bmap_unlock(bmap_hmap_);
//build temporary points that makes a triangle
VECTOR v1,v2,p1,p2,p3;
p1.x=32;p1.y=32;p1.z=c1*factor_;
p2.x=0;p2.y=32;p2.z=c2*factor_;
p3.x=32;p3.y=0;p3.z=c3*factor_;
//get first vector for cross product (p2-p1)
v1.x=p2.x-p1.x;
v1.y=p2.y-p1.y;
v1.z=p2.z-p1.z;
//get second vector for cross product (p3-p1)
v2.x=p3.x-p1.x;
v2.y=p3.y-p1.y;
v2.z=p3.z-p1.z;
//calculate cross product of v1 and v2
VECTOR n;
vec_cross(n,v1,v2);
//normalize to color range 0-255
vec_normalize(n,255);
//convert vector into normalmap color
n.x=n.x/2 + 128;
n.y=n.y/2 + 128;
n.z=n.z/2 + 128;
//copy color
COLOR color2_;
color2_.red=n.x;
color2_.green=n.y;
color2_.blue=n.z;
COLOR color_;
color_.red=(color1_.red+color2_.red)/2;
color_.green=(color1_.green+color2_.green)/2;
color_.blue=(color1_.blue+color2_.blue)/2;
//add to pixels
var format=bmap_lock(normalmap_,0);
var pixel=pixel_for_vec(color_,100,format);
pixel_to_bmap(normalmap_, px, py, pixel);
bmap_unlock(normalmap_);
}
}
//return new created Normalmap if no target bitmap was passed to function
if(bmap_nmap_==NULL){return normalmap_;}
else
{
//otherwise copy created Normalmap to target bitmap
bmap_blit(bmap_nmap_,normalmap_,NULL,vector(bmap_width(bmap_nmap_),bmap_height(bmap_nmap_),0));
//delete temp bitmap
bmap_purge(normalmap_);
bmap_remove(normalmap_);
//return
return bmap_nmap_;
}
}
All scripts to make a terrain like in the screenshot above: 1. Combine a Perlin Noise Heightmap of 2/3 with a Voronoi Heightmap of 1/3 2. Use the Perturbation Filter over the combined heightmap. 3. Run the Hydralic Erosion Script over the heightmap. 4. Blur it a litte bit (had no script yet for this, made this in Photoshop)
|
|
|
Re: Slope Blendmap Generator
[Re: lemming]
#434108
12/12/13 19:16
12/12/13 19:16
|
Joined: Sep 2003
Posts: 6,861 Kiel (Germany)
Superku
Senior Expert
|
Senior Expert
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
|
I really like the mesh of the terrain from the screenshot (in terms of usability for video games)! However, I think the terrain really needs triplanar texture mapping, the stretched texture on the slopes if not up to date. Btw. just saw the following part of your code:
VECTOR n;
n.x = 2.0*(c_.red-128);
n.y = 2.0*(c_.green-128);
n.z = 2.0*(c_.blue-128);
//normalize to 0-1
vec_normalize(n,1);
//get Euler angle
ANGLE rotation;
vec_rotate(n,vector(0,-90,0));
vec_to_angle(rotation,n);
//if angle is between given angles, paint blendmap
if(abs(rotation.tilt)>gradient_min_ && abs(rotation.tilt)<gradient_max_)
Basically you are only interested in the z-component of the normal vector, aren't you? If it's 1 your rotation.tilt is 0, near 1 the slope is near 90° in incline. Thus you should be able to skip the whole (vec_to_)angle stuff and work with the normal vector directly.
"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual Check out my new game: Pogostuck: Rage With Your Friends
|
|
|
Re: Slope Blendmap Generator
[Re: Superku]
#434109
12/12/13 19:55
12/12/13 19:55
|
Joined: Aug 2002
Posts: 3,258 Mainz
oliver2s
OP
Expert
|
OP
Expert
Joined: Aug 2002
Posts: 3,258
Mainz
|
However, I think the terrain really needs triplanar texture mapping, the stretched texture on the slopes if not up to date. Yes you are right. This is one thing I should work on. Never read about theory behind it, but I'm sure a google search give me dozen of papers about this. Basically you are only interested in the z-component of the normal vector, aren't you? If it's 1 your rotation.tilt is 0, near 1 the slope is near 90° in incline. Thus you should be able to skip the whole (vec_to_)angle stuff and work with the normal vector directly. I really suck at vector mathematics. but I think vec_to_angle is neccesary, because you need the exact euler angle. The normal vector gives you only the direction.
|
|
|
Re: Slope Blendmap Generator
[Re: oliver2s]
#434112
12/12/13 20:55
12/12/13 20:55
|
Joined: Feb 2010
Posts: 886
Random
User
|
User
Joined: Feb 2010
Posts: 886
|
What did you use to create your terrain?
|
|
|
|