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.vecmath.Vector3f;
import sig.utils.DrawUtils;
import java.awt.Graphics;
import java.awt.Color;
@ -22,6 +24,7 @@ public class Panel extends JPanel implements Runnable {
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
float fTheta=0f;
public Panel() {
super(true);
@ -46,6 +49,8 @@ public class Panel extends JPanel implements Runnable {
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
SigRenderer.SCREEN_WIDTH=getWidth();
SigRenderer.SCREEN_HEIGHT=getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
@ -64,6 +69,7 @@ public class Panel extends JPanel implements Runnable {
*/
public /* abstract */ void render(){
int[] p = pixel; // this avoid crash when resizing
//a=h/w
final int h=SigRenderer.SCREEN_HEIGHT;
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;
j += 1;
endTime=System.nanoTime();

@ -1,5 +1,6 @@
package sig;
import javax.swing.JFrame;
import javax.vecmath.Matrix4f;
import javax.vecmath.Point2d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3f;
@ -9,14 +10,17 @@ import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.awt.Toolkit;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.BorderLayout;
public class SigRenderer implements KeyListener,MouseListener,MouseMotionListener{
public static Triangle tri,tri2,tri3,tri4,tri5,tri6;
public final static int SCREEN_WIDTH=1280;
public final static int SCREEN_HEIGHT=720;
public static Mesh cube;
public static int SCREEN_WIDTH=1280;
public static int SCREEN_HEIGHT=720;
public final static long TIMEPERTICK = 16666667l;
public static float DRAWTIME=0;
public static float DRAWLOOPTIME=0;
@ -27,21 +31,52 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene
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() {
rot+=Math.PI/480d;
}
SigRenderer(JFrame f) {
tri = new Triangle(new Vector3f(-1,-1,0),new Vector3f(0,-1,0),new Vector3f(-1,0,0));
tri2 = new Triangle(new Vector3f(-1,0,0),new Vector3f(0,-1,0),new Vector3f(0,0,0));
tri3 = new Triangle(new Vector3f(0,0,0),new Vector3f(0,-1,0),new Vector3f(0,-1,-1));
tri4 = new Triangle(new Vector3f(0,-1,-1),new Vector3f(0,0,-1),new Vector3f(0,-1,0));
/*tri5 = new Triangle(new Vector3f(0,-1,0),new Vector3f(0,-1,-1),new Vector3f(0,0,0));
tri6 = new Triangle(new Vector3f(0,0,0),new Vector3f(0,-1,-1),new Vector3f(0,0,-1));*/
cube = new Mesh(Arrays.asList(
new Triangle[]{
new Triangle(new Vector3f(),new Vector3f(0,1,0),new Vector3f(1,1,0)),
new Triangle(new Vector3f(),new Vector3f(1,1,0),new Vector3f(1,0,0)),
new Triangle(new Vector3f(1,0,0),new Vector3f(1,1,0),new Vector3f(1,1,1)),
new Triangle(new Vector3f(1,0,0),new Vector3f(1,1,1),new Vector3f(1,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();
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() {
public void run(){
while (true) {
@ -67,15 +102,6 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene
}
}
}.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) {
JFrame f = new JFrame("SigRenderer");

@ -9,6 +9,10 @@ public class Triangle {
this.C=C;
}
@Override
protected Object clone(){
return new Triangle((Vector3f)this.A.clone(),(Vector3f)this.B.clone(),(Vector3f)this.C.clone());
}
@Override
public String toString() {
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