I'm hoping that someone may be able to help me out with this problem, I'm pulling what's left of my hair out again.
In the image below is a texture that's been spherized but the algorithm doesn't map it properly. I've googled day after day and found many sites with information about this, I think is called mercator transformation, but no listed maths or solutions to how it is actually done. The closest I found was some old source code on a blitz basic site but still no joy getting it working.
The input image is tiled, the output image should use some sort of spherical conversion algorithm to make it wrap onto a sphere without the pinching at the poles.
My code is based on this which I found: (absolutely no good)
double theta,phi,phi2;
int i,i2,j;
BITMAP *imagein,*imageout;
Form the input and output image arrays
Read an input image from a file
for (j=0;j<image.height;j++) {
theta = PI * (j - (image.height-1)/2.0) / (double)(image.height-1);
for (i=0;i<image.width;i++) {
phi = TWOPI * (i - image.width/2.0) / (double)image.width;
phi2 = phi * cos(theta);
i2 = phi2 * image.width / TWOPI + image.width/2;
if (i2 < 0 || i2 > image.width-1) {
newpixel = red; /* Should not happen */
} else {
newpixel = imagein[j*image.width+i2];
}
imageout[j*image.width+i] = image.newpixel;
}
}
My full code with the spherize functions at the end: Which is obviously not the correct algorithm.
sync on : sync rate 60 : autocam off
set window off
set display mode 1024,768,32
noise set params 0, 0.75, 0.02, 1.25, 8, 1
`img1 = create_perlin_texture(512,512)
`img2 = spherise_texture(img1)
imgs = create_perlin_sphere(256)
obj1 = find free object()
make object sphere obj1,100,32,32
texture object obj1,imgs
position camera 0,90,-90 : point camera 0,0,0
do
yrotate object obj1,object angle y(obj1)+0.5
`paste image img1,0,0
`paste image img2,0,256
paste image imgs,0,0
draw_cos()
sync
loop
end
function create_perlin_texture(wid,hgt)
bm = find free bitmap()
create bitmap bm,wid,hgt
noise set params 0, 0.75, 0.1, 1.25, 8, 0
lock pixels
for x=0 to wid-1
for y=0 to hgt-1
c = ( ( noise get height tiled (0,x,y,wid,hgt) + 1.0 ) / 2.0 ) * 255.0
if c<0 then c=0
if c>255 then c=255
c=c+(c<<8)+(c<<16)
dot x,y,c
next
next
unlock pixels
img = find free image()
get image img,0,0,wid,hgt
delete bitmap bm
endfunction img
function spherise_texture(img1)
wid = image width(img1)
hgt = image height(img1)
widh = wid/2
bm = find free bitmap()
create bitmap bm,wid*2,hgt
paste image img1,wid,0
lock pixels
cent = wid + widh
for y=0 to hgt-1
m# = widh / sin(180.0/hgt*y)
p# = widh / m#
for x=0 to widh
a# = p# * x
c=point( cent - a# , y )
dot widh - x , y, c
c=point( cent + a# , y )
dot widh + x , y, c
next
next
unlock pixels
img2 = find free image()
get image img2,0,0,wid-1,hgt-1
delete bitmap bm
endfunction img2
function create_perlin_sphere_old(size)
bm = find free bitmap() : create bitmap bm, size, size
sizeh = size / 2
lock pixels
for y = 0 to size
m# = sizeh / sin( 180.0 / size * y )
m# = sizeh / m#
for x=0 to sizeh
a# = m# * x
v# = noise get height tiled(0, sizeh - 1 - a#, y, size, size) : v# = 1.0 + ( v# / 2.0 ) * 255.0 : c = v#
if c<128 then c=rgb(c,c,128) else c=rgb(c,c,c)
dot sizeh-1-x,y,c
v# = noise get height tiled(0, sizeh + a#, y, size, size) : v# = 1.0 + ( v# / 2.0 ) * 255.0 : c = v#
if c<128 then c=rgb(c,c,128) else c=rgb(c,c,c)
dot sizeh+x,y,c
next
next y
unlock pixels
img = find free image() : get image img,0,0,size-1,size-1 : delete bitmap bm
endfunction img
function create_perlin_sphere(size)
bm = find free bitmap() : create bitmap bm, size, size
PI#=3.14136592 : TWOPI# = 2 * PI# : s#=size
lock pixels
for j=0 to size-1
`theta# = PI * (j - (size-1)/2.0) / (float)(size-1)
theta#=PI# * (j - (s#-1) / 2.0) / (s#-1)
for i=0 to size-1
phi#=TWOPI# * (i - s#/2.0) / s#
phi2#=phi#*cos(theta#*180.0/PI#)
i2# = phi2# * s# / TWOPI# + (s#/2.0) : i2=i2#
h#=noise get height tiled(0,i2,j,size,size)
h#=h# * 255.0
c=h#
if c<0 then c=rgb(abs(c),abs(c),255) else c=rgb(255,255-c,255-c)
dot i,j,c
next
next
unlock pixels
img = find free image() : get image img,0,0,size-1,size-1 : delete bitmap bm
endfunction img
function draw_cos()
for y=0 to 255
dot 127.5+sin(180.0/256.0*y)*127.5,y,0xffffff
next
endfunction
If anyone has any solutions to this problem, whether it called mercator or transvers mercator, or something else odd and has the formula/algorithm it would be greatly appreciated...
Each of the above functions has basically produced the same result, no corrected wrapping of the input texture...
NB: My code does actually use the perlin noise dll but the same code will also work on an input image of the same size.
Mental arithmetic? Me? (That's for computers) I can't subtract a fart from a plate of beans!
Warning! May contain Nuts!