//■レイトレーシング法による立体表示 // なお、画面例では、myWin.hのWHITE_BRUSHをLTGRAY_BRUSH(明るい灰色)に変えています。 // wndClass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); // #include "myWin.h" #include "my3Dmat.h" #include "stdio.h" #include "stdlib.h" #include "locale.h" #define LWIDTH 4 //線幅 #define AWIDTH 2 //軸の線幅 // ラベル #define LB_1 1001 // 方位角 #define LB_2 1002 // 仰角 #define LB_3 1003 // 距離 // エディットボックス #define ED_1 2001 // 方位角 #define ED_2 2002 // 仰角 #define ED_3 2003 // 距離 // ボタン #define BT_1 3001 // ボタン1 #define BT_2 3002 // ボタン2 #define BT_3 3003 // ボタン3 // カラー分離 #define RED(C) ( C & 0xFF) #define GREEN(C) ((C>>8) & 0xFF) #define BLUE(C) ((C>>16) & 0xFF) static HWND bt1, bt2, bt3; // 実行指定用ボタン static HWND editA, editB, editC;//変換用係数を指定するエディットボックス static HDC hbuf; static HBITMAP hBM;//ビットマップ描画用 // 立体表示用 Point org, v0;//原点、視点位置 TMatrix t, it;//変換マトリックス double dv;//Z方向にずらす量 double size_x, size_y;//表示画面サイズ double diffuse; //拡散反射係数 double specular;//鏡面反射係数 double ambient; //環境光 void clearBitmap(){//ビットマップクリア SelectObject(hbuf,GetStockObject(NULL_PEN)); PatBlt(hbuf,0,0,2000,1000,WHITENESS); } void setView(double a,double e, double d){ // 角度による方向設定 Point P1=setPoint(0,0,1); TMatrix PP=perspect(d), RX=rot_x(e-90), RZ=rot_z(-90-a); t=mlt(mlt(perspect(d),rot_x(e-90)),rot_z(-90-a)); v0=mlt(mlt(rot_z(90+a),rot_x(90-e)),mlt(P1,d)); } void setview(Point p){//視点位置による方向設定 Point P1=setPoint(0,0,1); dv=len(p); Point wa=unit(p); v0=p; if((wa.X==0) &&(wa.Y==0)){ t=perspect(dv);return;} double wd=sqrt(wa.X*wa.X+wa.Y*wa.Y); t=mlt(mlt(perspect(dv),rot_x(-wd,wa.Z)),rot_z(-wa.X/wd,-wa.Y/wd)); it=mlt(rot_z(wa.X/wd,-wa.Y/wd),rot_x(wd,wa.Z)); } Point screen(Point p){//スクリーン座標系への変換 Point a=mlt(t,p); double s=(t.mat[3][0]*p.X+t.mat[3][1]*p.Y+t.mat[3][2]*p.Z+t.mat[3][3]); return setPoint(org.X+a.X/s,org.Y-a.Y/s,a.Z); } Point world(Point p){ //View座標をWorld座標に変換 double sz=-p.Z/dv; return mlt(it,(setPoint((p.X-org.X)*sz,(-p.Y+org.Y)*sz,p.Z+dv))); } void init2D(int x, int y){//描画初期設定 size_x=x; size_y=y; org.X=size_x/2-0.5; org.Y=size_y/2-1.5; org.Z=0; setView(30,30,1000); } void origin(int x, int y){ org = setPoint(x+0.5F , y-0.5F,0); } //--------------------------------------------------------------------- //■Ray Tracing法による立体描画 // 以下の係数を用いる //  diffuse:拡散反射係数, specular: 鏡面反射係数, ambient: 環境光 // int shading(Point V, Point L, Point N, int CU){ double kd=diffuse, ks=specular, ke=ambient, D1, D2; Point RV=sub(L,mlt(2,mlt(mlt(L,N),N))); //反射方向ベクトル D1=(mlt(minus(N),L))/(len(N)*len(L)); if(D1<0)D1=0; // 拡散および環境光 D1=kd*D1+ke; D2=ks*(mlt(minus(RV),V))/(len(RV)*len(V)); if( D2 < 0)D2 = 0; int R=(int)(D1*(double)(RED (CU))+D2*255);if(R>255)R=255; int G=(int)(D1*(double)(GREEN(CU))+D2*255);if(G>255)G=255; int B=(int)(D1*(double)(BLUE (CU))+D2*255);if(B>255)B=255; return RGB(R,G,B); } int mix(int C1,double d1, int C2,double d2){// C1とC2をd1:d2で混ぜる int R=(int)(d1*(double)(RED (C1))+d2*(double)(RED (C2)));if(R>255)R=255; int G=(int)(d1*(double)(GREEN(C1))+d2*(double)(GREEN(C2)));if(G>255)G=255; int B=(int)(d1*(double)(BLUE (C1))+d2*(double)(BLUE (C2)));if(B>255)B=255; return RGB(R,G,B); } int shading(Point V, Point L, Point N, int CU, double s){ double kd=diffuse, ks=specular, ke=ambient, D1, D2; Point RV=sub(L,mlt(mlt(mlt(2,L),N),N)); //反射方向ベクトル D1=mlt(minus(N),L)/(len(N)*len(L));if(D1<0)D1=0;// 拡散および環境光 D1=kd*s*D1+ke; D2=s*ks*mlt(minus(RV),V)/(len(RV)*len(V)); if(D2<0)D2=0;// 反射 int R=(int)(D1*(double)(RED(CU) )+D2*255);if(R>255)R=255; int G=(int)(D1*(double)(GREEN(CU))+D2*255);if(G>255)G=255; int B=(int)(D1*(double)(BLUE(CU) )+D2*255);if(B>255)B=255; return RGB(R,G,B); } void drawPoint(double x,double y, int C){//点を描く SetPixel(hbuf,(int)(x+0.5), (int)(y+0.5),C); } void drawBall(){ init2D(500,400); origin(250,200);Point L0, V0; Ball Ba = setBall(setPoint(0,0,70),70); //球体の定義 L0 = setPoint(0,400,1000); //照明光 V0 = setPoint(500,500,500); //視点 setview(V0); for(int x=0;x