Refactor and create helper utility functions.

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
origin
sigonasr2, Sig, Sigo 3 years ago
parent dfe6210836
commit 7b0467cc5d
  1. 78
      src/sig/Matrix.java
  2. 79
      src/sig/Panel.java
  3. 9
      src/sig/SigRenderer.java
  4. 3
      src/sig/Triangle.java
  5. 38
      src/sig/Vector.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;
}
}

@ -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());
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);
Triangle triProjected = new Triangle(),triTransformed=new Triangle();
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;
normal = Vector.crossProduct(line1,line2);
normal = Vector.normalize(normal);
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;
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;

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

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

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

Loading…
Cancel
Save