diff --git a/src/sig/Matrix.java b/src/sig/Matrix.java new file mode 100644 index 0000000..ea48945 --- /dev/null +++ b/src/sig/Matrix.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; + } + } +} diff --git a/src/sig/Mesh.java b/src/sig/Mesh.java new file mode 100644 index 0000000..de2afd2 --- /dev/null +++ b/src/sig/Mesh.java @@ -0,0 +1,11 @@ +package sig; + +import java.util.ArrayList; +import java.util.List; + +public class Mesh { + List triangles = new ArrayList<>(); + Mesh(List tris) { + this.triangles=tris; + } +} diff --git a/src/sig/Panel.java b/src/sig/Panel.java index 0510a0f..9ba932f 100644 --- a/src/sig/Panel.java +++ b/src/sig/Panel.java @@ -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(); diff --git a/src/sig/SigRenderer.java b/src/sig/SigRenderer.java index 5541a28..f78d368 100644 --- a/src/sig/SigRenderer.java +++ b/src/sig/SigRenderer.java @@ -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 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"); diff --git a/src/sig/Triangle.java b/src/sig/Triangle.java index 199b01e..28ff0ae 100644 --- a/src/sig/Triangle.java +++ b/src/sig/Triangle.java @@ -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 + "]"; } diff --git a/src/sig/utils/DrawUtils.java b/src/sig/utils/DrawUtils.java new file mode 100644 index 0000000..c51822a --- /dev/null +++ b/src/sig/utils/DrawUtils.java @@ -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;x0&&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;y0&&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