From f70e1a4dbe25d03caa32ec88d2991b9293312745 Mon Sep 17 00:00:00 2001 From: Joshua Sigona Date: Wed, 3 Nov 2021 17:11:30 +0900 Subject: [PATCH] Starting of texture mapping to 3D coords --- dirt.png | Bin 0 -> 31634 bytes src/sig/ExtraData.java | 8 +++ src/sig/Panel.java | 17 +++++- src/sig/SigRenderer.java | 33 ++++++++++- src/sig/Triangle.java | 40 +++++++++++-- src/sig/Vector.java | 3 +- src/sig/Vector2.java | 12 ++++ src/sig/utils/DrawUtils.java | 106 +++++++++++++++++++++++++++++++++++ 8 files changed, 209 insertions(+), 10 deletions(-) create mode 100644 dirt.png create mode 100644 src/sig/ExtraData.java create mode 100644 src/sig/Vector2.java diff --git a/dirt.png b/dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..7951b56d41d1ce6d7784e75c7b01edf79e2b9ef3 GIT binary patch literal 31634 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�qy6D*Y@R^qC+9%tgU2zVM}V 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 literal 0 HcmV?d00001 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