private static boolean raysEquivalent(Ray ray1, Ray ray2) { Vector3d dir1 = new Vector3d(ray1.direction); Vector3d dir2 = new Vector3d(ray2.direction); dir1.normalize(); dir2.normalize(); dir1.sub(dir2); return ray1.origin.dist(ray2.origin) < 1e-6 && dir1.len() < 1e-6; }
public static void main(String args[]) { Vector3d viewPoint = new Vector3d(1, 0.5, 2); Vector3d viewDir = new Vector3d(15.23, -1.854, 65.221); viewDir.normalize(); Vector3d viewUp = new Vector3d(1, 0, 0); OrthographicCamera orthoCam = new OrthographicCamera(); orthoCam.setViewPoint(viewPoint); orthoCam.setViewDir(viewDir); orthoCam.setViewUp(viewUp); PerspectiveCamera perspectiveCam = new PerspectiveCamera(); perspectiveCam.setViewPoint(viewPoint); perspectiveCam.setViewDir(viewDir); perspectiveCam.setViewUp(viewUp); float u = 0.37123f; float v = 0.11343f; Ray correctRay0 = new Ray( new Vector3d(0.6235493799051484, 0.36878515466141304, 2.084176425089877), new Vector3d(0.22730915261287413, -0.027671120744863338, 0.9734294315537928)); orthoCam.testGetRay(correctRay0, u, v); Ray correctRay1 = new Ray( new Vector3d(1.0, 0.5, 2.0), new Vector3d(-0.13811656557506483, -0.14714072701594028, 0.9794250460177998)); perspectiveCam.testGetRay(correctRay1, u, v); u = 0.00234f; v = 0.9832f; Ray correctRay2 = new Ray( new Vector3d(1.4705511166404994, 0.005661926354425948, 1.8760675810709173), new Vector3d(0.22730915261287413, -0.027671120744863338, 0.9734294315537928)); orthoCam.testGetRay(correctRay2, u, v); Ray correctRay3 = new Ray( new Vector3d(1.0, 0.5, 2.0), new Vector3d(0.5734153111840217, -0.4289226336993767, 0.698011644029039)); perspectiveCam.testGetRay(correctRay3, u, v); u = 0.2345f; v = 0.78201f; Ray correctRay4 = new Ray( new Vector3d(1.2746277432055346, 0.2364287075632546, 1.928378256923414), new Vector3d(0.22730915261287413, -0.027671120744863338, 0.9734294315537928)); orthoCam.testGetRay(correctRay4, u, v); Ray correctRay5 = new Ray( new Vector3d(1.0, 0.5, 2.0), new Vector3d(0.46805451959738786, -0.27158260116709737, 0.8409327306198586)); perspectiveCam.testGetRay(correctRay5, u, v); u = 0.55523f; v = 0.12555f; Ray correctRay6 = new Ray( new Vector3d(0.635352111386452, 0.552789156075998, 2.0866509013806787), new Vector3d(0.22730915261287413, -0.027671120744863338, 0.9734294315537928)); orthoCam.testGetRay(correctRay6, u, v); Ray correctRay7 = new Ray( new Vector3d(1.0, 0.5, 2.0), new Vector3d(-0.12844581009091482, 0.02349159814594461, 0.991438257627089)); perspectiveCam.testGetRay(correctRay7, u, v); }
@Override public void getColor(float u, float v, Color outColor) { // TODO A4 // get our position if sphere is at 0, radius 1 (all that matters is ratios) Vector3d pt = getPositionFromUV(u, v); // create TBN inverse matrix Vector3d normal = (new Vector3d(pt.x, pt.y, pt.z)).normalize(); Vector3d tangent; if (u < .25 || (u > .5 && u < .75)) { tangent = (new Vector3d(1 / pt.x, 0, -1 / pt.z)).normalize(); } else { tangent = (new Vector3d(-1 / pt.x, 0, 1 / pt.z)).normalize(); } Vector3d bitangent = (normal.clone().cross(tangent.clone())).normalize(); Matrix3d invTBN = (new Matrix3d( tangent.x, bitangent.x, normal.x, tangent.y, bitangent.y, normal.y, tangent.z, bitangent.z, normal.z)) .invert(); // ~-- The rest of this function calculates the new normal --~ Vector3d newNormal = new Vector3d(); // first determine distance to closest disk center float divSize = (float) (1.0 / resolution); // -calculate column float modU = u % divSize; float closestColumn = (u - modU) / divSize; if (modU > divSize / 2) { closestColumn++; } // -calculate row float modV = v % divSize; float closestRow = (v - modV) / divSize; if (modV > divSize / 2) { closestRow++; } // -calculate distance float centerX = closestColumn * divSize; float centerY = closestRow * divSize; double distanceToCenter = Math.sqrt(Math.pow((centerX - u), 2) + Math.pow((centerY - v), 2)); // If we are on disk, use normal from disk center // (the following formula ensures a bumpRadius of 0.5 is tangent circles, and >=1 is full // overlap) double diskRadius = (divSize / 2) * (Math.sqrt(2 * bumpRadius)); if (distanceToCenter <= diskRadius) { Vector3d diskNormal = getPositionFromUV(centerX, centerY).normalize(); newNormal = multByMatrix(diskNormal, invTBN).normalize(); } // if not on disk, use position normalized as normal else { newNormal = multByMatrix(normal, invTBN).normalize(); } // Convert from [-1,1] to [0,1] to [0, 255] Vector3d converted = new Vector3d(); converted.setMultiple(0.5, newNormal.clone().normalize()); converted.add(0.5); Colord outColorAccurate = new Colord(converted); outColor.set(outColorAccurate); }
/** * Tests this surface for intersection with ray. If an intersection is found record is filled out * with the information about the intersection and the method returns true. It returns false * otherwise and the information in outRecord is not modified. * * @param outRecord the output IntersectionRecord * @param ray the ray to intersect * @return true if the surface intersects the ray */ public boolean intersect(IntersectionRecord outRecord, Ray rayIn) { // TODO#A2: fill in this function. Vector3d p = rayIn.origin.clone().sub(center); Vector3d d = rayIn.direction.clone(); double discr = Math.pow(d.dot(p), 2) - (d.dot(d)) * (p.dot(p) - Math.pow(radius, 2)); if (discr >= 0) { double tPlus = (-d.dot(p) + Math.sqrt(discr)) / d.dot(d); double tMinus = (-d.dot(p) - Math.sqrt(discr)) / d.dot(d); double t = Math.min(tPlus, tMinus); if (t > rayIn.end || t < rayIn.start) return false; Vector3d intersect = new Vector3d(); rayIn.evaluate(intersect, t); outRecord.location.set(intersect); Vector3d normal = intersect.clone().sub(center).normalize(); outRecord.normal.set(normal); outRecord.t = t; outRecord.surface = this; return true; } return false; }