diff --git a/src/sig/Matrix.java b/src/sig/Matrix.java index 2a6e627..3e32cd9 100644 --- a/src/sig/Matrix.java +++ b/src/sig/Matrix.java @@ -2,20 +2,80 @@ package sig; public class Matrix { float[][] m = new float[4][4]; + Matrix(){} Matrix(float[][]m) { this.m=m; } - public static void MultiplyMatrixVector(Vector i,Vector 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]; + public final static Matrix IDENTITY = new Matrix(new float[][]{ + {1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}, + }); - if (w!=0f) { - o.x/=w; - o.y/=w; - o.z/=w; + public static Vector MultiplyVector(Matrix m, Vector i) { + return new Vector( + i.x*m.m[0][0]+i.y*m.m[1][0]+i.z*m.m[2][0]+i.w*m.m[3][0], + i.x*m.m[0][1]+i.y*m.m[1][1]+i.z*m.m[2][1]+i.w*m.m[3][1], + i.x*m.m[0][2]+i.y*m.m[1][2]+i.z*m.m[2][2]+i.w*m.m[3][2], + i.x*m.m[0][3]+i.y*m.m[1][3]+i.z*m.m[2][3]+i.w*m.m[3][3] + ); + } + + public static Matrix MakeRotationX(float angle) { + return new Matrix(new float[][]{ + {1,0,0,0,}, + {0,(float)Math.cos(angle),(float)Math.sin(angle),0,}, + {0,(float)-Math.sin(angle),(float)Math.cos(angle),0,}, + {0,0,0,1,}, + }); + } + public static Matrix MakeRotationY(float angle) { + return new Matrix(new float[][]{ + {(float)Math.cos(angle),0,(float)Math.sin(angle),0,}, + {0,1,0,0,}, + {(float)-Math.sin(angle),0,(float)Math.cos(angle),0,}, + {0,0,0,1,}, + }); + } + public static Matrix MakeRotationZ(float angle) { + return new Matrix(new float[][]{ + {(float)Math.cos(angle),(float)Math.sin(angle),0,0,}, + {(float)-Math.sin(angle),(float)Math.cos(angle),0,0,}, + {0,0,1,0,}, + {0,0,0,1,}, + }); + } + public static Matrix MakeTranslation(float x,float y,float z) { + return new Matrix(new float[][]{ + {1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {x,y,z,1}, + }); + } + public static Matrix MakeProjection(float fov,float aspectRatio,float near,float far) { + float fFovRad = 1f/(float)Math.tan(fov*0.5f/180f*Math.PI); + return new Matrix( + new float[][]{ + {aspectRatio*fFovRad,0,0,0}, + {0,fFovRad,0,0}, + {0,0,far/(far-near),1f}, + {0,0,(-far*near)/(far-near),0f}, + }); + } + public static Matrix MultiplyMatrix(Matrix m1,Matrix m2) { + Matrix mm = new Matrix(); + for (int c=0;c<4;c++) { + for (int r=0;r<4;r++) { + mm.m[r][c]= + m1.m[r][0]*m2.m[0][c]+ + m1.m[r][1]*m2.m[1][c]+ + m1.m[r][2]*m2.m[2][c]+ + m1.m[r][3]*m2.m[3][c]; + } } + return mm; } } diff --git a/src/sig/Panel.java b/src/sig/Panel.java index 554785e..a9b4494 100644 --- a/src/sig/Panel.java +++ b/src/sig/Panel.java @@ -88,72 +88,49 @@ public class Panel extends JPanel implements Runnable { accumulatedTris.clear(); - 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,}, - }); + Matrix matRotZ = Matrix.MakeRotationZ(fTheta),matRotX = Matrix.MakeRotationX(fTheta*0.5f); + Matrix matTranslation = Matrix.MakeTranslation(0,0,16); + Matrix matWorld = Matrix.IDENTITY; + matWorld = Matrix.MultiplyMatrix(matRotZ,matRotX); + matWorld = Matrix.MultiplyMatrix(matWorld,matTranslation); fTheta+=0.01f; for (Triangle t : SigRenderer.cube.triangles) { - Triangle triProjected = new Triangle(new Vector(),new Vector(),new Vector()),triTranslated=new Triangle(new Vector(),new Vector(),new Vector()),triRotatedZ=new Triangle(new Vector(),new Vector(),new Vector()),triRotatedZX=new Triangle(new Vector(),new Vector(),new Vector()); + Triangle triProjected = new Triangle(),triTransformed=new Triangle(); - - 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+6f; - triTranslated.B.z=triRotatedZX.B.z+6f; - triTranslated.C.z=triRotatedZX.C.z+6f; + triTransformed.A = Matrix.MultiplyVector(matWorld,t.A); + triTransformed.B = Matrix.MultiplyVector(matWorld,t.B); + triTransformed.C = Matrix.MultiplyVector(matWorld,t.C); Vector normal=new Vector(),line1=new Vector(),line2=new Vector(); - line1.x=triTranslated.B.x-triTranslated.A.x; - line1.y=triTranslated.B.y-triTranslated.A.y; - line1.z=triTranslated.B.z-triTranslated.A.z; - line2.x=triTranslated.C.x-triTranslated.A.x; - line2.y=triTranslated.C.y-triTranslated.A.y; - line2.z=triTranslated.C.z-triTranslated.A.z; + line1 = Vector.subtract(triTransformed.B,triTransformed.A); + line2 = Vector.subtract(triTransformed.C,triTransformed.A); - normal.x=line1.y*line2.z-line1.z*line2.y; - normal.y=line1.z*line2.x-line1.x*line2.z; - normal.z=line1.x*line2.y-line1.y*line2.x; - - float l = (float)Math.sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z); - normal.x/=l; normal.y/=l; normal.z/=l; + normal = Vector.crossProduct(line1,line2); + normal = Vector.normalize(normal); + + Vector cameraRay = Vector.subtract(triTransformed.A,SigRenderer.vCamera); - if (normal.x*(triTranslated.A.x-SigRenderer.vCamera.x)+ - normal.y*(triTranslated.A.y-SigRenderer.vCamera.y)+ - normal.z*(triTranslated.A.z-SigRenderer.vCamera.z)<0) { + if (Vector.dotProduct(normal,cameraRay)<0) { Vector lightDir = new Vector(0,0,-1); - l = (float)Math.sqrt(lightDir.x*lightDir.x+lightDir.y*lightDir.y+lightDir.z*lightDir.z); - lightDir.x/=l; lightDir.y/=l; lightDir.z/=l; + lightDir = Vector.normalize(lightDir); - float dp = Math.abs(normal.x*lightDir.x+normal.y*lightDir.y+normal.z*lightDir.z); + float dp = Math.max(0.1f,Vector.dotProduct(lightDir,normal)); - 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 = Matrix.MultiplyVector(SigRenderer.matProj,triTransformed.A); + triProjected.B = Matrix.MultiplyVector(SigRenderer.matProj,triTransformed.B); + triProjected.C = Matrix.MultiplyVector(SigRenderer.matProj,triTransformed.C); triProjected.setColor(new Color(dp,dp,dp)); - 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 = Vector.divide(triProjected.A, triProjected.A.w); + triProjected.B = Vector.divide(triProjected.B, triProjected.B.w); + triProjected.C = Vector.divide(triProjected.C, triProjected.C.w); + + Vector viewOffset = new Vector(1,1,0); + triProjected.A = Vector.add(triProjected.A,viewOffset); + triProjected.B = Vector.add(triProjected.B,viewOffset); + triProjected.C = Vector.add(triProjected.C,viewOffset); triProjected.A.x*=0.5f*SigRenderer.SCREEN_WIDTH; triProjected.A.y*=0.5f*SigRenderer.SCREEN_HEIGHT; triProjected.B.x*=0.5f*SigRenderer.SCREEN_WIDTH; diff --git a/src/sig/SigRenderer.java b/src/sig/SigRenderer.java index fa3b8bf..47bb908 100644 --- a/src/sig/SigRenderer.java +++ b/src/sig/SigRenderer.java @@ -33,14 +33,7 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene 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 static Matrix matProj = Matrix.MakeProjection(fFov,fAspectRatio,fNear,fFar); public static Vector vCamera = new Vector(); diff --git a/src/sig/Triangle.java b/src/sig/Triangle.java index 18daca3..6b6f6b6 100644 --- a/src/sig/Triangle.java +++ b/src/sig/Triangle.java @@ -4,6 +4,9 @@ import java.awt.Color; public class Triangle { Vector A,B,C; Color col = Color.WHITE; + public Triangle() { + this(new Vector(),new Vector(),new Vector()); + } public Triangle(Vector A,Vector B,Vector C) { this.A=A; this.B=B; diff --git a/src/sig/Vector.java b/src/sig/Vector.java index 77c9c0f..fb56652 100644 --- a/src/sig/Vector.java +++ b/src/sig/Vector.java @@ -1,17 +1,51 @@ package sig; public class Vector { - public float x,y,z; + public float x,y,z,w; Vector() { - this(0,0,0); + this(0,0,0,1); } public Vector(float x,float y,float z) { + this(x,y,z,1); + } + public Vector(float x,float y,float z,float w) { this.x=x; this.y=y; this.z=z; + this.w=w; } @Override protected Object clone(){ return new Vector(x,y,z); } + + public static Vector add(Vector v1,Vector v2) { + return new Vector(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z); + } + public static Vector subtract(Vector v1,Vector v2) { + return new Vector(v1.x-v2.x,v1.y-v2.y,v1.z-v2.z); + } + public static Vector multiply(Vector v1,float k) { + return new Vector(v1.x*k,v1.y*k,v1.z*k); + } + public static Vector divide(Vector v1,float k) { + return new Vector(v1.x/k,v1.y/k,v1.z/k); + } + public static float dotProduct(Vector v1,Vector v2) { + return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z; + } + public static float length(Vector v) { + return (float)Math.sqrt(dotProduct(v,v)); + } + public static Vector normalize(Vector v) { + float l = length(v); + return new Vector(v.x/l,v.y/l,v.z/l); + } + public static Vector crossProduct(Vector v1,Vector v2) { + Vector v = new Vector(); + v.x=v1.y*v2.z-v1.z*v2.y; + v.y=v1.z*v2.x-v1.x*v2.z; + v.z=v1.x*v2.y-v1.y*v2.x; + return v; + } }