//Generate Normalmap from Heightmap
///////////////////////////////
// bmap_hmap_ -> heightmap which data will be read from
// bmap_nmap_ -> target bitmap which the normalmap data will be written to
// if NULL is passed for bmap_nmap_, the function returns a new created bitmap
// factor_ -> bumpiness factor (recommended range: 0-2, default: 1)
///////////////////////////////
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_;
}
}