Draw a rotating 3D cube.

This commit is contained in:
Joshua Sigona 2021-11-02 09:41:33 +09:00
parent 0bb1e490c3
commit 9e324be3e2
6 changed files with 207 additions and 19 deletions

23
src/sig/Matrix.java Normal file
View File

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

11
src/sig/Mesh.java Normal file
View File

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

View File

@ -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();

View File

@ -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");

View File

@ -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 + "]";
}

View File

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