Draw a rotating 3D cube.

origin
Joshua Sigona 3 years ago
parent 0bb1e490c3
commit 9e324be3e2
  1. 23
      src/sig/Matrix.java
  2. 11
      src/sig/Mesh.java
  3. 56
      src/sig/Panel.java
  4. 64
      src/sig/SigRenderer.java
  5. 4
      src/sig/Triangle.java
  6. 68
      src/sig/utils/DrawUtils.java

@ -0,0 +1,23 @@
package sig;
import javax.vecmath.Vector3f;
public class Matrix {
float[][] m = new float[4][4];
Matrix(float[][]m) {
this.m=m;
}
public static void MultiplyMatrixVector(Vector3f i,Vector3f o,Matrix m) {
o.x=i.x*m.m[0][0]+i.y*m.m[1][0]+i.z*m.m[2][0]+m.m[3][0];
o.y=i.x*m.m[0][1]+i.y*m.m[1][1]+i.z*m.m[2][1]+m.m[3][1];
o.z=i.x*m.m[0][2]+i.y*m.m[1][2]+i.z*m.m[2][2]+m.m[3][2];
float w=i.x*m.m[0][3]+i.y*m.m[1][3]+i.z*m.m[2][3]+m.m[3][3];
if (w!=0f) {
o.x/=w;
o.y/=w;
o.z/=w;
}
}
}

@ -0,0 +1,11 @@
package sig;
import java.util.ArrayList;
import java.util.List;
public class Mesh {
List<Triangle> triangles = new ArrayList<>();
Mesh(List<Triangle> tris) {
this.triangles=tris;
}
}

@ -2,6 +2,8 @@ package sig;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.vecmath.Vector3f; import javax.vecmath.Vector3f;
import sig.utils.DrawUtils;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Color; import java.awt.Color;
@ -22,6 +24,7 @@ public class Panel extends JPanel implements Runnable {
private MemoryImageSource mImageProducer; private MemoryImageSource mImageProducer;
private ColorModel cm; private ColorModel cm;
private Thread thread; private Thread thread;
float fTheta=0f;
public Panel() { public Panel() {
super(true); super(true);
@ -46,6 +49,8 @@ public class Panel extends JPanel implements Runnable {
cm = getCompatibleColorModel(); cm = getCompatibleColorModel();
width = getWidth(); width = getWidth();
height = getHeight(); height = getHeight();
SigRenderer.SCREEN_WIDTH=getWidth();
SigRenderer.SCREEN_HEIGHT=getHeight();
int screenSize = width * height; int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){ if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize]; pixel = new int[screenSize];
@ -64,6 +69,7 @@ public class Panel extends JPanel implements Runnable {
*/ */
public /* abstract */ void render(){ public /* abstract */ void render(){
int[] p = pixel; // this avoid crash when resizing int[] p = pixel; // this avoid crash when resizing
//a=h/w
final int h=SigRenderer.SCREEN_HEIGHT; final int h=SigRenderer.SCREEN_HEIGHT;
if(p.length != width * height) return; if(p.length != width * height) return;
@ -75,6 +81,56 @@ public class Panel extends JPanel implements Runnable {
} }
} }
} }
Matrix matRotZ = new Matrix(new float[][]{
{(float)Math.cos(fTheta),(float)Math.sin(fTheta),0,0,},
{(float)-Math.sin(fTheta),(float)Math.cos(fTheta),0,0,},
{0,0,1,0,},
{0,0,0,1,},
}),matRotX = new Matrix(new float[][]{
{1,0,0,0,},
{0,(float)Math.cos(fTheta*0.5f),(float)Math.sin(fTheta*0.5f),0,},
{0,(float)-Math.sin(fTheta*0.5f),(float)Math.cos(fTheta*0.5f),0,},
{0,0,0,1,},
});
fTheta+=0.01f;
for (Triangle t : SigRenderer.cube.triangles) {
Triangle triProjected = new Triangle(new Vector3f(),new Vector3f(),new Vector3f()),triTranslated=new Triangle(new Vector3f(),new Vector3f(),new Vector3f()),triRotatedZ=new Triangle(new Vector3f(),new Vector3f(),new Vector3f()),triRotatedZX=new Triangle(new Vector3f(),new Vector3f(),new Vector3f());
Matrix.MultiplyMatrixVector(t.A, triRotatedZ.A, matRotZ);
Matrix.MultiplyMatrixVector(t.B, triRotatedZ.B, matRotZ);
Matrix.MultiplyMatrixVector(t.C, triRotatedZ.C, matRotZ);
Matrix.MultiplyMatrixVector(triRotatedZ.A, triRotatedZX.A, matRotX);
Matrix.MultiplyMatrixVector(triRotatedZ.B, triRotatedZX.B, matRotX);
Matrix.MultiplyMatrixVector(triRotatedZ.C, triRotatedZX.C, matRotX);
triTranslated = (Triangle)triRotatedZX.clone();
triTranslated.A.z=triRotatedZX.A.z+3f;
triTranslated.B.z=triRotatedZX.B.z+3f;
triTranslated.C.z=triRotatedZX.C.z+3f;
Matrix.MultiplyMatrixVector(triTranslated.A, triProjected.A, SigRenderer.matProj);
Matrix.MultiplyMatrixVector(triTranslated.B, triProjected.B, SigRenderer.matProj);
Matrix.MultiplyMatrixVector(triTranslated.C, triProjected.C, SigRenderer.matProj);
triProjected.A.x+=1f;
triProjected.A.y+=1f;
triProjected.B.x+=1f;
triProjected.B.y+=1f;
triProjected.C.x+=1f;
triProjected.C.y+=1f;
triProjected.A.x*=0.5f*SigRenderer.SCREEN_WIDTH;
triProjected.A.y*=0.5f*SigRenderer.SCREEN_HEIGHT;
triProjected.B.x*=0.5f*SigRenderer.SCREEN_WIDTH;
triProjected.B.y*=0.5f*SigRenderer.SCREEN_HEIGHT;
triProjected.C.x*=0.5f*SigRenderer.SCREEN_WIDTH;
triProjected.C.y*=0.5f*SigRenderer.SCREEN_HEIGHT;
DrawUtils.DrawTriangle(p,(int)triProjected.A.x,(int)triProjected.A.y,(int)triProjected.B.x,(int)triProjected.B.y,(int)triProjected.C.x,(int)triProjected.C.y,Color.BLACK);
}
i += 1; i += 1;
j += 1; j += 1;
endTime=System.nanoTime(); endTime=System.nanoTime();

@ -1,5 +1,6 @@
package sig; package sig;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.vecmath.Matrix4f;
import javax.vecmath.Point2d; import javax.vecmath.Point2d;
import javax.vecmath.Tuple3d; import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3f; import javax.vecmath.Vector3f;
@ -9,14 +10,17 @@ import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.KeyListener; import java.awt.event.KeyListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension;
import java.awt.BorderLayout;
public class SigRenderer implements KeyListener,MouseListener,MouseMotionListener{ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListener{
public static Triangle tri,tri2,tri3,tri4,tri5,tri6; public static Mesh cube;
public final static int SCREEN_WIDTH=1280; public static int SCREEN_WIDTH=1280;
public final static int SCREEN_HEIGHT=720; public static int SCREEN_HEIGHT=720;
public final static long TIMEPERTICK = 16666667l; public final static long TIMEPERTICK = 16666667l;
public static float DRAWTIME=0; public static float DRAWTIME=0;
public static float DRAWLOOPTIME=0; public static float DRAWLOOPTIME=0;
@ -27,21 +31,52 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene
public static List<Pixel> pixels; public static List<Pixel> pixels;
public static float fNear = 0.1f;
public static float fFar = 1000f;
public static float fFov = 90f;
public static float fAspectRatio = (float)SCREEN_HEIGHT/SCREEN_WIDTH;
public static float fFovRad = 1f/(float)Math.tan(fFov*0.5f/180f*Math.PI);
public static Matrix matProj = new Matrix(
new float[][]{
{fAspectRatio*fFovRad,0,0,0},
{0,fFovRad,0,0},
{0,0,fFar/(fFar-fNear),1f},
{0,0,(-fFar*fNear)/(fFar-fNear),0f},
});
public void runGameLoop() { public void runGameLoop() {
rot+=Math.PI/480d; rot+=Math.PI/480d;
} }
SigRenderer(JFrame f) { SigRenderer(JFrame f) {
cube = new Mesh(Arrays.asList(
tri = new Triangle(new Vector3f(-1,-1,0),new Vector3f(0,-1,0),new Vector3f(-1,0,0)); new Triangle[]{
tri2 = new Triangle(new Vector3f(-1,0,0),new Vector3f(0,-1,0),new Vector3f(0,0,0)); new Triangle(new Vector3f(),new Vector3f(0,1,0),new Vector3f(1,1,0)),
tri3 = new Triangle(new Vector3f(0,0,0),new Vector3f(0,-1,0),new Vector3f(0,-1,-1)); new Triangle(new Vector3f(),new Vector3f(1,1,0),new Vector3f(1,0,0)),
tri4 = new Triangle(new Vector3f(0,-1,-1),new Vector3f(0,0,-1),new Vector3f(0,-1,0)); new Triangle(new Vector3f(1,0,0),new Vector3f(1,1,0),new Vector3f(1,1,1)),
/*tri5 = new Triangle(new Vector3f(0,-1,0),new Vector3f(0,-1,-1),new Vector3f(0,0,0)); new Triangle(new Vector3f(1,0,0),new Vector3f(1,1,1),new Vector3f(1,0,1)),
tri6 = new Triangle(new Vector3f(0,0,0),new Vector3f(0,-1,-1),new Vector3f(0,0,-1));*/ new Triangle(new Vector3f(0,1,0),new Vector3f(0,1,1),new Vector3f(1,1,0)),
new Triangle(new Vector3f(0,1,1),new Vector3f(1,1,1),new Vector3f(1,1,0)),
new Triangle(new Vector3f(),new Vector3f(0,0,1),new Vector3f(1,0,0)),
new Triangle(new Vector3f(0,0,1),new Vector3f(1,0,1),new Vector3f(1,0,0)),
new Triangle(new Vector3f(0,0,1),new Vector3f(0,1,1),new Vector3f(1,0,1)),
new Triangle(new Vector3f(0,1,1),new Vector3f(1,1,1),new Vector3f(1,0,1)),
new Triangle(new Vector3f(),new Vector3f(0,1,0),new Vector3f(0,0,1)),
new Triangle(new Vector3f(0,1,0),new Vector3f(0,1,1),new Vector3f(0,0,1)),
}));
Panel p = new Panel(); Panel p = new Panel();
f.getContentPane().addMouseListener(this);
f.getContentPane().addMouseMotionListener(this);
f.addKeyListener(this);
f.setSize(SCREEN_WIDTH,SCREEN_HEIGHT);
f.add(p,BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
p.init();
new Thread() { new Thread() {
public void run(){ public void run(){
while (true) { while (true) {
@ -67,15 +102,6 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene
} }
} }
}.start(); }.start();
f.getContentPane().addMouseListener(this);
f.getContentPane().addMouseMotionListener(this);
f.addKeyListener(this);
f.add(p);
f.setSize(SCREEN_WIDTH,SCREEN_HEIGHT);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
p.init();
} }
public static void main(String[] args) { public static void main(String[] args) {
JFrame f = new JFrame("SigRenderer"); JFrame f = new JFrame("SigRenderer");

@ -9,6 +9,10 @@ public class Triangle {
this.C=C; this.C=C;
} }
@Override @Override
protected Object clone(){
return new Triangle((Vector3f)this.A.clone(),(Vector3f)this.B.clone(),(Vector3f)this.C.clone());
}
@Override
public String toString() { public String toString() {
return "Triangle [A=" + A + ", B=" + B + ", C=" + C + "]"; return "Triangle [A=" + A + ", B=" + B + ", C=" + C + "]";
} }

@ -0,0 +1,68 @@
package sig.utils;
import java.awt.Color;
import sig.SigRenderer;
public class DrawUtils {
public static void DrawTriangle(int[]canvas,int x1,int y1,int x2,int y2,int x3,int y3,Color col) {
DrawLine(canvas,x1,y1,x2,y2,col);
DrawLine(canvas,x2,y2,x3,y3,col);
DrawLine(canvas,x3,y3,x1,y1,col);
}
public static void DrawLine(int[] canvas,int x1,int y1,int x2,int y2,Color col) {
int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i;
dx=x2-x1;dy=y2-y1;
dx1=Math.abs(dx);dy1=Math.abs(dy);
px=2*dy1-dx1;py=2*dx1-dy1;
if (dy1<=dx1) {
if (dx>=0) {
x=x1;y=y1;xe=x2;
} else {
x=x2;y=y2;xe=x1;
}
Draw(canvas,x,y,col);
for (i=0;x<xe;i++) {
x=x+1;
if (px<0) {
px=px+2*dy1;
} else {
if ((dx<0&&dy<0)||(dx>0&&dy>0)) {
y=y+1;
} else {
y=y-1;
}
px=px+2*(dy1-dx1);
}
Draw(canvas,x,y,col);
}
} else {
if (dy>=0) {
x=x1;y=y1;ye=y2;
} else {
x=x2;y=y2;ye=y1;
}
Draw(canvas,x,y,col);
for (i=0;y<ye;i++) {
y=y+1;
if (py<=0) {
py=py+2*dx1;
} else {
if ((dx<0&&dy<0)||(dx>0&&dy>0)) {
x=x+1;
} else {
x=x-1;
}
py=py+2*(dx1-dy1);
}
Draw(canvas,x,y,col);
}
}
}
public static void Draw(int[] canvas,int x,int y,Color col) {
if (x>=0&&y>=0&&x<SigRenderer.SCREEN_WIDTH&&y<SigRenderer.SCREEN_HEIGHT) {
//System.out.println(x+","+y);
canvas[x+y*SigRenderer.SCREEN_WIDTH]=col.getRGB();
}
}
}
Loading…
Cancel
Save