Created
June 24, 2017 23:07
-
-
Save robertleeplummerjr/18b3a9636845d112237da800950929ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function round(a) { | |
| return Math.floor(a + 0.5); | |
| }; | |
| function vectorDotProduct(V1x, V1y, V1z, V2x, V2y, V2z) { | |
| return (V1x * V2x) + (V1y * V2y) + (V1z * V2z); | |
| }; | |
| function unitVectorX(Vx, Vy, Vz) { | |
| var magnitude = Math.sqrt((Vx * Vx) + (Vy * Vy) + (Vz * Vz)); | |
| var div = 1.0 / magnitude; | |
| return div * Vx; | |
| }; | |
| function unitVectorY(Vx, Vy, Vz) { | |
| var magnitude = Math.sqrt((Vx * Vx) + (Vy * Vy) + (Vz * Vz)); | |
| var div = 1.0 / magnitude; | |
| return div * Vy; | |
| }; | |
| function unitVectorZ(Vx, Vy, Vz) { | |
| var magnitude = Math.sqrt((Vx * Vx) + (Vy * Vy) + (Vz * Vz)); | |
| var div = 1.0 / magnitude; | |
| return div * Vz; | |
| }; | |
| function sphereNormalX(Sx, Sy, Sz, radius, Px, Py, Pz) { | |
| var SPx = Px - Sx; | |
| var SPy = Py - Sy; | |
| var SPz = Pz - Sz; | |
| var magnitude = (SPx * SPx) + (SPy * SPy) + (SPz * SPz); | |
| var div = this.constants.INFINITY; | |
| if (magnitude > 0) | |
| div = 1.0 / magnitude; | |
| return div * SPx; | |
| }; | |
| function sphereNormalY(Sx, Sy, Sz, radius, Px, Py, Pz) { | |
| var SPx = Px - Sx; | |
| var SPy = Py - Sy; | |
| var SPz = Pz - Sz; | |
| var magnitude = (SPx * SPx) + (SPy * SPy) + (SPz * SPz); | |
| var div = this.constants.INFINITY; | |
| if (magnitude > 0) | |
| div = 1.0 / magnitude; | |
| return div * SPy; | |
| }; | |
| function sphereNormalZ(Sx, Sy, Sz, radius, Px, Py, Pz) { | |
| var SPx = Px - Sx; | |
| var SPy = Py - Sy; | |
| var SPz = Pz - Sz; | |
| var magnitude = (SPx * SPx) + (SPy * SPy) + (SPz * SPz); | |
| var div = this.constants.INFINITY; | |
| if (magnitude > 0) | |
| div = 1.0 / magnitude; | |
| return div * SPz; | |
| }; | |
| function vectorReflectX(Vx, Vy, Vz, Nx, Ny, Nz) { | |
| var V1x = ((Vx * Nx) + (Vy * Ny) + (Vz * Nz)) * Nx; | |
| return (V1x * 2) - Vx; | |
| }; | |
| function vectorReflectY(Vx, Vy, Vz, Nx, Ny, Nz) { | |
| var V1y = ((Vx * Nx) + (Vy * Ny) + (Vz * Nz)) * Ny; | |
| return (V1y * 2) - Vy; | |
| }; | |
| function vectorReflectZ(Vx, Vy, Vz, Nx, Ny, Nz) { | |
| var V1z = ((Vx * Nx) + (Vy * Ny) + (Vz * Nz)) * Nz; | |
| return (V1z * 2) - Vz; | |
| }; | |
| function sphereIntersectionDistance(Sx, Sy, Sz, radius, Ex, Ey, Ez, Vx, Vy, Vz) { | |
| var EOx = Sx - Ex; | |
| var EOy = Sy - Ey; | |
| var EOz = Sz - Ez; | |
| var v = (EOx * Vx) + (EOy * Vy) + (EOz * Vz); | |
| var discriminant = (radius * radius) - | |
| ((EOx * EOx) + (EOy * EOy) + (EOz * EOz)) + | |
| (v * v); | |
| if (discriminant < 0) { | |
| return this.constants.INFINITY; | |
| } else { | |
| return v - Math.sqrt(discriminant); | |
| } | |
| }; | |
| var fn = function fn(camera, lights, things, eyeV, rightV, upV, halfHeight, halfWidth, pixelHeight, pixelWidth, lambertianReflectance, specularReflection) { | |
| var x = this.thread.x; | |
| var y = this.thread.y; | |
| var rayPx = camera[0]; | |
| var rayPy = camera[1]; | |
| var rayPz = camera[2]; | |
| var xCompVx = ((x * pixelWidth) - halfWidth) * rightV[0]; | |
| var xCompVy = ((x * pixelWidth) - halfWidth) * rightV[1]; | |
| var xCompVz = ((x * pixelWidth) - halfWidth) * rightV[2]; | |
| var yCompVx = ((y * pixelHeight) - halfHeight) * upV[0]; | |
| var yCompVy = ((y * pixelHeight) - halfHeight) * upV[1]; | |
| var yCompVz = ((y * pixelHeight) - halfHeight) * upV[2]; | |
| var sumVx = eyeV[0] + xCompVx + yCompVx; | |
| var sumVy = eyeV[1] + xCompVy + yCompVy; | |
| var sumVz = eyeV[2] + xCompVz + yCompVz; | |
| var rayVx = unitVectorX(sumVx, sumVy, sumVz); | |
| var rayVy = unitVectorY(sumVx, sumVy, sumVz); | |
| var rayVz = unitVectorZ(sumVx, sumVy, sumVz); | |
| var closest = this.constants.THINGSCOUNT; | |
| var closestDistance = this.constants.INFINITY; | |
| for (var i = 0; i < this.constants.THINGSCOUNT; i++) { | |
| var distance = sphereIntersectionDistance(things[i][9], things[i][10], things[i][11], things[i][12], rayPx, rayPy, rayPz, rayVx, rayVy, rayVz); | |
| if (distance < closestDistance) { | |
| closest = i; | |
| closestDistance = distance; | |
| } | |
| } | |
| if (closestDistance < this.constants.INFINITY) { | |
| var px = rayPx + rayVx * closestDistance; | |
| var py = rayPy + rayVy * closestDistance; | |
| var pz = rayPz + rayVz * closestDistance; | |
| var sx = things[closest][9]; | |
| var sy = things[closest][10]; | |
| var sz = things[closest][11]; | |
| var sRadius = things[closest][12]; | |
| var snVx = sphereNormalX(sx, sy, sz, sRadius, px, py, pz); | |
| var snVy = sphereNormalY(sx, sy, sz, sRadius, px, py, pz); | |
| var snVz = sphereNormalZ(sx, sy, sz, sRadius, px, py, pz); | |
| var sRed = things[closest][2]; | |
| var sGreen = things[closest][3]; | |
| var sBlue = things[closest][4]; | |
| var ambient = things[closest][7]; | |
| var lambert = things[closest][6]; | |
| var lambertAmount = 0; | |
| if (lambertianReflectance > 0 && lambert > 0) { | |
| for (var i = 0; i < this.constants.LIGHTSCOUNT; i++) { | |
| var LPx = px - lights[i][0]; | |
| var LPy = py - lights[i][1]; | |
| var LPz = pz - lights[i][2]; | |
| var uLPx = unitVectorX(LPx, LPy, LPz); | |
| var uLPy = unitVectorY(LPx, LPy, LPz); | |
| var uLPz = unitVectorZ(LPx, LPy, LPz); | |
| var closestDistance_1 = this.constants.INFINITY; | |
| for (var j = 0; j < this.constants.THINGSCOUNT; j++) { | |
| var distance = this.constants.INFINITY; | |
| var EOx = things[j][9] - px; | |
| var EOy = things[j][10] - py; | |
| var EOz = things[j][11] - pz; | |
| var v = (EOx * uLPx) + (EOy * uLPy) + (EOz * uLPz); | |
| var radius = things[j][12]; | |
| var discriminant = (radius * radius) - | |
| ((EOx * EOx) + (EOy * EOy) + (EOz * EOz)) + | |
| (v * v); | |
| if (discriminant >= 0) { | |
| distance = v - Math.sqrt(discriminant); | |
| } | |
| if (distance < closestDistance_1) { | |
| closestDistance_1 = distance; | |
| } | |
| } | |
| if (closestDistance_1 > -0.005) { | |
| var PLx = -LPx; | |
| var PLy = -LPy; | |
| var PLz = -LPz; | |
| var uPLx = unitVectorX(PLx, PLy, PLz); | |
| var uPLy = unitVectorY(PLx, PLy, PLz); | |
| var uPLz = unitVectorZ(PLx, PLy, PLz); | |
| var contribution = vectorDotProduct(uPLx, uPLy, uPLz, snVx, snVy, snVz); | |
| if (contribution > 0) | |
| lambertAmount += contribution; | |
| } | |
| } | |
| } | |
| if (lambertianReflectance > 0) { | |
| lambertAmount = Math.min(1, lambertAmount); | |
| } | |
| var specular = things[closest][5]; | |
| var cVx = 0; | |
| var cVy = 0; | |
| var cVz = 0; | |
| if (specularReflection > 0 && specular > 0) { | |
| var rRayPx = px; | |
| var rRayPy = py; | |
| var rRayPz = pz; | |
| var rRayVx = vectorReflectX(rayVx, rayVy, rayVz, snVx, snVy, snVz); | |
| var rRayVy = vectorReflectY(rayVx, rayVy, rayVz, snVx, snVy, snVz); | |
| var rRayVz = vectorReflectZ(rayVx, rayVy, rayVz, snVx, snVy, snVz); | |
| var closest_1 = this.constants.THINGSCOUNT; | |
| var closestDistance_2 = this.constants.INFINITY; | |
| for (var i = 0; i < this.constants.THINGSCOUNT; i++) { | |
| var distance = sphereIntersectionDistance(things[i][9], things[i][10], things[i][11], things[i][12], rRayPx, rRayPy, rRayPz, rRayVx, rRayVy, rRayVz); | |
| if (distance < closestDistance_2) { | |
| closest_1 = i; | |
| closestDistance_2 = distance; | |
| } | |
| } | |
| var reflectedRed = 1; | |
| var reflectedGreen = 1; | |
| var reflectedBlue = 1; | |
| if (closestDistance_2 < this.constants.INFINITY) { | |
| var px_1 = rRayPx + rRayVx * closestDistance_2; | |
| var py_1 = rRayPy + rRayVy * closestDistance_2; | |
| var pz_1 = rRayPz + rRayVz * closestDistance_2; | |
| var sx_1 = things[closest_1][9]; | |
| var sy_1 = things[closest_1][10]; | |
| var sz_1 = things[closest_1][11]; | |
| var sRadius_1 = things[closest_1][12]; | |
| var snVx_1 = sphereNormalX(sx_1, sy_1, sz_1, sRadius_1, px_1, py_1, pz_1); | |
| var snVy_1 = sphereNormalY(sx_1, sy_1, sz_1, sRadius_1, px_1, py_1, pz_1); | |
| var snVz_1 = sphereNormalZ(sx_1, sy_1, sz_1, sRadius_1, px_1, py_1, pz_1); | |
| var rsRed = things[closest_1][2]; | |
| var rsGreen = things[closest_1][3]; | |
| var rsBlue = things[closest_1][4]; | |
| var rambient = things[closest_1][7]; | |
| var rlambert = things[closest_1][6]; | |
| var rlambertAmount = 0; | |
| if (lambertianReflectance > 0 && rlambert > 0) { | |
| for (var i = 0; i < this.constants.LIGHTSCOUNT; i++) { | |
| var LPx = px_1 - lights[i][0]; | |
| var LPy = py_1 - lights[i][1]; | |
| var LPz = pz_1 - lights[i][2]; | |
| var uLPx = unitVectorX(LPx, LPy, LPz); | |
| var uLPy = unitVectorY(LPx, LPy, LPz); | |
| var uLPz = unitVectorZ(LPx, LPy, LPz); | |
| var closestDistance_3 = this.constants.INFINITY; | |
| for (var j = 0; j < this.constants.THINGSCOUNT; j++) { | |
| var distance = this.constants.INFINITY; | |
| var EOx = things[j][9] - px_1; | |
| var EOy = things[j][10] - py_1; | |
| var EOz = things[j][11] - pz_1; | |
| var v = (EOx * uLPx) + (EOy * uLPy) + (EOz * uLPz); | |
| var radius = things[j][12]; | |
| var discriminant = (radius * radius) - | |
| ((EOx * EOx) + (EOy * EOy) + (EOz * EOz)) + | |
| (v * v); | |
| if (discriminant >= 0) { | |
| distance = v - Math.sqrt(discriminant); | |
| } | |
| if (distance < closestDistance_3) { | |
| closestDistance_3 = distance; | |
| } | |
| } | |
| if (closestDistance_3 > -0.005) { | |
| var PLx = -LPx; | |
| var PLy = -LPy; | |
| var PLz = -LPz; | |
| var uPLx = unitVectorX(PLx, PLy, PLz); | |
| var uPLy = unitVectorY(PLx, PLy, PLz); | |
| var uPLz = unitVectorZ(PLx, PLy, PLz); | |
| var contribution = vectorDotProduct(uPLx, uPLy, uPLz, snVx_1, snVy_1, snVz_1); | |
| if (contribution > 0) | |
| rlambertAmount += contribution; | |
| } | |
| } | |
| } | |
| if (lambertianReflectance > 0) | |
| rlambertAmount = Math.min(1, rlambertAmount); | |
| reflectedRed = (rsRed * rlambertAmount * rlambert) + (rsRed * rambient); | |
| reflectedGreen = (rsGreen * rlambertAmount * rlambert) + (rsGreen * rambient); | |
| reflectedBlue = (rsBlue * rlambertAmount * rlambert) + (rsBlue * rambient); | |
| cVx = cVx + (specular * reflectedRed); | |
| cVy = cVy + (specular * reflectedGreen); | |
| cVz = cVz + (specular * reflectedBlue); | |
| } | |
| } | |
| var red = cVx + (sRed * lambertAmount * lambert) + (sRed * ambient); | |
| var green = cVy + (sGreen * lambertAmount * lambert) + (sGreen * ambient); | |
| var blue = cVz + (sBlue * lambertAmount * lambert) + (sBlue * ambient); | |
| this.color(red, green, blue); | |
| } else { | |
| this.color(0.95, 0.95, 0.95); | |
| } | |
| }.bind(this); | |
| return function(camera, lights, things, eyeV, rightV, upV, halfHeight, halfWidth, pixelHeight, pixelWidth, lambertianReflectance, specularReflection) { | |
| var ret = new Array(1); | |
| for (this.thread.z = 0; this.thread.z < 1; this.thread.z++) { | |
| ret[this.thread.z] = new Array(600); | |
| for (this.thread.y = 0; this.thread.y < 600; this.thread.y++) { | |
| ret[this.thread.z][this.thread.y] = new Array(600); | |
| for (this.thread.x = 0; this.thread.x < 600; this.thread.x++) { | |
| ret[this.thread.z][this.thread.y][this.thread.x] = fn.apply(this, arguments); | |
| } | |
| } | |
| } | |
| if (this.graphical) { | |
| this._imageData.data.set(this._colorData); | |
| this._canvasCtx.putImageData(this._imageData, 0, 0); | |
| return; | |
| } | |
| if (this.dimensions.length === 1) { | |
| ret = ret[0][0]; | |
| } else if (this.dimensions.length === 2) { | |
| ret = ret[0]; | |
| } | |
| return ret; | |
| console.log(this); | |
| }.bind(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment