From 099f3e672c88099d62db50e87590151a7ab6dc17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petar=20Kapri=C5=A1?= Date: Wed, 23 Nov 2022 15:56:49 +0100 Subject: [PATCH] Modify HitBall (quadratic equation based solution) --- .idea/vcs.xml | 6 ++ .../gfxlab/graphics3d/solids/Ball.java | 68 ++++++++++--------- 2 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/xyz/marsavic/gfxlab/graphics3d/solids/Ball.java b/src/xyz/marsavic/gfxlab/graphics3d/solids/Ball.java index 789588b..89f1bf4 100644 --- a/src/xyz/marsavic/gfxlab/graphics3d/solids/Ball.java +++ b/src/xyz/marsavic/gfxlab/graphics3d/solids/Ball.java @@ -1,79 +1,83 @@ package xyz.marsavic.gfxlab.graphics3d.solids; -import xyz.marsavic.geometry.Vector; import xyz.marsavic.gfxlab.Vec3; import xyz.marsavic.gfxlab.graphics3d.Hit; import xyz.marsavic.gfxlab.graphics3d.Ray; import xyz.marsavic.gfxlab.graphics3d.Solid; -import xyz.marsavic.utils.Numeric; public class Ball implements Solid { - + private final Vec3 c; private final double r; - + // transient private final double rSqr; - - + private Ball(Vec3 c, double r) { this.c = c; this.r = r; rSqr = r * r; } - - + + public static Ball cr(Vec3 c, double r) { return new Ball(c, r); } - - + + public Vec3 c() { return c; } - - + + public double r() { return r; } - - - + + + @Override public HitBall firstHit(Ray ray, double afterTime) { - Vec3 e = c().sub(ray.p()); // Vector from the ray origin to the ball center - - double dSqr = ray.d().lengthSquared(); - double l = e.dot(ray.d()) / dSqr; - double mSqr = l * l - (e.lengthSquared() - rSqr) / dSqr; - - if (mSqr > 0) { - double m = Math.sqrt(mSqr); - if (l - m > afterTime) return new HitBall(ray, l - m); - if (l + m > afterTime) return new HitBall(ray, l + m); + // U nasoj jednacini At^2 + Bt + C = 0, gde je t vreme kada zrak pogadja dve tacke sfere + // diskriminanta ce nam dati da li trazeno t postoji i da li postoje 1 ili 2, ako postoje 2, + // iz diskriminante mozemo dobiti i njihove udaljenosti. + // Za sferu (x-xc)^2 + (y-yc)^2 + (z-zc)^2 = r^2 i pravu (x,y,z) = (x0,y0,z0) + t(a,b,c) + // (a,b,c) je ray.d(), a x0,y0,z0 je ray.p(), dok je (xc,yc,zc) centar sfere i r poluprecnik. + double A = ray.d().lengthSquared(), B = 2*ray.d().dot(ray.p().sub(c)), C = ray.p().sub(c).lengthSquared() - rSqr; + // A = a^2+b^2+c^2, B = 2(a(x0-xc)+b(y0-yc)+c(z0-zc)), C = (x0-xc)^2+(y0-yc)^2+(z0-zc)^2-r^2 + double D = B*B - 4*A*C; + if (D > 0) { + double rootD = Math.sqrt(D); + // t = (-B+-sqrt(D))/2A + double tSmall = (-B-rootD)/(2*A); + if (afterTime < tSmall) + return new HitBall(ray, tSmall); + double tBig = (-B+rootD)/(2*A); + if (afterTime < tBig) + return new HitBall(ray, tBig); } return null; } - - + + class HitBall extends Hit.RayT { - + protected HitBall(Ray ray, double t) { super(ray, t); } - + @Override public Vec3 n() { return ray().at(t()).sub(c()); } - + @Override public Vec3 n_() { return n().div(r); } - + } - + }