Fixed Texture coordinates to account for perspective.

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
This commit is contained in:
sigonasr2, Sig, Sigo 2021-11-03 12:41:54 +00:00
parent 9ea6587bdf
commit 482d512433
7 changed files with 94 additions and 34 deletions

View File

@ -17,6 +17,8 @@ import java.awt.GraphicsEnvironment;
import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfiguration;
import java.awt.Toolkit; import java.awt.Toolkit;
import sig.Texture;
public class Panel extends JPanel implements Runnable { public class Panel extends JPanel implements Runnable {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
long endTime = System.nanoTime(); long endTime = System.nanoTime();
@ -149,9 +151,20 @@ public class Panel extends JPanel implements Runnable {
triProjected.B = Matrix.MultiplyVector(SigRenderer.matProj,clipped[i].B); triProjected.B = Matrix.MultiplyVector(SigRenderer.matProj,clipped[i].B);
triProjected.C = Matrix.MultiplyVector(SigRenderer.matProj,clipped[i].C); triProjected.C = Matrix.MultiplyVector(SigRenderer.matProj,clipped[i].C);
triProjected.col = clipped[i].col; triProjected.col = clipped[i].col;
triProjected.T = clipped[i].T; triProjected.T = (Vector2)clipped[i].T.clone();
triProjected.U = clipped[i].U; triProjected.U = (Vector2)clipped[i].U.clone();
triProjected.V = clipped[i].V; triProjected.V = (Vector2)clipped[i].V.clone();
triProjected.T.u = triProjected.T.u/triProjected.A.w;
triProjected.U.u = triProjected.U.u/triProjected.B.w;
triProjected.V.u = triProjected.V.u/triProjected.C.w;
triProjected.T.v = triProjected.T.v/triProjected.A.w;
triProjected.U.v = triProjected.U.v/triProjected.B.w;
triProjected.V.v = triProjected.V.v/triProjected.C.w;
triProjected.T.w = 1.0f/triProjected.A.w;
triProjected.U.w = 1.0f/triProjected.B.w;
triProjected.V.w = 1.0f/triProjected.C.w;
triProjected.A = Vector.divide(triProjected.A, triProjected.A.w); triProjected.A = Vector.divide(triProjected.A, triProjected.A.w);
triProjected.B = Vector.divide(triProjected.B, triProjected.B.w); triProjected.B = Vector.divide(triProjected.B, triProjected.B.w);
@ -215,9 +228,9 @@ public class Panel extends JPanel implements Runnable {
for (Triangle tt : triList) { for (Triangle tt : triList) {
DrawUtils.TexturedTriangle(p, DrawUtils.TexturedTriangle(p,
(int)tt.A.x,(int)tt.A.y,tt.T.u,tt.T.v, (int)tt.A.x,(int)tt.A.y,tt.T.u,tt.T.v,tt.T.w,
(int)tt.B.x,(int)tt.B.y,tt.U.u,tt.U.v, (int)tt.B.x,(int)tt.B.y,tt.U.u,tt.U.v,tt.U.w,
(int)tt.C.x,(int)tt.C.y,tt.V.u,tt.V.v, (int)tt.C.x,(int)tt.C.y,tt.V.u,tt.V.v,tt.V.w,
SigRenderer.dirtTex); SigRenderer.dirtTex);
if (SigRenderer.WIREFRAME) { 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.WHITE); 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);

View File

@ -2,12 +2,9 @@ package sig;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.JFrame; import javax.swing.JFrame;
import sig.utils.OBJReader;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener; import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@ -45,7 +42,7 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene
final float MOVESPEED = 0.03f; final float MOVESPEED = 0.03f;
final float TURNSPEED = 0.03f; final float TURNSPEED = 0.03f;
public static BufferedImage dirtTex; public static Texture dirtTex;
boolean upHeld=false,downHeld=false,leftHeld=false,rightHeld=false, boolean upHeld=false,downHeld=false,leftHeld=false,rightHeld=false,
aHeld=false,sHeld=false,dHeld=false,wHeld=false; aHeld=false,sHeld=false,dHeld=false,wHeld=false;
@ -81,12 +78,7 @@ public class SigRenderer implements KeyListener,MouseListener,MouseMotionListene
} }
SigRenderer(JFrame f) { SigRenderer(JFrame f) {
dirtTex = new Texture(new File("dirt.png"));
try {
dirtTex = ImageIO.read(new File("dirt.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
//cube = new Mesh(OBJReader.ReadOBJFile("teapot.obj")); //cube = new Mesh(OBJReader.ReadOBJFile("teapot.obj"));
cube = new Mesh(Arrays.asList( cube = new Mesh(Arrays.asList(

30
src/sig/Texture.java Normal file
View File

@ -0,0 +1,30 @@
package sig;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.Color;
public class Texture{
BufferedImage tex;
public Texture(File f) {
try {
this.tex = ImageIO.read(f);
} catch (IOException e) {
e.printStackTrace();
}
}
public Color getColor(float u,float v) {
int sx = (int)(u*tex.getWidth()-1f);
int sy = (int)(v*tex.getHeight()-1f);
if (sx<0||sx>=tex.getWidth()||sy<0||sy>=tex.getHeight()) {
return new Color(0,0,0,0);
} else {
return new Color(tex.getRGB(sx,sy));
}
}
}

View File

@ -90,9 +90,11 @@ public class Triangle {
out_tri[0].B = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[0],t); 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.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].U.v = t.t*(outside_tex[0].v-inside_tex[0].v)+inside_tex[0].v;
out_tri[0].U.w = t.t*(outside_tex[0].w-inside_tex[0].w)+inside_tex[0].w;
out_tri[0].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[1],t); 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.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; out_tri[0].V.v = t.t*(outside_tex[1].v-inside_tex[0].v)+inside_tex[0].v;
out_tri[0].V.w = t.t*(outside_tex[1].w-inside_tex[0].w)+inside_tex[0].w;
return 1; return 1;
} else } else
if (insidePointCount==2&&outsidePointCount==1) { if (insidePointCount==2&&outsidePointCount==1) {
@ -105,6 +107,7 @@ public class Triangle {
out_tri[0].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[0], outside_points[0],t); 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.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[0].V.v = t.t*(outside_tex[0].v-inside_tex[0].v)+inside_tex[0].v;
out_tri[0].V.w = t.t*(outside_tex[0].w-inside_tex[0].w)+inside_tex[0].w;
out_tri[1].A = inside_points[1]; out_tri[1].A = inside_points[1];
out_tri[1].T = inside_tex[1]; out_tri[1].T = inside_tex[1];
out_tri[1].B = out_tri[0].C; out_tri[1].B = out_tri[0].C;
@ -112,6 +115,7 @@ public class Triangle {
out_tri[1].C = Vector.IntersectPlane(plane_p, plane_n, inside_points[1], outside_points[0],t); 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.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; out_tri[1].V.v = t.t*(outside_tex[0].v-inside_tex[1].v)+inside_tex[1].v;
out_tri[1].V.w = t.t*(outside_tex[0].w-inside_tex[1].w)+inside_tex[1].w;
return 2; return 2;
} }

View File

@ -16,7 +16,7 @@ public class Vector {
} }
@Override @Override
protected Object clone(){ protected Object clone(){
return new Vector(x,y,z); return new Vector(x,y,z,w);
} }
public static Vector add(Vector v1,Vector v2) { public static Vector add(Vector v1,Vector v2) {

View File

@ -1,16 +1,20 @@
package sig; package sig;
public class Vector2 { public class Vector2 {
public float u,v; public float u,v,w;
Vector2() { Vector2() {
this(0,0); this(0,0,1);
} }
public Vector2(float u,float v) { public Vector2(float u,float v) {
this(u,v,1);
}
public Vector2(float u,float v,float w) {
this.u=u; this.u=u;
this.v=v; this.v=v;
this.w=w;
} }
@Override @Override
protected Object clone(){ protected Object clone(){
return new Vector2(u,v); return new Vector2(u,v,w);
} }
} }

View File

@ -5,6 +5,7 @@ import java.util.Arrays;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import sig.SigRenderer; import sig.SigRenderer;
import sig.Texture;
public class DrawUtils { public class DrawUtils {
static void drawLine(int[] canvas,int sx,int ex,int ny,Color col) { static void drawLine(int[] canvas,int sx,int ex,int ny,Color col) {
@ -13,36 +14,40 @@ public class DrawUtils {
} }
} }
public static void TexturedTriangle(int[] canvas, public static void TexturedTriangle(int[] canvas,
int x1, int y1, float u1,float v1, int x1, int y1, float u1,float v1,float w1,
int x2, int y2, float u2,float v2, int x2, int y2, float u2,float v2,float w2,
int x3, int y3, float u3,float v3, int x3, int y3, float u3,float v3,float w3,
BufferedImage texture Texture texture
) { ) {
if (y2<y1) {int t=y1;y1=y2;y2=t;t=x1;x1=x2;x2=t;float u=u1;u1=u2;u2=u;float v=v1;v1=v2;v2=v;} if (y2<y1) {int t=y1;y1=y2;y2=t;t=x1;x1=x2;x2=t;float u=u1;u1=u2;u2=u;float v=v1;v1=v2;v2=v;float w=w1;w1=w2;w2=w;}
if (y3<y1) {int t=y1;y1=y3;y3=t;t=x1;x1=x3;x3=t;float u=u1;u1=u3;u3=u;float v=v1;v1=v3;v3=v;} if (y3<y1) {int t=y1;y1=y3;y3=t;t=x1;x1=x3;x3=t;float u=u1;u1=u3;u3=u;float v=v1;v1=v3;v3=v;float w=w1;w1=w3;w3=w;}
if (y3<y2) {int t=y2;y2=y3;y3=t;t=x2;x2=x3;x3=t;float u=u2;u2=u3;u3=u;float v=v2;v2=v3;v3=v;} if (y3<y2) {int t=y2;y2=y3;y3=t;t=x2;x2=x3;x3=t;float u=u2;u2=u3;u3=u;float v=v2;v2=v3;v3=v;float w=w2;w2=w3;w3=w;}
int dy1=y2-y1; int dy1=y2-y1;
int dx1=x2-x1; int dx1=x2-x1;
float dv1=v2-v1; float dv1=v2-v1;
float du1=u2-u1; float du1=u2-u1;
float dw1=w2-w1;
int dy2=y3-y1; int dy2=y3-y1;
int dx2=x3-x1; int dx2=x3-x1;
float dv2=v3-v1; float dv2=v3-v1;
float du2=u3-u1; float du2=u3-u1;
float tex_u,tex_v; float dw2=w3-w1;
float tex_u,tex_v,tex_w;
float dax_step=0,dbx_step=0, float dax_step=0,dbx_step=0,
du1_step=0,dv1_step=0, du1_step=0,dv1_step=0,dw1_step=0,
du2_step=0,dv2_step=0; du2_step=0,dv2_step=0,dw2_step=0;
if (dy1!=0) {dax_step=dx1/((float)Math.abs(dy1));} if (dy1!=0) {dax_step=dx1/((float)Math.abs(dy1));}
if (dy2!=0) {dbx_step=dx2/((float)Math.abs(dy2));} if (dy2!=0) {dbx_step=dx2/((float)Math.abs(dy2));}
if (dy1!=0) {du1_step=du1/((float)Math.abs(dy1));} if (dy1!=0) {du1_step=du1/((float)Math.abs(dy1));}
if (dy1!=0) {dv1_step=dv1/((float)Math.abs(dy1));} if (dy1!=0) {dv1_step=dv1/((float)Math.abs(dy1));}
if (dy1!=0) {dw1_step=dw1/((float)Math.abs(dy1));}
if (dy2!=0) {du2_step=du2/((float)Math.abs(dy2));} if (dy2!=0) {du2_step=du2/((float)Math.abs(dy2));}
if (dy2!=0) {dv2_step=dv2/((float)Math.abs(dy2));} if (dy2!=0) {dv2_step=dv2/((float)Math.abs(dy2));}
if (dy2!=0) {dw2_step=dw2/((float)Math.abs(dy2));}
if (dy1!=0) { if (dy1!=0) {
for (int i=y1;i<=y2;i++) { for (int i=y1;i<=y2;i++) {
@ -51,17 +56,21 @@ public class DrawUtils {
float tex_su=u1+((float)(i-y1))*du1_step; float tex_su=u1+((float)(i-y1))*du1_step;
float tex_sv=v1+((float)(i-y1))*dv1_step; float tex_sv=v1+((float)(i-y1))*dv1_step;
float tex_sw=w1+((float)(i-y1))*dw1_step;
float tex_eu=u1+((float)(i-y1))*du2_step; float tex_eu=u1+((float)(i-y1))*du2_step;
float tex_ev=v1+((float)(i-y1))*dv2_step; float tex_ev=v1+((float)(i-y1))*dv2_step;
float tex_ew=w1+((float)(i-y1))*dw2_step;
if (ax>bx) { if (ax>bx) {
int t=ax;ax=bx;bx=t; int t=ax;ax=bx;bx=t;
float u=tex_su;tex_su=tex_eu;tex_eu=u; float u=tex_su;tex_su=tex_eu;tex_eu=u;
float v=tex_sv;tex_sv=tex_ev;tex_ev=v; float v=tex_sv;tex_sv=tex_ev;tex_ev=v;
float w=tex_sw;tex_sw=tex_ew;tex_ew=w;
} }
tex_u=tex_su; tex_u=tex_su;
tex_v=tex_sv; tex_v=tex_sv;
tex_w=tex_sw;
float tstep = 1.0f/((float)(bx-ax)); float tstep = 1.0f/((float)(bx-ax));
float t=0.0f; float t=0.0f;
@ -69,7 +78,8 @@ public class DrawUtils {
for (int j=ax;j<bx;j++) { for (int j=ax;j<bx;j++) {
tex_u=(1.0f-t)*tex_su+t*tex_eu; tex_u=(1.0f-t)*tex_su+t*tex_eu;
tex_v=(1.0f-t)*tex_sv+t*tex_ev; tex_v=(1.0f-t)*tex_sv+t*tex_ev;
Draw(canvas,j,i,new Color(texture.getRGB((int)Math.max(0,tex_u*(texture.getWidth()-1)),(int)Math.max(0,tex_v*(texture.getHeight()-1))))); tex_w=(1.0f-t)*tex_sw+t*tex_ew;
Draw(canvas,j,i,texture.getColor(tex_u/tex_w,tex_v/tex_w));
t+=tstep; t+=tstep;
} }
} }
@ -79,31 +89,37 @@ public class DrawUtils {
dx1=x3-x2; dx1=x3-x2;
dv1=v3-v2; dv1=v3-v2;
du1=u3-u2; du1=u3-u2;
dw1=w3-w2;
if (dy1!=0) {dax_step=dx1/((float)Math.abs(dy1));} if (dy1!=0) {dax_step=dx1/((float)Math.abs(dy1));}
if (dy2!=0) {dbx_step=dx2/((float)Math.abs(dy2));} if (dy2!=0) {dbx_step=dx2/((float)Math.abs(dy2));}
du1_step=0f; du1_step=0f;
dv1_step=0f; dv1_step=0f;
if (dy1!=0) {du1_step=du1/((float)Math.abs(dy1));} if (dy1!=0) {du1_step=du1/((float)Math.abs(dy1));}
if (dy1!=0) {dv1_step=dv1/((float)Math.abs(dy1));} if (dy1!=0) {dv1_step=dv1/((float)Math.abs(dy1));}
if (dy1!=0) {dw1_step=dw1/((float)Math.abs(dy1));}
if (dy1!=0) { if (dy1!=0) {
for (int i=y2;i<=y3;i++) { for (int i=y2;i<=y3;i++) {
int ax=(int)(x2+(float)(i-y2)*dax_step); int ax=(int)(x2+((float)(i-y2))*dax_step);
int bx=(int)(x1+(float)(i-y1)*dbx_step); int bx=(int)(x1+((float)(i-y1))*dbx_step);
float tex_su=u2+((float)(i-y2))*du1_step; float tex_su=u2+((float)(i-y2))*du1_step;
float tex_sv=v2+((float)(i-y2))*dv1_step; float tex_sv=v2+((float)(i-y2))*dv1_step;
float tex_sw=w2+((float)(i-y2))*dw1_step;
float tex_eu=u1+((float)(i-y1))*du2_step; float tex_eu=u1+((float)(i-y1))*du2_step;
float tex_ev=v1+((float)(i-y1))*dv2_step; float tex_ev=v1+((float)(i-y1))*dv2_step;
float tex_ew=w1+((float)(i-y1))*dw2_step;
if (ax>bx) { if (ax>bx) {
int t=ax;ax=bx;bx=t; int t=ax;ax=bx;bx=t;
float u=tex_su;tex_su=tex_eu;tex_eu=u; float u=tex_su;tex_su=tex_eu;tex_eu=u;
float v=tex_sv;tex_sv=tex_ev;tex_ev=v; float v=tex_sv;tex_sv=tex_ev;tex_ev=v;
float w=tex_sw;tex_sw=tex_ew;tex_ew=w;
} }
tex_u=tex_su; tex_u=tex_su;
tex_v=tex_sv; tex_v=tex_sv;
tex_w=tex_sw;
float tstep = 1.0f/((float)(bx-ax)); float tstep = 1.0f/((float)(bx-ax));
float t=0.0f; float t=0.0f;
@ -111,7 +127,8 @@ public class DrawUtils {
for (int j=ax;j<bx;j++) { for (int j=ax;j<bx;j++) {
tex_u=(1.0f-t)*tex_su+t*tex_eu; tex_u=(1.0f-t)*tex_su+t*tex_eu;
tex_v=(1.0f-t)*tex_sv+t*tex_ev; tex_v=(1.0f-t)*tex_sv+t*tex_ev;
Draw(canvas,j,i,new Color(texture.getRGB((int)Math.max(0,tex_u*(texture.getWidth()-1)),(int)Math.max(0,tex_v*(texture.getHeight()-1))))); tex_w=(1.0f-t)*tex_sw+t*tex_ew;
Draw(canvas,j,i,texture.getColor(tex_u/tex_w,tex_v/tex_w));
t+=tstep; t+=tstep;
} }
} }