みけCATのにっき(仮)
つれづれなるまゝに、日くらし、PCにむかひて、心に移りゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
(本当か!?)
出典

【3D】続・三角形に画像を貼り付けてみる【モデルもあるよ】

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

【3D】続・三角形に画像を貼り付けてみる【モデルもあるよ】

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

前の日記で、一時変換を使用して3D空間内の三角形に画像を貼り付けてみましたが、
単純な一時変換だと画像が歪んで見えてしまいます。
[album]489[/album]
そこで、「透視補正」をかけます。
前のプログラムのように画像の上/下を選択するのではなく、テクスチャ内の座標で指定するプログラムにしました。
テクスチャ内の画像の左下が(0,0)で、右上が(1,1)です。

CODE:

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 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;
	double ntx,nty;
	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;
	if(zz1my) {
		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;irx) {
			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;jrx) {
			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);
		}
	}
}
このプログラムを使用すると、このように綺麗に描画できます。
[album]490[/album]
ただし、旧エンジンでは37fps程度なのに対し、新エンジンが同じシーンで26fpsと、
若干fpsが下がってしまいました。

ついでに、同じような動作のプログラムをDXライブラリに移植し、比較してみました。
こちらが自作プログラムです。17fps程度です。
[album]491[/album]
そして、こちらがDXライブラリを使用したプログラムです。当たり前のように60fps程度出ます。
[album]492[/album]

この技術を応用して、PMDモデルを描画してみました。
しかし、28fpsと低いfpsで、しかも本家のように綺麗には描画されず、ベタ塗りになっています。
それでもある程度の精度は得られています。
なお、テクスチャとしてはBMPファイルしか読み込めないので、モデルによってはおかしくなります。
[album]493[/album]

この3種類のプログラムを添付しておきます。
添付ファイル

[拡張子 zip は無効化されているため、表示できません]

[拡張子 zip は無効化されているため、表示できません]

[拡張子 zip は無効化されているため、表示できません]

最後に編集したユーザー みけCAT on 2012年9月02日(日) 10:10 [ 編集 1 回目 ]
理由: ファイルの差し替え

コメントはまだありません。