2012-05-11 13 views
1

私は可視性と一定のシェーディングを持つプラトン固体を描くものをやっています。私はOpenGLまたはdirectXなしでそれをしなければならない。私は今可視性を解決しています。私はおそらく画家alghoritmによって解決することができますが、私は自分のコードでそれを実装する方法を知らない。私はそれを描く方法があります。 私は自分のコードでpainters alghoritmを実装する方法をアドバイスしています。私はすでにこのalghoritm - teoreticalyについて何か知っています。そして、おそらくz座標で面を並べ替えるだけで十分でしょう。投影用プラトン固体の視認性

enter image description here
Iクラス射影行列を使用し、私は、OpenGLのように配列vertexBufferとindexBufferを有します。
私はC#のVisual studio 2010ですべてを行います。

ProjectionMatrix

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace KPG3D 
{ 
    /// <summary> 
    /// Structure of 3D point 
    /// </summary> 
    public struct Point3D 
    { 
     public float X; 
     public float Y; 
     public float Z; 

     public Point3D(float x, float y, float z) 
     { 
      X = x; 
      Y = y; 
      Z = z; 
     } 
    } 

    public class ProjectionMatrix 
    { 
     public float[,] projectionMatrix = new float[4, 4]; //projection matrix 

     /// <summary> 
     /// Konstructor of projection matrix 
     /// </summary> 
     public ProjectionMatrix() 
     { 
      setIdentity(); 
     } 

     /// <summary> 
     /// Konstructor of projection matrix 
     /// </summary> 
     public ProjectionMatrix(float zNear, float zFar, float viewportWidth, float viewportHeight) 
     { 
      setIdentity(); 
      float Q = zFar/(zFar - zNear); 
      float w = 2 * zNear/viewportWidth; 
      float h = 2 * zNear/viewportHeight; 

      projectionMatrix[0, 0] = w; 
      projectionMatrix[1, 1] = h; 
      projectionMatrix[2, 2] = Q; 
      projectionMatrix[3, 2] = 1; 
      projectionMatrix[2, 3] = -Q * zNear; 
     } 

     /// <summary> 
     /// Konstructor of projection matrix 
     /// </summary> 
     public ProjectionMatrix(float d, float z) 
     { 
      setIdentity();//set identity matrix 

      projectionMatrix[0, 0] = d/(d - z); 
      projectionMatrix[1, 1] = d/(d - z); 
      projectionMatrix[2, 2] = 0; 
     } 

     /// <summary> 
     /// Set the matrix to identity 
     /// </summary> 
     public void setIdentity() 
     { 
      projectionMatrix[0, 0] = 1; 
      projectionMatrix[0, 1] = 0; 
      projectionMatrix[0, 2] = 0; 
      projectionMatrix[0, 3] = 0; 

      projectionMatrix[1, 0] = 0; 
      projectionMatrix[1, 1] = 1; 
      projectionMatrix[1, 2] = 0; 
      projectionMatrix[1, 3] = 0; 

      projectionMatrix[2, 0] = 0; 
      projectionMatrix[2, 1] = 0; 
      projectionMatrix[2, 2] = 1; 
      projectionMatrix[2, 3] = 0; 

      projectionMatrix[3, 0] = 0; 
      projectionMatrix[3, 1] = 0; 
      projectionMatrix[3, 2] = 0; 
      projectionMatrix[3, 3] = 1; 
     } 

     /// <summary> 
     /// Aplicate projection on set point 
     /// </summary> 
     /// <param name="p">Point want to transformate</param> 
     /// <returns>Transformated point</returns> 
     public Point3D multiply(Point3D p) 
     { 
      Point3D result; 

      float tmp = projectionMatrix[3, 0] * p.X + projectionMatrix[3, 1] * p.Y + projectionMatrix[3, 2] * p.Z + projectionMatrix[3, 3] * 1; 

      result.X = (projectionMatrix[0, 0] * p.X + projectionMatrix[0, 1] * p.Y + projectionMatrix[0, 2] * p.Z + projectionMatrix[0, 3] * 1)/tmp; 
      result.Y = (projectionMatrix[1, 0] * p.X + projectionMatrix[1, 1] * p.Y + projectionMatrix[1, 2] * p.Z + projectionMatrix[1, 3] * 1)/tmp; 
      result.Z = (projectionMatrix[2, 0] * p.X + projectionMatrix[2, 1] * p.Y + projectionMatrix[2, 2] * p.Z + projectionMatrix[2, 3] * 1)/tmp; 


      return result; 
     } 
    } 
} 

ます(画像参照)を三角形に交差を考慮する必要がある場合

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 KPG3D 
{ 
    public partial class Form1 : Form 
    { 
     private Bitmap canvasBitmap; //bitmap of drawing area 
     private Graphics g;   //access to graffics 

     private List<Point3D> vertexBuffer = new List<Point3D>(); //list of all vertices 
     private List<int> indexBuffer = new List<int>();//list of all indices 
     private Point3D centroid = new Point3D(0, 0, 0);// center of object 

     private ProjectionMatrix projection = null; //projection matrix 

     private bool rotation = false; 
     private int objectID = 0; 

     public Form1() 
     { 
      InitializeComponent(); 

      //create bitmap and set to canvas 
      canvasBitmap = new Bitmap(canvas.Width, canvas.Height); 
      canvas.Image = canvasBitmap; 

      //prepare grafics 
      g = Graphics.FromImage(canvasBitmap); 
      g.SmoothingMode = SmoothingMode.AntiAlias; 


      Matrix origin = new Matrix(); 
      origin.Translate(canvas.Width/2, canvas.Height/2); 
      g.Transform = origin; 
     } 

     /// <summary> 
     /// Reaction on click on start button 
     /// </summary> 
     private void buttonStart_Click(object sender, EventArgs e) 
     { 
      if (projection == null) 
      { 
       projection = new ProjectionMatrix(1, 100, 1, 1); 
       //createBox(); 
       //createTetrahedron(); 
       createChosenObject(); 
      } 

      Timer t = new Timer(); 
      t.Tick += new EventHandler(timerDrawing);//set tick method 
      t.Interval = 30; //every 30 ms 
      t.Enabled = true; 
      t.Start(); 
     } 


     /// <summary> 
     /// Create tetrahedron 
     /// </summary> 
     private void createTetrahedron() 
     { 



      Point3D a = new Point3D(-3,-3, 7);//h 
      Point3D b = new Point3D(3,-3,13);//c 
      Point3D c = new Point3D(3, 3, 7);//a 
      Point3D d = new Point3D(-3, 3,13);//f 

      vertexBuffer.Add(a); 
      vertexBuffer.Add(b); 
      vertexBuffer.Add(c); 
      vertexBuffer.Add(d); 

      //acb 
      indexBuffer.Add(0); 
      indexBuffer.Add(2); 
      indexBuffer.Add(1); 

      //adc 
      indexBuffer.Add(0); 
      indexBuffer.Add(3); 
      indexBuffer.Add(2); 

      //cdb 
      indexBuffer.Add(2); 
      indexBuffer.Add(3); 
      indexBuffer.Add(1); 

      //adb 
      indexBuffer.Add(0); 
      indexBuffer.Add(3); 
      indexBuffer.Add(1); 

      centroid = new Point3D(0, 0, 10); 
     } 


     /// <summary> 
     /// Create chosen object 
     /// </summary> 
     private void createChosenObject() { 
      switch (objectID) { 
       case 1: 
        createTetrahedron(); 
        break; 
       case 2: 
        createHexahedron(); 
        break; 
       case 3: 
        createOctahedron(); 
        break; 
       case 4: 
        createDodecahedron(); 
        break; 
       case 5: 
        createIcosahedron(); 
        break; 
       default: 
        //do nothing 
        break; 
      } 

     } 




     /// <summary> 
     /// Rotate direcion vector by the specified angle 
     /// </summary> 
     /// <param name="vector">Direction vector</param> 
     /// <param name="angle">Angle of rotation</param> 
     /// <returns></returns> 
     private Point3D rotateVector(Point3D vector, Point3D centroid, double angle) 
     { 
      vector.X -= centroid.X; 
      vector.Y -= centroid.Y; 
      vector.Z -= centroid.Z; 

      Point3D result; 
      result.X = vector.X * (float)Math.Cos(angle) - vector.Z * (float)Math.Sin(angle); 
      result.Z = vector.X * (float)Math.Sin(angle) + vector.Z * (float)Math.Cos(angle); 
      result.Y = vector.Y; 

      result.X += centroid.X; 
      result.Y += centroid.Y; 
      result.Z += centroid.Z; 

      return result; 
     } 




     /// <summary> 
     /// Reaction on timer 
     /// </summary> 
     private void timerDrawing(Object obj, EventArgs ea) 
     { 

      //rotation of object 
      if (rotation == true) 
      { 
       for (int i = 0; i < vertexBuffer.Count; i++) 
       { 
        vertexBuffer[i] = rotateVector(vertexBuffer[i], centroid, 0.02); 
       } 
      } 

      //drawing of object 
      draw(vertexBuffer, indexBuffer); 


      //refresh what is on canvas 
      canvas.Invalidate(); 
     } 

     /// <summary> 
     ///Draw point and triangles 
     /// </summary> 
     /// <param name="vert"></param> 
     /// <param name="ind"></param> 
     private void draw(List<Point3D> vert, List<int> ind) 
     { 
      //clear drawing area 
      g.Clear(Color.Maroon); 

      //prepare pen and brush 
      Pen pen = new Pen(Color.Black, 1); 
      SolidBrush brush = new SolidBrush(Color.Black); 
      SolidBrush faceBrush = new SolidBrush(Color.FromArgb(75, Color.Green)); 

      //draw edges 
      for (int i = 0; i < ind.Count/3; i++) 
      { 
       Point3D A = projection.multiply(vert[ind[3 * i + 0]]); 
       Point3D B = projection.multiply(vert[ind[3 * i + 1]]); 
       Point3D C = projection.multiply(vert[ind[3 * i + 2]]); 

       //count to 2D 
       PointF a = new PointF(A.X * 200, -A.Y * 200); 
       PointF b = new PointF(B.X * 200, -B.Y * 200); 
       PointF c = new PointF(C.X * 200, -C.Y * 200); 

       g.FillPolygon(faceBrush, new PointF[] { a, b, c }); 

       //draw triangle 
       g.DrawLine(pen, a, b); 
       g.DrawLine(pen, b, c); 
       g.DrawLine(pen, c, a); 
      } 

      //draw element 
      for (int i = 0; i < vert.Count; i++) 
      { 



       Point3D p = projection.multiply(vert[i]); //projection from 3D to 2D 
       g.FillRectangle(brush, p.X * 200 - 2, -p.Y * 200 - 2, 4, 4); 


      } 

     } 



     /// <summary> 
     /// Printscreen to file 
     /// </summary> 
     private void buttonPrintScreen_Click(object sender, EventArgs e) 
     { 
      canvas.Image.Save("out.png"); 
     } 

     private void checkBoxRotate_CheckedChanged(object sender, EventArgs e) 
     { 
      if (checkBoxRotate.Checked) rotation = true; 
      else rotation = false; 
     } 



     private void objectChooser_SelectedIndexChanged(object sender, EventArgs e) 
     { 
      //set ide of chosen object 
      if(objectChooser.SelectedItem.Equals("Tetrahedron")) objectID = 1; 
      else if (objectChooser.SelectedItem.Equals("Box")) objectID = 2; 
      else if (objectChooser.SelectedItem.Equals("Octahedron")) objectID = 3; 
      else if(objectChooser.SelectedItem.Equals("Dodecahedron")) objectID = 4; 
      else if (objectChooser.SelectedItem.Equals("Icosahedron")) objectID = 5; 
     } 


    } 
} 
+0

どのようなアドバイスが必要ですか?ペインターのアルゴリズムはかなり簡単です。 zソートを使用するあなたのアイデアは素晴らしい最初のステップのように聞こえる。 Zバッファを実装することは許可されていますか? – RustyTheBoyRobot

+0

あなたが意味することは、Zバッファを実装することに依存します。既に実装されているZ-bufferやGPUのいくつかのソリューションを使用することはできません - 私はそれが属するものを正確には知りませんが、他のアプリケーションでOpenGlで使用しました。 – user1097772

答えて

0

フォームは、私は(最も簡単な解決策は、zバッファを必要とするだろうと思います彼らはかなり簡単に作成して使用することができます)。交差する三角形をレンダリングする必要がない場合、zソートの提案されたソリューションはより簡単になり、うまく動作します。

enter image description here

関連する問題