1

I have problem with my program. I have ascii file with columns "theta y radius" ~ 180 000 lines. I can calculate from that: x,y,z records. I try to paint it in 3D space, next I want to combine the pixels and result should be project which I can rotate with my mouse. I should use only java.awt.

I have something like that:

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 );
   }
}

That aplet is okay but it's showing square - I want that there should be object from my pixels.

I can calculate > 160 00 vertices and when I'm painting it in 2D I can see a man head. The problem is, what I can do with edges?

Any suggestions?

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • What do you mean "do with edges"? Are you trying to draw the edges between pairs of 3d points? If so, can't you just work out the projected coordinates of the endpoints, and draw a line between them? – Andy Turner Jan 06 '16 at 22:40
  • Also, I'd suggest using OpenGL. – Andy Turner Jan 06 '16 at 22:41
  • I'm only thinking, in that code is all okay because we know how much edges we need. How about that idea: make 2 arraylist, first shoud be make profile of that guy from pixels and second should be rotate in with mouse @AndyTurner – Natalie Chawkins Jan 06 '16 at 22:45
  • @AndyTurner I don't how but I want paint all of pixeles and combine all of them to make a 3D head and it should be probably awt like in this aplet. – Natalie Chawkins Jan 06 '16 at 22:48
  • Make sure you dispose the Graphics object of your backing buffer when your done painting to it. Don't override update, just override paint – MadProgrammer Jan 06 '16 at 23:23
  • @MadProgrammer and if I would have these pixels in 3D space how can I impose file in which are situaded colors corresponding to the drawn points. – Natalie Chawkins Jan 07 '16 at 02:34
  • 1) Why code an applet? If it is due to the teacher specifying it, please refer them to [Why CS teachers should **stop** teaching Java applets](http://programmers.blogoverflow.com/2013/05/why-cs-teachers-should-stop-teaching-java-applets/). 2) Why use AWT? See [this answer](http://stackoverflow.com/questions/6255106/java-gui-listeners-without-awt/6255978#6255978) for many good reasons to abandon AWT using components in favor of Swing. – Andrew Thompson Jan 08 '16 at 21:12

2 Answers2

1

Change...

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 );
}

to...

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

And it produces...

Cude

update actually calls paint, so you're kind of screwing with the way painting works.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • thanks man.. I fixed it! But can you give me que how can I change it to my file without edges? In square I know how many edges it has but in my object with 160 000 vertices I don't have any idea... – Natalie Chawkins Jan 07 '16 at 07:56
  • Well, my 3D's a little rusty, but a vertice is just a point in 3D space, the edge been a connection between two vertices, so you need to know how each vertice connects. Of course, rather than using `drawLine`, you could draw small "dots" (maybe a rectangle of 1x1 size) which could represent a "cloud" of vericies – MadProgrammer Jan 07 '16 at 07:59
  • I think it is important. My file is sorting by first column (theta) and next is second column (y), when e.g. theta 0.00 is endind (0.12 is starting) the same is with "y"! Last column is "free" in sorting. I heard that is making a grid but I don't know how I can use it. In my opinion it can be key in connection.. but I'm only thinking. – Natalie Chawkins Jan 07 '16 at 08:06
  • Mad, look at this please: http://pastebin.com/3HAQmQ53 // It is e.g. from ~center of my file. – Natalie Chawkins Jan 07 '16 at 08:28
0

This is not something you will want to do solely in java.awt. There is a lot involved with rendering 3D using only pixels.

You'll have to compute all of the mathematics for converting 3D space to 2D, account for rotation/translation/scaling and account for shading (if required).

Are you able to use OpenGL to solve your issue?

Java even has bindings for OpenGL (see Java OpenGL) that allow you to render 3D graphics on an AWT window.

If you absolutely must implement your own software rendering pipeline, you'll need to start by learning about projection matrices and modelview matrices. Then you will need to implement your own version of a vertex shader and fragment shader (or something of the sort).

I found this article which may be helpful in the mathematics: http://www.songho.ca/opengl/gl_projectionmatrix.html

Nicholas Miller
  • 4,205
  • 2
  • 39
  • 62