【3D】テクスチャの透視補正

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

【3D】テクスチャの透視補正

#1

投稿記事 by みけCAT » 13年前

Dev-C++5.2.0.3(gcc4.7.0)、Windows Vista SP2 32ビットです。
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);
				}
			}
		}
	}
}
もしくは、こちらのテクスチャ上の頂点に対応する座標を0~1で指定するコードからでも構いません。

コード:

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

よろしくお願いします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 【3D】テクスチャの透視補正

#2

投稿記事 by softya(ソフト屋) » 13年前

パースペクティブ補正とか呼ばれるもですが、テクスチャのUV透視補正は必要ですね。
そうしないとPS1やサターンのようになってしまいますが、CPUでやるのはもの凄くコストが掛かりますが大丈夫ですか?

書かれている通りに処理をピクセル単位で行う必要があります。
ここまで来ると車輪の再発明なので私もやったことがありません(面倒なので)。
もう少し頑張ってみてください。

要はピクセルごとに透視変換して位置を求めるだけです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 【3D】テクスチャの透視補正

#3

投稿記事 by みけCAT » 13年前

softya(ソフト屋) さんが書きました:CPUでやるのはもの凄くコストが掛かりますが大丈夫ですか?
大丈夫じゃなくても、やらないと画像が歪むので・・・
モードを切り替えられるようにしておきます。
softya(ソフト屋) さんが書きました:要はピクセルごとに透視変換して位置を求めるだけです。
もう少し詳しくお願いできますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 【3D】テクスチャの透視補正

#4

投稿記事 by softya(ソフト屋) » 13年前

みけCAT さんが書きました:
softya(ソフト屋) さんが書きました:CPUでやるのはもの凄くコストが掛かりますが大丈夫ですか?
大丈夫じゃなくても、やらないと画像が歪むので・・・
モードを切り替えられるようにしておきます。
softya(ソフト屋) さんが書きました:要はピクセルごとに透視変換して位置を求めるだけです。
もう少し詳しくお願いできますか?
さっき書かかれていた
http://www.geocities.co.jp/SiliconValle ... /prg03.htm
以上の説明するとなると時間が掛かるので、しばらくは無理そうです。
私も理論上理解している(つもり?)だけですから。

【補足】
こういうのは悩みに悩んでやらないと身につかないので悩んだほうが良いと思うんですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 【3D】テクスチャの透視補正

#5

投稿記事 by みけCAT » 13年前

http://ameblo.jp/summerclap/entry-10284588299.htmlを参考に書いてみたところ、
見た目が改善したように見えました。
こんな感じでいいのでしょうか?
※UV座標に合わせて先ほどのコードとテクスチャの上下を反転しています

コード:

void draw3dHenkan2(
		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 uiz,miz,diz;
	double utx,uty,mtx,mty,dtx,dty;
	int lx,rx;
	double lz,rz,nz,iz;
	double liz,riz,niz;
	double ltx,rtx,lty,rty;
	int i,j;
	int x,y;
	int rflag;
	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;
	uiz=1/uz;miz=1/mz;diz=1/dz;
	utx=utx*uiz;
	uty=uty*uiz;
	mtx=mtx*miz;
	mty=mty*miz;
	dtx=dtx*diz;
	dty=dty*diz;
	if(uy>my) {
		temp=ux;ux=mx;mx=temp;
		temp=uy;uy=my;my=temp;
		dtemp=uz;uz=mz;mz=dtemp;
		dtemp=uiz;uiz=miz;miz=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=miz;miz=diz;diz=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=uiz;uiz=miz;miz=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));
		liz=uiz+(dy==uy?0:(diz-uiz)*(i-uy)/(dy-uy));
		riz=uiz+(my==uy?0:(miz-uiz)*(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=liz;liz=riz;riz=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));
			niz=liz+(rx==lx?0:(riz-liz)*(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/niz*bmpGetWidth(bmp))%bmpGetWidth(bmp);
			y=(int)(nty/niz*bmpGetHeight(bmp))%bmpGetHeight(bmp);
			if(x<0)x+=bmpGetWidth(bmp);
			if(y<0)y+=bmpGetHeight(bmp);
			y=bmpGetHeight(bmp)-1-y;
			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));
		liz=miz+(dy==my?0:(diz-miz)*(i-my)/(dy-my));
		riz=uiz+(dy==uy?0:(diz-uiz)*(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=liz;liz=riz;riz=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));
			niz=liz+(rx==lx?0:(riz-liz)*(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/niz*bmpGetWidth(bmp))%bmpGetWidth(bmp);
			y=(int)(nty/niz*bmpGetHeight(bmp))%bmpGetHeight(bmp);
			if(x<0)x+=bmpGetWidth(bmp);
			if(y<0)y+=bmpGetHeight(bmp);
			y=bmpGetHeight(bmp)-1-y;
			setRGB(j,i,bmpGetXY(bmp,x,y).r,bmpGetXY(bmp,x,y).g,bmpGetXY(bmp,x,y).b,nz);
		}
	}
}
プロジェクトを添付します。
F2で新エンジンを使用、F3で旧エンジンを使用します。
添付ファイル
3dtexture.zip
プロジェクトです。
(217.54 KiB) ダウンロード数: 117 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 【3D】テクスチャの透視補正

#6

投稿記事 by softya(ソフト屋) » 13年前

画像が網目状とか分りやすいものじゃないと正しいか判定しづらいですね。
あと三角メッシュじゃないのでズレが分かりづらいのかも(PS1は三角だったのでわかり易かった)。
カメラをよせたりするとはっきりするので、カメラ操作に距離も加えて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 【3D】テクスチャの透視補正

#7

投稿記事 by みけCAT » 13年前

softya(ソフト屋) さんが書きました:画像が網目状とか分りやすいものじゃないと正しいか判定しづらいですね。
前から格子テクスチャファイルは入れてありましたが、プログラムから切り替えられるようにしました。
softya(ソフト屋) さんが書きました:カメラをよせたりするとはっきりするので、カメラ操作に距離も加えて下さい。
距離の変更、および平行移動モードを追加しました。
softya(ソフト屋) さんが書きました:あと三角メッシュじゃないのでズレが分かりづらいのかも(PS1は三角だったのでわかり易かった)。
どういうことでしょうか?

テクスチャはimage.bmp及びimage_alt.bmpを差し替えることにより変更できます。
操作方法はReadMe.txtを参照してください。
添付ファイル
3dtexture.zip
プログラムです。
(219.63 KiB) ダウンロード数: 118 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 【3D】テクスチャの透視補正

#8

投稿記事 by softya(ソフト屋) » 13年前

確認しました。大丈夫そうですね。
三角メッシュだったんですね。忘れてました。申し訳ないです。

しかし重いです。アップにするとコマ落ちどころのレベルではないですね。
高速化するとなるとアセンブラレベルでSSEの利用やスレッド化しないと無理でしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 【3D】テクスチャの透視補正

#9

投稿記事 by みけCAT » 13年前

ありがとうございます。
高速化はまた余裕ができたら考えることにします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る