3次元の立方体に画像を貼り付けてみているのですが、
回転させると画像が歪んで見えます。
調べてみると、「透視補正」というものをしなくてはいけないようなのですが、
わからなくなってしまいました。
このコードに透視補正をつけるにはどうすればいいでしょうか?
#include "3d.h"
#include "bmpio.h"
#include "main.h"
static void setHenkan(double henkan[2][2],
int width,int height,int x1,int y1,int x2,int y2) {
henkan[0][0]=(double)x1/width;
henkan[0][1]=(double)x2/height;
henkan[1][0]=(double)y1/width;
henkan[1][1]=(double)y2/height;
}
static int calcuateInvMatrix(double out[2][2],double in[2][2]) {
double delta;
delta=in[0][0]*in[1][1]-in[0][1]*in[1][0];
if(delta==0)return 0;
out[0][0]=in[1][1]/delta;
out[0][1]=-in[0][1]/delta;
out[1][0]=-in[1][0]/delta;
out[1][1]=in[0][0]/delta;
return 1;
}
void draw3dHenkan(
int x1,int y1,int z1,
int x2,int y2,int z2,
int x3,int y3,int z3,
int isUpper,const bmp_t* bmp,
const camera_t* camera) {
int xx1,yy1,xx2,yy2,xx3,yy3;
double zz1,zz2,zz3;
double tx,ty;
int ux,uy,mx,my,dx,dy,temp;
double uz,mz,dz,dtemp;
int lx,rx;
double lz,rz,nz;
int i,j;
int x,y,nx,ny;
double henkan[2][2];
double invHenkan[2][2];
char debug[1024];
henkan3dzahyou(&tx,&ty,&zz1,x1,y1,z1,camera);
xx1=(int)tx;yy1=(int)ty;
henkan3dzahyou(&tx,&ty,&zz2,x2,y2,z2,camera);
xx2=(int)tx;yy2=(int)ty;
henkan3dzahyou(&tx,&ty,&zz3,x3,y3,z3,camera);
xx3=(int)tx;yy3=(int)ty;
ux=xx1;uy=yy1;mx=xx2;my=yy2;dx=xx3;dy=yy3;
uz=zz1;mz=zz2;dz=zz3;
if(uy>my) {
temp=ux;ux=mx;mx=temp;
temp=uy;uy=my;my=temp;
dtemp=uz;uz=mz;mz=dtemp;
}
if(my>dy) {
temp=mx;mx=dx;dx=temp;
temp=my;my=dy;dy=temp;
dtemp=mz;mz=dz;dz=dtemp;
}
if(uy>my) {
temp=ux;ux=mx;mx=temp;
temp=uy;uy=my;my=temp;
dtemp=uz;uz=mz;mz=dtemp;
}
if(isUpper) {
setHenkan(henkan,bmpGetWidth(bmp),bmpGetHeight(bmp),
xx2-xx1,yy2-yy1,xx3-xx1,yy3-yy1);
if(!calcuateInvMatrix(invHenkan,henkan))return;
for(i=uy;i<my;i++) {
lx=ux+(dy==uy?0:(dx-ux)*(i-uy)/(dy-uy));
rx=ux+(my==uy?0:(mx-ux)*(i-uy)/(my-uy));
lz=uz+(dy==uy?0:(dz-uz)*(i-uy)/(dy-uy));
rz=uz+(my==uy?0:(mz-uz)*(i-uy)/(my-uy));
if(lx>rx) {
temp=lx;lx=rx;rx=temp;
dtemp=lz;lz=rz;rz=dtemp;
}
for(j=lx;j<=rx;j++) {
nx=j-xx1;ny=i-yy1;
nz=lz+(rx==lx?0:(rz-lz)*(j-lx)/(rx-lx));
x=invHenkan[0][0]*nx+invHenkan[0][1]*ny;
y=invHenkan[1][0]*nx+invHenkan[1][1]*ny;
if(x>=0 && y>=0 && x<bmpGetWidth(bmp) && y<bmpGetHeight(bmp)) {
setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
}
}
}
for(i=my;i<=dy;i++) {
lx=mx+(dy==my?0:(dx-mx)*(i-my)/(dy-my));
rx=ux+(dy==uy?0:(dx-ux)*(i-uy)/(dy-uy));
lz=mz+(dy==my?0:(dz-mz)*(i-my)/(dy-my));
rz=uz+(dy==uy?0:(dz-uz)*(i-uy)/(dy-uy));
if(lx>rx) {
temp=lx;lx=rx;rx=temp;
dtemp=lz;lz=rz;rz=dtemp;
}
for(j=lx;j<=rx;j++) {
nx=j-xx1;ny=i-yy1;
nz=lz+(rx==lx?0:(rz-lz)*(j-lx)/(rx-lx));
x=invHenkan[0][0]*nx+invHenkan[0][1]*ny;
y=invHenkan[1][0]*nx+invHenkan[1][1]*ny;
if(x>=0 && y>=0 && x<bmpGetWidth(bmp) && y<bmpGetHeight(bmp)) {
setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
}
}
}
} else {
setHenkan(henkan,bmpGetWidth(bmp),bmpGetHeight(bmp),
xx1-xx3,yy1-yy3,xx1-xx2,yy1-yy2);
if(!calcuateInvMatrix(invHenkan,henkan))return;
for(i=uy;i<my;i++) {
lx=ux+(dy==uy?0:(dx-ux)*(i-uy)/(dy-uy));
rx=ux+(my==uy?0:(mx-ux)*(i-uy)/(my-uy));
lz=uz+(dy==uy?0:(dz-uz)*(i-uy)/(dy-uy));
rz=uz+(my==uy?0:(mz-uz)*(i-uy)/(my-uy));
if(lx>rx) {
temp=lx;lx=rx;rx=temp;
dtemp=lz;lz=rz;rz=dtemp;
}
for(j=lx;j<=rx;j++) {
nx=xx1-j;ny=yy1-i;
nz=lz+(rx==lx?0:(rz-lz)*(j-lx)/(rx-lx));
x=invHenkan[0][0]*nx+invHenkan[0][1]*ny;
y=invHenkan[1][0]*nx+invHenkan[1][1]*ny;
if(x>=0 && y>=0 && x<bmpGetWidth(bmp) && y<bmpGetHeight(bmp)) {
x=bmpGetWidth(bmp)-x-1;y=bmpGetHeight(bmp)-y-1;
setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
}
}
}
for(i=my;i<=dy;i++) {
lx=mx+(dy==my?0:(dx-mx)*(i-my)/(dy-my));
rx=ux+(dy==uy?0:(dx-ux)*(i-uy)/(dy-uy));
lz=mz+(dy==my?0:(dz-mz)*(i-my)/(dy-my));
rz=uz+(dy==uy?0:(dz-uz)*(i-uy)/(dy-uy));
if(lx>rx) {
temp=lx;lx=rx;rx=temp;
dtemp=lz;lz=rz;rz=dtemp;
}
for(j=lx;j<=rx;j++) {
nx=xx1-j;ny=yy1-i;
nz=lz+(rx==lx?0:(rz-lz)*(j-lx)/(rx-lx));
x=invHenkan[0][0]*nx+invHenkan[0][1]*ny;
y=invHenkan[1][0]*nx+invHenkan[1][1]*ny;
if(x>=0 && y>=0 && x<bmpGetWidth(bmp) && y<bmpGetHeight(bmp)) {
x=bmpGetWidth(bmp)-x-1;y=bmpGetHeight(bmp)-y-1;
setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
}
}
}
}
}void draw3dHenkan(
double x1,double y1,double z1,
double x2,double y2,double z2,
double x3,double y3,double z3,
double tx1,double ty1,
double tx2,double ty2,
double tx3,double ty3,
const bmp_t* bmp,
const camera_t* camera) {
int xx1,yy1,xx2,yy2,xx3,yy3;
double zz1,zz2,zz3;
double tx,ty;
int ux,uy,mx,my,dx,dy,temp;
double uz,mz,dz,dtemp;
double utx,uty,mtx,mty,dtx,dty;
int lx,rx;
double lz,rz,nz;
double ltx,rtx,lty,rty;
int i,j;
int x,y;
double ntx,nty;
double henkan[2][2];
double invHenkan[2][2];
if(bmp==NULL || camera==NULL)return;
henkan3dzahyou(&tx,&ty,&zz1,x1,y1,z1,camera);
xx1=(int)tx;yy1=(int)ty;
henkan3dzahyou(&tx,&ty,&zz2,x2,y2,z2,camera);
xx2=(int)tx;yy2=(int)ty;
henkan3dzahyou(&tx,&ty,&zz3,x3,y3,z3,camera);
xx3=(int)tx;yy3=(int)ty;
ux=xx1;uy=yy1;mx=xx2;my=yy2;dx=xx3;dy=yy3;
uz=zz1;mz=zz2;dz=zz3;
utx=tx1;uty=ty1;mtx=tx2;mty=ty2;dtx=tx3;dty=ty3;
if(uy>my) {
temp=ux;ux=mx;mx=temp;
temp=uy;uy=my;my=temp;
dtemp=uz;uz=mz;mz=dtemp;
dtemp=utx;utx=mtx;mtx=dtemp;
dtemp=uty;uty=mty;mty=dtemp;
}
if(my>dy) {
temp=mx;mx=dx;dx=temp;
temp=my;my=dy;dy=temp;
dtemp=mz;mz=dz;dz=dtemp;
dtemp=mtx;mtx=dtx;dtx=dtemp;
dtemp=mty;mty=dty;dty=dtemp;
}
if(uy>my) {
temp=ux;ux=mx;mx=temp;
temp=uy;uy=my;my=temp;
dtemp=uz;uz=mz;mz=dtemp;
dtemp=utx;utx=mtx;mtx=dtemp;
dtemp=uty;uty=mty;mty=dtemp;
}
for(i=uy;i<my;i++) {
lx=ux+(dy==uy?0:(dx-ux)*(i-uy)/(dy-uy));
rx=ux+(my==uy?0:(mx-ux)*(i-uy)/(my-uy));
lz=uz+(dy==uy?0:(dz-uz)*(i-uy)/(dy-uy));
rz=uz+(my==uy?0:(mz-uz)*(i-uy)/(my-uy));
ltx=utx+(dy==uy?0:(dtx-utx)*(i-uy)/(dy-uy));
rtx=utx+(my==uy?0:(mtx-utx)*(i-uy)/(my-uy));
lty=uty+(dy==uy?0:(dty-uty)*(i-uy)/(dy-uy));
rty=uty+(my==uy?0:(mty-uty)*(i-uy)/(my-uy));
if(lx>rx) {
temp=lx;lx=rx;rx=temp;
dtemp=lz;lz=rz;rz=dtemp;
dtemp=ltx;ltx=rtx;rtx=dtemp;
dtemp=lty;lty=rty;rty=dtemp;
}
for(j=lx;j<=rx;j++) {
nz=lz+(rx==lx?0:(rz-lz)*(j-lx)/(rx-lx));
ntx=ltx+(rx==lx?0:(rtx-ltx)*(j-lx)/(rx-lx));
nty=lty+(rx==lx?0:(rty-lty)*(j-lx)/(rx-lx));
x=(int)(ntx*bmpGetWidth(bmp))%bmpGetWidth(bmp);
y=(int)(nty*bmpGetHeight(bmp))%bmpGetHeight(bmp);
if(x<0)x+=bmpGetWidth(bmp);
if(y<0)y+=bmpGetHeight(bmp);
setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
}
}
for(i=my;i<=dy;i++) {
lx=mx+(dy==my?0:(dx-mx)*(i-my)/(dy-my));
rx=ux+(dy==uy?0:(dx-ux)*(i-uy)/(dy-uy));
lz=mz+(dy==my?0:(dz-mz)*(i-my)/(dy-my));
rz=uz+(dy==uy?0:(dz-uz)*(i-uy)/(dy-uy));
ltx=mtx+(dy==my?0:(dtx-mtx)*(i-my)/(dy-my));
rtx=utx+(dy==uy?0:(dtx-utx)*(i-uy)/(dy-uy));
lty=mty+(dy==my?0:(dty-mty)*(i-my)/(dy-my));
rty=uty+(dy==uy?0:(dty-uty)*(i-uy)/(dy-uy));
if(lx>rx) {
temp=lx;lx=rx;rx=temp;
dtemp=lz;lz=rz;rz=dtemp;
dtemp=ltx;ltx=rtx;rtx=dtemp;
dtemp=lty;lty=rty;rty=dtemp;
}
for(j=lx;j<=rx;j++) {
nz=lz+(rx==lx?0:(rz-lz)*(j-lx)/(rx-lx));
ntx=ltx+(rx==lx?0:(rtx-ltx)*(j-lx)/(rx-lx));
nty=lty+(rx==lx?0:(rty-lty)*(j-lx)/(rx-lx));
x=(int)(ntx*bmpGetWidth(bmp))%bmpGetWidth(bmp);
y=(int)(nty*bmpGetHeight(bmp))%bmpGetHeight(bmp);
if(x<0)x+=bmpGetWidth(bmp);
if(y<0)y+=bmpGetHeight(bmp);
setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
}
}
}http://dixq.net/forum/blog.php?u=536&b=3169
参考にしたサイトはこれです。
http://www.geocities.co.jp/SiliconValle ... /prg03.htm
http://ameblo.jp/summerclap/entry-10284588299.html
よろしくお願いします。