diff --git a/dirt.png b/dirt.png new file mode 100644 index 0000000..7951b56 Binary files /dev/null and b/dirt.png differ diff --git a/src/sig/ExtraData.java b/src/sig/ExtraData.java new file mode 100644 index 0000000..2455add --- /dev/null +++ b/src/sig/ExtraData.java @@ -0,0 +1,8 @@ +package sig; + +public class ExtraData { + public float t; + ExtraData(float t) { + this.t=t; + } +} diff --git a/src/sig/Panel.java b/src/sig/Panel.java index f028e1a..fa87b6d 100644 --- a/src/sig/Panel.java +++ b/src/sig/Panel.java @@ -109,6 +109,9 @@ public class Panel extends JPanel implements Runnable { triTransformed.A = Matrix.MultiplyVector(matWorld,t.A); triTransformed.B = Matrix.MultiplyVector(matWorld,t.B); triTransformed.C = Matrix.MultiplyVector(matWorld,t.C); + triTransformed.T = t.T; + triTransformed.U = t.U; + triTransformed.V = t.V; Vector normal=new Vector(),line1=new Vector(),line2=new Vector(); line1 = Vector.subtract(triTransformed.B,triTransformed.A); @@ -130,6 +133,9 @@ public class Panel extends JPanel implements Runnable { triViewed.B = Matrix.MultiplyVector(matView,triTransformed.B); triViewed.C = Matrix.MultiplyVector(matView,triTransformed.C); triViewed.setColor(new Color(dp,dp,dp)); + triViewed.T = triTransformed.T; + triViewed.U = triTransformed.U; + triViewed.V = triTransformed.V; int clippedTriangles = 0; Triangle[] clipped = new Triangle[]{new Triangle(),new Triangle()}; @@ -143,6 +149,9 @@ public class Panel extends JPanel implements Runnable { triProjected.B = Matrix.MultiplyVector(SigRenderer.matProj,clipped[i].B); triProjected.C = Matrix.MultiplyVector(SigRenderer.matProj,clipped[i].C); triProjected.col = clipped[i].col; + triProjected.T = clipped[i].T; + triProjected.U = clipped[i].U; + triProjected.V = clipped[i].V; triProjected.A = Vector.divide(triProjected.A, triProjected.A.w); triProjected.B = Vector.divide(triProjected.B, triProjected.B.w); @@ -205,9 +214,13 @@ public class Panel extends JPanel implements Runnable { } for (Triangle tt : triList) { - DrawUtils.FillTriangle(p,(int)tt.A.x,(int)tt.A.y,(int)tt.B.x,(int)tt.B.y,(int)tt.C.x,(int)tt.C.y,tt.getColor()); + DrawUtils.TexturedTriangle(p, + (int)tt.A.x,(int)tt.A.y,tt.T.u,tt.T.v, + (int)tt.B.x,(int)tt.B.y,tt.U.u,tt.U.v, + (int)tt.C.x,(int)tt.C.y,tt.V.u,tt.V.v, + SigRenderer.dirtTex); if (SigRenderer.WIREFRAME) { - DrawUtils.DrawTriangle(p,(int)tt.A.x,(int)tt.A.y,(int)tt.B.x,(int)tt.B.y,(int)tt.C.x,(int)tt.C.y,Color.BLACK); + DrawUtils.DrawTriangle(p,(int)tt.A.x,(int)tt.A.y,(int)tt.B.x,(int)tt.B.y,(int)tt.C.x,(int)tt.C.y,Color.WHITE); } } } diff --git a/src/sig/SigRenderer.java b/src/sig/SigRenderer.java index f422d57..eaa4240 100644 --- a/src/sig/SigRenderer.java +++ b/src/sig/SigRenderer.java @@ -1,4 +1,5 @@ package sig; +import javax.imageio.ImageIO; import javax.swing.JFrame; import sig.utils.OBJReader; @@ -6,15 +7,19 @@ import sig.utils.OBJReader; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.util.Arrays; import java.util.List; import java.awt.Toolkit; import java.awt.BorderLayout; public class SigRenderer implements KeyListener,MouseListener,MouseMotionListener{ - public static boolean WIREFRAME = false; + public static boolean WIREFRAME = true; public static Mesh cube; public static int SCREEN_WIDTH=1280; @@ -40,6 +45,8 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene final float MOVESPEED = 0.03f; final float TURNSPEED = 0.03f; + public static BufferedImage dirtTex; + boolean upHeld=false,downHeld=false,leftHeld=false,rightHeld=false, aHeld=false,sHeld=false,dHeld=false,wHeld=false; @@ -74,7 +81,29 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene } SigRenderer(JFrame f) { - cube = new Mesh(OBJReader.ReadOBJFile("teapot.obj")); + + try { + dirtTex = ImageIO.read(new File("dirt.png")); + } catch (IOException e1) { + e1.printStackTrace(); + } + + //cube = new Mesh(OBJReader.ReadOBJFile("teapot.obj")); + cube = new Mesh(Arrays.asList( + new Triangle[]{ + new Triangle(new Vector(),new Vector(0,1,0),new Vector(1,1,0),new Vector2(0,1),new Vector2(0,0),new Vector2(1,0)), + new Triangle(new Vector(),new Vector(1,1,0),new Vector(1,0,0),new Vector2(0,1),new Vector2(1,0),new Vector2(1,1)), + new Triangle(new Vector(1,0,0),new Vector(1,1,0),new Vector(1,1,1),new Vector2(0,1),new Vector2(0,0),new Vector2(1,0)), + new Triangle(new Vector(1,0,0),new Vector(1,1,1),new Vector(1,0,1),new Vector2(0,1),new Vector2(1,0),new Vector2(1,1)), + new Triangle(new Vector(1,0,1),new Vector(1,1,1),new Vector(0,1,1),new Vector2(0,1),new Vector2(0,0),new Vector2(1,0)), + new Triangle(new Vector(1,0,1),new Vector(0,1,1),new Vector(0,0,1),new Vector2(0,1),new Vector2(1,0),new Vector2(1,1)), + new Triangle(new Vector(0,0,1),new Vector(0,1,1),new Vector(0,1,0),new Vector2(0,1),new Vector2(0,0),new Vector2(1,0)), + new Triangle(new Vector(0,0,1),new Vector(0,1,0),new Vector(0,0,0),new Vector2(0,1),new Vector2(1,0),new Vector2(1,1)), + new Triangle(new Vector(0,1,0),new Vector(0,1,1),new Vector(1,1,1),new Vector2(0,1),new Vector2(0,0),new Vector2(1,0)), + new Triangle(new Vector(0,1,0),new Vector(1,1,1),new Vector(1,1,0),new Vector2(0,1),new Vector2(1,0),new Vector2(1,1)), + new Triangle(new Vector(1,0,1),new Vector(0,0,1),new Vector(0,0,0),new Vector2(0,1),new Vector2(0,0),new Vector2(1,0)), + new Triangle(new Vector(1,0,1),new Vector(0,0,0),new Vector(1,0,0),new Vector2(0,1),new Vector2(1,0),new Vector2(1,1)), + })); Panel p = new Panel(); diff --git a/src/sig/Triangle.java b/src/sig/Triangle.java index bebe7ec..4c070f7 100644 --- a/src/sig/Triangle.java +++ b/src/sig/Triangle.java @@ -1,17 +1,23 @@ package sig; import java.awt.Color; -import java.util.Arrays; public class Triangle { Vector A,B,C; + Vector2 T,U,V; Color col = Color.WHITE; public Triangle() { this(new Vector(),new Vector(),new Vector()); } public Triangle(Vector A,Vector B,Vector C) { + this(A,B,C,new Vector2(),new Vector2(),new Vector2()); + } + public Triangle(Vector A,Vector B,Vector C,Vector2 T,Vector2 U,Vector2 V) { this.A=A; this.B=B; this.C=C; + this.T=T; + this.U=U; + this.V=V; } @Override protected Object clone(){ @@ -38,7 +44,10 @@ public class Triangle { plane_n = Vector.normalize(plane_n); Vector[] inside_points = new Vector[]{new Vector(),new Vector(),new Vector()}; Vector[] outside_points = new Vector[]{new Vector(),new Vector(),new Vector()}; + Vector2[] inside_tex = new Vector2[]{new Vector2(),new Vector2(),new Vector2()}; + Vector2[] outside_tex = new Vector2[]{new Vector2(),new Vector2(),new Vector2()}; int insidePointCount=0,outsidePointCount=0; + int insideTexCount=0,outsideTexCount=0; float d0=dist(plane_p,plane_n,in.A); float d1=dist(plane_p,plane_n,in.B); @@ -46,18 +55,24 @@ public class Triangle { if (d0>=0) { inside_points[insidePointCount++]=in.A; + inside_tex[insideTexCount++]=in.T; } else { outside_points[outsidePointCount++]=in.A; + outside_tex[outsideTexCount++]=in.T; } if (d1>=0) { inside_points[insidePointCount++]=in.B; + inside_tex[insideTexCount++]=in.U; } else { outside_points[outsidePointCount++]=in.B; + outside_tex[outsideTexCount++]=in.U; } if (d2>=0) { inside_points[insidePointCount++]=in.C; + inside_tex[insideTexCount++]=in.V; } else { outside_points[outsidePointCount++]=in.C; + outside_tex[outsideTexCount++]=in.V; } if (insidePointCount==0) { @@ -68,20 +83,35 @@ public class Triangle { return 1; } else if (insidePointCount==1&&outsidePointCount==2) { + ExtraData t = new ExtraData(0); out_tri[0].col = in.col; out_tri[0].A = inside_points[0]; - out_tri[0].B = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[0]); - out_tri[0].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[1]); + out_tri[0].T = inside_tex[0]; + out_tri[0].B = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[0],t); + out_tri[0].U.u = t.t*(outside_tex[0].u-inside_tex[0].u)+inside_tex[0].u; + out_tri[0].U.v = t.t*(outside_tex[0].v-inside_tex[0].v)+inside_tex[0].v; + out_tri[0].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[1],t); + out_tri[0].V.u = t.t*(outside_tex[1].u-inside_tex[0].u)+inside_tex[0].u; + out_tri[0].V.v = t.t*(outside_tex[1].v-inside_tex[0].v)+inside_tex[0].v; return 1; } else if (insidePointCount==2&&outsidePointCount==1) { + ExtraData t = new ExtraData(0); out_tri[0].col=out_tri[1].col=in.col; out_tri[0].A = inside_points[0]; out_tri[0].B = inside_points[1]; - out_tri[0].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[0]); + out_tri[0].T = inside_tex[0]; + out_tri[0].U = inside_tex[1]; + out_tri[0].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[0],t); + out_tri[0].V.u = t.t*(outside_tex[0].u-inside_tex[0].u)+inside_tex[0].u; + out_tri[0].V.v = t.t*(outside_tex[0].v-inside_tex[0].v)+inside_tex[0].v; out_tri[1].A = inside_points[1]; + out_tri[1].T = inside_tex[1]; out_tri[1].B = out_tri[0].C; - out_tri[1].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[1], outside_points[0]); + out_tri[1].U = out_tri[0].V; + out_tri[1].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[1], outside_points[0],t); + out_tri[1].V.u = t.t*(outside_tex[0].u-inside_tex[1].u)+inside_tex[1].u; + out_tri[1].V.v = t.t*(outside_tex[0].v-inside_tex[1].v)+inside_tex[1].v; return 2; } diff --git a/src/sig/Vector.java b/src/sig/Vector.java index 8842f2f..90448d2 100644 --- a/src/sig/Vector.java +++ b/src/sig/Vector.java @@ -53,12 +53,13 @@ public class Vector { public String toString() { return "Vector ["+x+","+y+","+z+","+w+"]"; } - public static Vector IntersectPlane(Vector plane_p,Vector plane_n,Vector lineStart,Vector lineEnd) { + public static Vector IntersectPlane(Vector plane_p,Vector plane_n,Vector lineStart,Vector lineEnd,ExtraData tt) { plane_n = Vector.normalize(plane_n); float plane_d = -Vector.dotProduct(plane_n,plane_p); float ad = Vector.dotProduct(lineStart,plane_n); float bd = Vector.dotProduct(lineEnd,plane_n); float t = (-plane_d-ad)/(bd-ad); + tt.t=t; Vector lineStartToEnd = Vector.subtract(lineEnd,lineStart); Vector lineToIntersect = Vector.multiply(lineStartToEnd,t); return Vector.add(lineStart,lineToIntersect); diff --git a/src/sig/Vector2.java b/src/sig/Vector2.java new file mode 100644 index 0000000..1e926e6 --- /dev/null +++ b/src/sig/Vector2.java @@ -0,0 +1,12 @@ +package sig; + +public class Vector2 { + public float u,v; + Vector2() { + this(0,0); + } + public Vector2(float u,float v) { + this.u=u; + this.v=v; + } +} diff --git a/src/sig/utils/DrawUtils.java b/src/sig/utils/DrawUtils.java index 1215c8c..f238b28 100644 --- a/src/sig/utils/DrawUtils.java +++ b/src/sig/utils/DrawUtils.java @@ -2,6 +2,7 @@ package sig.utils; import java.awt.Color; import java.util.Arrays; +import java.awt.image.BufferedImage; import sig.SigRenderer; @@ -11,6 +12,111 @@ public class DrawUtils { Draw(canvas,i,ny,col); } } + public static void TexturedTriangle(int[] canvas, + int x1, int y1, float u1,float v1, + int x2, int y2, float u2,float v2, + int x3, int y3, float u3,float v3, + BufferedImage texture + ) { + if (y2bx) { + int t=ax;ax=bx;bx=t; + float u=tex_su;tex_su=tex_eu;tex_eu=u; + float v=tex_sv;tex_sv=tex_ev;tex_ev=v; + } + + tex_u=tex_su; + tex_v=tex_sv; + + float tstep = 1.0f/((float)(bx-ax)); + float t=0.0f; + + for (int j=ax;jbx) { + int t=ax;ax=bx;bx=t; + float u=tex_su;tex_su=tex_eu;tex_eu=u; + float v=tex_sv;tex_sv=tex_ev;tex_ev=v; + } + + tex_u=tex_su; + tex_v=tex_sv; + + float tstep = 1.0f/((float)(bx-ax)); + float t=0.0f; + + for (int j=ax;j