Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,721
|
Here's a video processor that is cleaned up and has fewer stitching artifacts:
Code:
//equirectangular 360 panner
//@param1:fov_ang 'fov' 90 20 170 90 1
//@param2:x_ang 'yaw' 0 -180 180 0 1
//@param3:y_ang 'pitch' 0 -90 90 0 1
//@param4:z_ang 'roll' 0 -180 180 0 1
project_w=1920;
project_h=1080;
xdiv=ydiv=100; // subdivision (quality) 10-200 is usable
filter=1; // bilinear filtering?
xscale=1; // -1 to flip yaw
yscale=1; // -1 to flip pitch
zscale=1; // -1 to flip roll
function matrix_make_rotate(matrix, m, d) global() local(m2) (
memset(matrix,0,16);
matrix[m*5-5] = matrix[15] = 1.0;
m2 = ((m%=3)+1)%3;
matrix[m2*5]=matrix[m*5]=cos(d);
matrix[m2*4+m]=-(matrix[m*4+m2]=sin(d));
);
function matrix_make_xlate(matrix, x, y, z) global() (
memset(matrix,0,16);
matrix[0]=matrix[5]=matrix[10]=matrix[15]=1;
matrix[3]=x; matrix[7]=y; matrix[11]=z;
);
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];
loop(4, dest[0] = s0*src[0]+s1*src[4]+s2*src[8]+s3*src[12]; dest+=1; src+=1; );
src -= 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];
);
function vector_project(vv*, s*) global(srcw,srch) (
s.y = srch * (0.5 + asin(vv.y / sqrt(vv.x*vv.x+vv.y*vv.y+vv.z*vv.z)) * (1/$pi));
s.x = srcw * (0.5 + atan2(vv.x,vv.z) * (1 / (2*$pi)));
);
function centerx(sm*, v*) global(srcw) (
v.x < sm.x-srcw*.5 ? ( v.x += srcw; 2; ) : v.x > sm.x+srcw*.5 ? ( v.x -= srcw; 1; );
);
gfx_img_resize(-1,project_w,project_h);
input_info(0,srcw,srch);
gfx_mode=filter ? 0x100 : 0;
screen_z = project_w/tan(fov_ang * 0.5 * $pi / 180);
dxpos=project_w/(xdiv-1);
dypos=project_h/(ydiv-1);
ypos = 0;
matrix1 = 0; matrix2 = matrix1 + 16;
matrix_make_rotate(matrix1,2,xscale * x_ang * -$pi / 180);
matrix_make_rotate(matrix2,1,yscale * y_ang * $pi / 180); matrix_multiply(matrix1,matrix2);
matrix_make_rotate(matrix2,3,z_ang * -$pi / 180); matrix_multiply(matrix1,matrix2);
matrix_make_xlate(matrix2,project_w*-.5,project_h*-.5,0); matrix_multiply(matrix1,matrix2);
loop(ydiv,
y1=(ypos)&0xffffe;
y2=(ypos+=dypos)&0xffffe;
idy = 1/(y2-y1);
xpos = 0;
loop(xdiv,
x1=(xpos)&0xffffe;
x2=(xpos+=dxpos)&0xffffe;
idx = 1/(x2-x1);
matrix_apply(x1,y1,screen_z,matrix1,vv); vector_project(vv, s1);
matrix_apply(x2,y1,screen_z,matrix1,vv); vector_project(vv, s2);
matrix_apply(x1,y2,screen_z,matrix1,vv); vector_project(vv, s3);
matrix_apply(x2,y2,screen_z,matrix1,vv); vector_project(vv, s4);
a=centerx(s1,s2)|centerx(s1,s3)|centerx(s1,s4);
dsdx = (s2.x-s1.x) * idx;
dtdx = (s2.y-s1.y) * idx;
dsdy = (s3.x-s1.x) * idy;
dtdy = (s3.y-s1.y) * idy;
dsdx2 = (s4.x-s3.x) * idx;
dtdx2 = (s4.y-s3.y) * idx;
dsdxdy = (dsdx2-dsdx) * idy;
dtdxdy = (dtdx2-dtdx) * idy;
gfx_deltablit(0, x1,y1, x2-x1,y2-y1, s1.x,s1.y, dsdx, dtdx, dsdy, dtdy, dsdxdy, dtdxdy);
(a&1) ? gfx_deltablit(0, x1,y1, x2-x1,y2-y1, s1.x+srcw,s1.y, dsdx, dtdx, dsdy, dtdy, dsdxdy, dtdxdy);
(a&2) ? gfx_deltablit(0, x1,y1, x2-x1,y2-y1, s1.x-srcw,s1.y, dsdx, dtdx, dsdy, dtdy, dsdxdy, dtdxdy);
);
);
(edited with simplifications -- you can now configure the output dimensions in the code easily, and flip the x/y axes, etc)
(edited: added roll support)
Last edited by Justin; 06-29-2016 at 09:10 PM.
|