// ■3Dモデル5手法の比較 // @ボタンbutton1, 2, 3, 4, 5を割り付け、それぞれ次のように設定する。 // // コントロール名  Text       イベント // --------------------------------------------------- //   button1   ワイヤフレーム button1_Click //   button2   法線ベクトル法1 button2_Click //   button3   法線ベクトル法1 button3_Click //   button4   塗り重ね法    button4_Click //   button5   Zバッファ法 button5_Click // // AチェックボックスcheckBox1を割り付け、Textを「補助線あり」に設定する。 // BForm1のText自由では構いませんが本例では「3Dモデル5手法の比較」とした。 // // (注) 数値確認用にデバッグ用表示をコメントにして残していますので、 // 疑問が生じたら、適宜コメントを外してご利用ください。 // using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; // これを指定する namespace FigModel3D { public partial class Form1 : Form { private Image image; 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[500,400]; public Form1() { InitializeComponent(); SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); image = new Bitmap(500, 400); 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;i1) D=1; int X=(int)(D*255); Color C=Color.FromArgb(X,X,X); paintPolygon(p,C); this.Invalidate(); //debugPoint("p.p[0]",p.p[0]); //debugPoint("L0",L0); //debugPoint("L",L); //debugPoint("N",N); //MessageBox.Show(" D=" +D.ToString()+" X=" +X); } } if(checkBox1.Checked) { drawAxis(); drawLine(100*b, Color.Red); drawLine(100*c, Color.Red); } this.Invalidate(); } private void 塗り重ね法() { init2D(500,400); origin(250,200); Point V0= new Point(500,500,500); //視点 Point L0= new Point(0,500,1000); //照明光 setview(V0); drawAxis(); Line a,b; Surface f; a=circle_xz(18);               //トーラスの原型(円) b=circle_xy(36); //円形(補助線用) f=revolve_z(move(100,0,0)*50*a,36); int NN=f.n; float[] d=new float[f.n]; int[] s=new int[f.n]; //視点とポリゴンの距離計算 for(int j=0; j1) D=1; int X=(int)(D*255); Color C=Color.FromArgb(X,X,X); paintPolygon(p,C); } if(checkBox1.Checked) { drawAxis(); drawLine(move(100,0,0)*50*a, Color.Red); drawLine(150*b, Color.Red); } this.Invalidate(); } private void Zバッファ描画(Polygon a,Point L0, Color CU) { //screen 座標変換 Point[] pp=new Point[a.n]; for(int i=0; i1) D=1; int R=(int)(D*(double)(CU.R)); int G=(int)(D*(double)(CU.G)); int B=(int)(D*(double)(CU.B)); Color C=Color.FromArgb(R,G,B); // screen座標範囲の設定 int y_max=(int)pp[0].Y, y_min=(int)pp[0].Y; int s0=0, s1=0, n=a.n-1; for(int i=0;i(int)pp[i].Y){y_min=(int)pp[i].Y;s0=s1=i;} else if(y_min==(int)pp[i].Y) s1=i; if(y_max0) 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