// ■レイトレーシング法による物体の描画 // @ button1〜button3を配置して、TextプロパティとClickイベントを次のように設定する。 // // button名    Text   Clickイベント // -------------------------------------------- // button1 球体       button1_Click // button2 球体と床     button2_Click // button3 映込みのある球体 button3_Click // // A label1〜label3, textBox1〜textBox3を配置してプロパティを次のように設定する。 // // label名  Text   textBox名 Text TextAlign // ---------------------------------------------------------- // label1 拡散反射係数   textBox1 0.7 Right // label2 鏡面反射係数   textBox2 0.2 Right // label3 環境光係数   textBox3 0.3 Right // // 【手法の概要】 // 視点を中心に、2次元方向内の微小な角度(画角)ごとのそれぞれの方向から // 受け取る光線に対して算術演算を行うことによって、光線を逆方向に追跡し、 // その方向に見える光を判定することで描画を行う。 // using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace rayTracing2 { public partial class Form1 : Form { public const int XMAX = 500, YMAX = 400; private Image image = new Bitmap(XMAX, YMAX); private Point org = new Point(); private TMatrix t, it; private Point v0; private float dv; private float size_x; private float size_y; private float[,] z_buff = new float[XMAX, YMAX]; double 拡散反射係数, 鏡面反射係数, 環境光係数; public Form1() { InitializeComponent(); InitializeComponent(); SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); Graphics g = Graphics.FromImage(image); Brush brush = new SolidBrush(Color.White); g.FillRectangle(brush, 0, 0, image.Width, image.Height); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.DrawImage(image, 0, 0); } public float len(Point a){ return (float)Math.Sqrt(a.X*a.X+a.Y*a.Y+a.Z*a.Z);} public Point unit(Point a){ return (len(a)==0)?new Point(1,0,0):a/len(a);} public Point unit(float a, float e) { double PIR=Math.PI/180; double aa=a*PIR; double ee=e*PIR; float X=(float)(Math.Cos(aa)*Math.Cos(ee)); float Y=(float)(Math.Sin(aa)*Math.Cos(ee)); float Z=(float)(Math.Sin(ee)); return new Point(X,Y,Z); } public Point unit(float a) { double PIR=Math.PI/180; double aa=a*PIR; float X=(float)Math.Cos(aa); float Y=(float)Math.Sin(aa); float Z=0; return new Point(X,Y,Z); } public static TMatrix scale(float scale_x, float scale_y, float scale_z) { TMatrix m=new TMatrix(); m.t[0,0]=scale_x; m.t[1,1]=scale_y; m.t[2,2]=scale_z; return m; } //public static TMatrix scale(Point P){ return scale(P.X, P.Y, P.Z);} //public static TMatrix scale(float S){ return scale(S, S, S);} public TMatrix rot_x(float sn, float cs) //X軸を中心に回転 { TMatrix m=new TMatrix(); m.t[1,1]=cs; m.t[1,2]=-sn; m.t[2,1]=sn; m.t[2,2]=cs; return m; } public TMatrix rot_y(float sn, float cs) //Y軸を中心に回転 { TMatrix m=new TMatrix(); m.t[0,0]=cs; m.t[0,2]=sn; m.t[2,0]=-sn; m.t[2,2]=cs; return m; } public TMatrix rot_z(float sn, float cs) //Z軸を中心に回転 { TMatrix m=new TMatrix(); m.t[0,0]=cs; m.t[0,1]=-sn; m.t[1,0]=sn; m.t[1,1]=cs; return m; } public TMatrix rot_x(float r) //X軸を中心に回転 { double PIR=Math.PI/180; return rot_x((float)Math.Sin(r*PIR),(float)Math.Cos(r*PIR)); } public TMatrix rot_y(float r) //Y軸を中心に回転 { double PIR=Math.PI/180; return rot_y((float)Math.Sin(r*PIR),(float)Math.Cos(r*PIR)); } public TMatrix rot_z(float r) //Z軸を中心に回転 { double PIR=Math.PI/180; return rot_z((float)Math.Sin(r*PIR),(float)Math.Cos(r*PIR)); } public TMatrix rotate(Point a, float sn, float cs) //回転変換 { Point P=new Point(a.X, a.Y,0); Point axy=unit(P); Point axz=rot_z(-axy.Y,axy.X)*unit(a); return rot_z(axy.Y, axy.X)*rot_y(-axz.Z,axz.X)*rot_x(sn,cs) *rot_y(axz.Z,axz.X)*rot_z(-axy.Y, axy.X); } public TMatrix rotate(float r) { return rot_z(r);} public TMatrix rotate(Point a, float r) { double PIR=Math.PI/180; return rotate(a,(float)Math.Sin(r*PIR),(float)Math.Cos(r*PIR)); } public TMatrix rotate(Point a, Point b) { float sn=len(unit(a) % unit(b)); if(sn !=0) return rotate(unit(a%b),sn, unit(a)*unit(b)); return new TMatrix(); } public TMatrix rotate(Point n) //ベクトル方向に回転 { Point P = new Point(1,0,0); Point ss = P%unit(n); if(len(ss)==0) ss= new Point(0,0,1); Point s = unit(ss); TMatrix t1 = rot_x(-s.Y,s.Z); TMatrix t3 = rot_x(s.Y,s.Z); Point m = unit(t1*n); TMatrix t2 = rot_z(m.Y, m.X); return t3*t2*t1; } public TMatrix move(float x, float y, float z) { TMatrix m=new TMatrix(); m.t[0,3]=x; m.t[1,3]=y; m.t[2,3]=z; return m; } public TMatrix move(Point P) { return move(P.X, P.Y, P.Z); } public TMatrix perspect(float d) { TMatrix m=new TMatrix(); m.t[2,3]=-d; m.t[3,2]=-1/d; return m; } public TMatrix trans(TMatrix a) { TMatrix c=new TMatrix(); for(int i=0; i<4; i++) for(int j=0; j<4; j++) c.t[i,j]=a.t[j,i]; return c; } public TMatrix inverse(TMatrix a) { float d=0; for(int i=0; i<3; i++) d = d + a.t[0,i]*a.t[1, (i+1)%3]*a.t[2, (i+2) % 3] - a.t[0,i]*a.t[1, (i+2)%3]*a.t[2, (i+1) % 3]; TMatrix b=new TMatrix(); if(d != 0) for(int i=0; i<3; i++) for(int j=0; j<3; j++) b.t[i,j]=(a.t[(j+1)%3,(i+1)%3]*a.t[(j+2)%3, (i+2)%3] -a.t[(j+1)%3,(i+2)%3]*a.t[(j+2)%3, (i+1)%3])/d; for(int i=0; i<3; i++) b.t[i,3]=-a.t[i,3]; return b; } private Surface revolve_z(Line a, int n,float b, float e)//z軸回転によるポリゴンモデル作成 { Surface f=new Surface((a.n-1)*n); TMatrix m0,m1; for(int j=0,t=0;j0.1) { f[0] =move(b.p[0]) *rot_xz(b.p[1]-b.p[0]) *a; f[b.n-1]=move(b.p[b.n-1])*rot_xz(b.p[b.n-1]-b.p[b.n-2])*a; } else { f[0] =move(b.p[0])*rot_xz(b.p[1]-b.p[b.n-4])*a; f[b.n-1]=move(b.p[0])*rot_xz(b.p[3]-b.p[b.n-2])*a; } for(int i=1;i255)R=255; int G=(int)(D1*(double)(CU.G)+D2*255);if(G>255)G=255; int B=(int)(D1*(double)(CU.B)+D2*255);if(B>255)B=255; return Color.FromArgb(R,G,B); } private Color mix(Color C1,double d1,Color C2,double d2) { int R=(int)(d1*(double)(C1.R)+d2*(double)(C2.R));if(R>255)R=255; int G=(int)(d1*(double)(C1.G)+d2*(double)(C2.G));if(G>255)G=255; int B=(int)(d1*(double)(C1.B)+d2*(double)(C2.B));if(B>255)B=255; return Color.FromArgb(R,G,B); } private Color shading(Point V, Point L, Point N, Color CU, double s) { double kd=拡散反射係数, ks=鏡面反射係数, ke=環境光係数; Point RV=L-2*(L*N)*N; //反射方向ベクトル double D1=(-N*L)/(len(N)*len(L));  // 拡散および環境光 if(D1<0)D1=0; D1=kd*s*D1+ke;  double D2=s*ks*((-RV*V))/(len(RV)*len(V));    // 反射 if(D2<0)D2=0; int R=(int)(D1*(double)(CU.R)+D2*255);if(R>255)R=255; int G=(int)(D1*(double)(CU.G)+D2*255);if(G>255)G=255; int B=(int)(D1*(double)(CU.B)+D2*255);if(B>255)B=255; return Color.FromArgb(R,G,B); } private Point 補間(Point p1,Point p2,int a1,int a2)//p1,p2を補間 { return ((a1+a2<1) ?p1: ((a2)*p1+a1*p2)/(a1+a2)); } private Color 色補間(Color c1,Color c2,int a1,int a2)//p1,p2を補間 { int aa=a1+a2; float b1=(float)a1, b2=(float)a2; if(aa<1) return c1; float R1=(float)c1.R, G1=(float)c1.G, B1=(float)c1.B; float R2=(float)c2.R, G2=(float)c2.G, B2=(float)c2.B; return Color.FromArgb((int)((b2*R1+b1*R2)/aa),(int)((b2*G1+b1*G2)/aa),(int)((b2*B1+b1*B2)/aa)); } private void 球体() { init2D(500,400); origin(250,200); Ball Ba = new Ball(new Point(0,0,70),70); //球体の定義 Point L0 = new Point(0,400,1000); //照明光 Point V0 = new Point(500,500,500); //視点       setview(V0); for(int x=0;x0) p=new Point[n];} public Line(Point P0, Point P1) { n=2; p=new Point[n]; p[0]=P0; p[1]=P1;} public Line(Point P0, Point P1, Point P2){ n=3; p=new Point[n]; p[0]=P0; p[1]=P1; p[2]=P2;} public Line(Point P0,Point P1,Point P2,Point P3) { n=4; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;} public Line(Point P0,Point P1,Point P2,Point P3, Point P4) { n=5; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;} public Line(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5) { n=6; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;} public Line(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6) { n=7; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;} public Line(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6,Point P7) { n=8; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P7;} public Line(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6,Point P7,Point P8) { n=9; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P7;p[8]=P8;} public Line(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6,Point P7,Point P8,Point P9) { n=10;p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P7;p[8]=P8;p[9]=P9;} public Line(Line b){ n=b.n;if(n>0) p=new Point[n];for(int i=0;i0) p=new Point[n];} public Polygon(Point P0, Point P1){ n=3; p=new Point[n]; p[0]=P0; p[1]=P1; p[2]=P0;} public Polygon(Point P0, Point P1, Point P2){ n=4; p=new Point[n]; p[0]=P0; p[1]=P1; p[2]=P2;p[3]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3) { n=5; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3, Point P4) { n=6; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5) { n=7; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6) { n=8; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6,Point P7) { n=9; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P7;p[8]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6,Point P7,Point P8) { n=10; p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P7;p[8]=P8;p[9]=P0;} public Polygon(Point P0,Point P1,Point P2,Point P3,Point P4,Point P5,Point P6,Point P7,Point P8,Point P9) { n=11;p=new Point[n];p[0]=P0;p[1]=P1;p[2]=P2;p[3]=P3;p[4]=P4;p[5]=P5;p[6]=P6;p[7]=P7;p[8]=P8;p[9]=P9;p[10]=P0;} public Polygon(Point[] a,int 頂点数){ n=頂点数+1;if(n>0) p=new Point[n];for(int i=0;i0){ p=new Point[n];for(int i=0;i0) { p=new Point[n];for(int i=0;i0) p=new Point[n];for(int i=0;i0) p=new Polygon[n];} public Surface(Polygon a) {n=1; p=new Polygon[n];p[0]=a;} public Surface(Surface a) {n=a.n;if (n>0) p=new Polygon[n];for(int i=0;i