Skip to content

Instantly share code, notes, and snippets.

@robertleeplummerjr
Created June 24, 2017 23:07
Show Gist options
  • Select an option

  • Save robertleeplummerjr/18b3a9636845d112237da800950929ad to your computer and use it in GitHub Desktop.

Select an option

Save robertleeplummerjr/18b3a9636845d112237da800950929ad to your computer and use it in GitHub Desktop.
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