如何从像素中绘制3D对象?

时间:2016-01-06 22:34:54

标签: java 3d awt

我的程序有问题。我有ascii文件,列“theta y radius”~18万000行。我可以从中计算:x,y,z记录。我尝试在3D空间中绘制它,接下来我想要组合像素,结果应该是我可以用鼠标旋转的项目。我应该只使用java.awt。

我有类似的东西:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;

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

class Edge {
   public int a, b;
   public Edge( int A, int B ) {
      a = A;  b = B;
   }
}

public class WireframeViewer extends Applet
   implements MouseListener, MouseMotionListener {

   int width, height;
   int mx, my;  // the most recently recorded mouse coordinates

   Image backbuffer;
   Graphics backg;

   int azimuth = 35, elevation = 30;

   Point3D[] vertices;
   Edge[] edges;

   public void init() {
      width = getSize().width;
      height = getSize().height;

      vertices = new Point3D[ 8 ];
      vertices[0] = new Point3D( -1, -1, -1 );
      vertices[1] = new Point3D( -1, -1,  1 );
      vertices[2] = new Point3D( -1,  1, -1 );
      vertices[3] = new Point3D( -1,  1,  1 );
      vertices[4] = new Point3D(  1, -1, -1 );
      vertices[5] = new Point3D(  1, -1,  1 );
      vertices[6] = new Point3D(  1,  1, -1 );
      vertices[7] = new Point3D(  1,  1,  1 );

      edges = new Edge[ 12 ];
      edges[ 0] = new Edge( 0, 1 );
      edges[ 1] = new Edge( 0, 2 );
      edges[ 2] = new Edge( 0, 4 );
      edges[ 3] = new Edge( 1, 3 );
      edges[ 4] = new Edge( 1, 5 );
      edges[ 5] = new Edge( 2, 3 );
      edges[ 6] = new Edge( 2, 6 );
      edges[ 7] = new Edge( 3, 7 );
      edges[ 8] = new Edge( 4, 5 );
      edges[ 9] = new Edge( 4, 6 );
      edges[10] = new Edge( 5, 7 );
      edges[11] = new Edge( 6, 7 );

      backbuffer = createImage( width, height );
      backg = backbuffer.getGraphics();
      drawWireframe( backg );

      addMouseListener( this );
      addMouseMotionListener( this );
   }

   void drawWireframe( Graphics g ) {

      // compute coefficients for the projection
      double theta = Math.PI * azimuth / 180.0;
      double phi = Math.PI * elevation / 180.0;
      float cosT = (float)Math.cos( theta ), sinT = (float)Math.sin( theta );
      float cosP = (float)Math.cos( phi ), sinP = (float)Math.sin( phi );
      float cosTcosP = cosT*cosP, cosTsinP = cosT*sinP,
             sinTcosP = sinT*cosP, sinTsinP = sinT*sinP;

      // project vertices onto the 2D viewport
      Point[] points;
      points = new Point[ vertices.length ];
      int j;
      int scaleFactor = width/4;
      float near = 3;  // distance from eye to near plane
      float nearToObj = 1.5f;  // distance from near plane to center of object
      for ( j = 0; j < vertices.length; ++j ) {
         int x0 = vertices[j].x;
         int y0 = vertices[j].y;
         int z0 = vertices[j].z;

         // compute an orthographic projection
         float x1 = cosT*x0 + sinT*z0;
         float y1 = -sinTsinP*x0 + cosP*y0 + cosTsinP*z0;

         // now adjust things to get a perspective projection
         float z1 = cosTcosP*z0 - sinTcosP*x0 - sinP*y0;
         x1 = x1*near/(z1+near+nearToObj);
         y1 = y1*near/(z1+near+nearToObj);

         // the 0.5 is to round off when converting to int
         points[j] = new Point(
            (int)(width/2 + scaleFactor*x1 + 0.5),
            (int)(height/2 - scaleFactor*y1 + 0.5)
         );
      }

      // draw the wireframe
      g.setColor( Color.black );
      g.fillRect( 0, 0, width, height );
      g.setColor( Color.white );
      for ( j = 0; j < edges.length; ++j ) {
         g.drawLine(
            points[ edges[j].a ].x, points[ edges[j].a ].y,
            points[ edges[j].b ].x, points[ edges[j].b ].y
         );
      }
   }

   public void mouseEntered( MouseEvent e ) { }
   public void mouseExited( MouseEvent e ) { }
   public void mouseClicked( MouseEvent e ) { }
   public void mousePressed( MouseEvent e ) {
      mx = e.getX();
      my = e.getY();
      e.consume();
   }
   public void mouseReleased( MouseEvent e ) { }
   public void mouseMoved( MouseEvent e ) { }
   public void mouseDragged( MouseEvent e ) {
      // get the latest mouse position
      int new_mx = e.getX();
      int new_my = e.getY();

      // adjust angles according to the distance travelled by the mouse
      // since the last event
      azimuth -= new_mx - mx;
      elevation += new_my - my;

      // update the backbuffer
      drawWireframe( backg );

      // update our data
      mx = new_mx;
      my = new_my;

      repaint();
      e.consume();
   }

   public void update( Graphics g ) {
      g.drawImage( backbuffer, 0, 0, this );
      showStatus("Elev: "+elevation+" deg, Azim: "+azimuth+" deg");
   }

   public void paint( Graphics g ) {
      update( g );
   }
}

那个aplet还可以,但它显示正方形 - 我希望我的像素中应该有对象。

我可以计算&gt; 160 00顶点,当我在2D中绘画时,我可以看到一个男人头。问题是,我可以用边缘做什么?

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

更改...

public void update( Graphics g ) {
   g.drawImage( backbuffer, 0, 0, this );
   showStatus("Elev: "+elevation+" deg, Azim: "+azimuth+" deg");
}

public void paint( Graphics g ) {
   update( g );
}

为...

@Override
public void paint(Graphics g) {
    super.paint(g);
    g.drawImage(backbuffer, 0, 0, this);
    showStatus("Elev: " + elevation + " deg, Azim: " + azimuth + " deg");
}

它产生......

Cude

update实际上会调用paint,因此您可能会对绘画的工作方式感到不安。

答案 1 :(得分:0)

这不是您只想在java.awt中完成的事情。仅使用像素渲染3D涉及很多。

您必须计算用于将3D空间转换为2D的所有数学,计算旋转/平移/缩放以及考虑阴影(如果需要)。

您是否可以使用OpenGL来解决您的问题?

Java甚至还为OpenGL (see Java OpenGL)提供了绑定,允许您在AWT窗口上渲染3D图形。

如果您绝对必须实现自己的软件渲染管道,则需要首先了解投影矩阵和模型视图矩阵。然后,您需要实现自己版本的顶点着色器和片段着色器(或类似的东西)。

我发现这篇文章可能对数学有用:http://www.songho.ca/opengl/gl_projectionmatrix.html