Another test version, removes some stitching artifacts but makes some others (ugh):
Code:
//Equirectangular 360 panner
//@param1:fov_ang 'fov' 90 20 170 45 1
//@param2:x_ang 'x' 0 -180 180 0.5 1
//@param3:y_ang 'y' 0 -90 90 0.5 1
//@param4:div 'div' 100 20 150 40 1
//@param5:filter 'filter' 0 0 1 0 1
project_w<1 ? project_w=1920;
project_h<1 ? project_h=1080;
gfx_img_resize(-1,project_w,project_h);
input_info(0,srcw,srch);
function matrix_make_rotate(matrix, m, d) global() local(m2)
(
memset(matrix,0,16);
matrix[m*5-5] = matrix[15] = 1.0;
m2 = m==2 ? 0 : (m+1);
matrix[m2*5]=matrix[m*5]=cos(d);
matrix[m2*4+m]=-(matrix[m*4+m2]=sin(d));
);
function matrix_multiply(dest,src) global() local(s0,s1,s2,s3)
(
loop(4,
s0=dest[0]; s1=dest[1]; s2=dest[2]; s3=dest[3];
dest[0] = s0*src[(0<<2)+0]+s1*src[(1<<2)+0]+s2*src[(2<<2)+0]+s3*src[(3<<2)+0];
dest[1] = s0*src[(0<<2)+1]+s1*src[(1<<2)+1]+s2*src[(2<<2)+1]+s3*src[(3<<2)+1];
dest[2] = s0*src[(0<<2)+2]+s1*src[(1<<2)+2]+s2*src[(2<<2)+2]+s3*src[(3<<2)+2];
dest[3] = s0*src[(0<<2)+3]+s1*src[(1<<2)+3]+s2*src[(2<<2)+3]+s3*src[(3<<2)+3];
dest+=4;
);
);
function matrix_apply(x,y,z, m, vec*) global()
(
vec.x = x*m[0] + y*m[1] + z*m[2] + m[3];
vec.y = x*m[4] + y*m[5] + z*m[6] + m[7];
vec.z = x*m[8] + y*m[9] + z*m[10] + m[11];
);
matrix1 = 0;
matrix2 = matrix1 + 16;
tab=matrix2 + 16;
xdiv=ydiv=div|0;
screen_z = 1/tan(fov_ang * 0.5 * $pi / 180);
y = -0.5 * (project_h/project_w);
dx = 1.0 / (xdiv-1);
dy = (project_h/project_w) / (ydiv-1);
matrix_make_rotate(matrix1,2,-x_ang * $pi / 180);
matrix_make_rotate(matrix2,1,y_ang * $pi / 180);
matrix_multiply(matrix1,matrix2);
xf=0;
ptr = tab;
loop(ydiv,
x=-0.5;
ya_offs=xa_offs=0;
loop(xdiv,
matrix_apply(x,y,screen_z,matrix1,vv);
ya = asin(vv.y / sqrt(vv.x*vv.x+vv.y*vv.y+vv.z*vv.z)) / $pi + ya_offs + 0.5;
xa = atan2(vv.x,vv.z)/(2*$pi) + xa_offs + 0.5;
x!=-0.5 ? (
xa>lxa+0.5 ? (
xa-=1;
xa_offs-=1;
) : xa < lxa-0.5 ? (
xa+=1;
xa_offs+=1;
);
ya>lya+ 0.5 ? (
ya-=1;
ya_offs-=1;
) : ya < lya-0.5 ? (
ya+=1;
ya_offs+=1;
);
);
lxa=xa;
lya=ya;
xa>1?xf|=1;
xa<0?xf|=2;
ptr[0]=xa*srcw;
ptr[1]=ya*srch;
x+=dx;
ptr+=2;
);
y+=dy;
);
//gfx_set(1,0,1);
//gfx_fillrect(0,0,project_w,project_h);
gfx_mode=filter > 0 ? 0x100 : 0;
gfx_xformblit(0, 0,0, project_w,project_h,xdiv,ydiv, tab,0);
ptr=tab;
loop(ydiv*xdiv,
ptr[0] -= srcw-0.5/*fudge*/;
ptr+=2;
);
(xf&1) ? gfx_xformblit(0, 0,0, project_w,project_h,xdiv,ydiv, tab,0);
ptr=tab;
loop(ydiv*xdiv,
ptr[0] += srcw*2+1.0;
ptr+=2;
);
(xf&2) ? gfx_xformblit(0, 0,0, project_w,project_h,xdiv,ydiv, tab,0);