xxxxxxxxxx
208
class Player {
constructor(sc) {
this.sc = sc;
this.thresh = 1e-7;
this.pos = createVector(1, 0, 0);
if (abs(this.pos.mag() - 1.0) > this.thresh) {
throw ("position vector no bueno.");
}
this.ori = createVector(0, -1, 0);
this.r = 0.5;
}
show() {
push();
translate(width / 2, height / 2);
translate(this.sc * this.pos.x, this.sc * this.pos.y);
fill(0, 255, 0);
noStroke();
ellipse(0, 0, 10 * (1 - this.pos.z), 10 * (1 - this.pos.z));
stroke(2);
line(0, 0, this.ori.x * this.sc, this.ori.y * this.sc);
pop();
}
moveForw(stepSize) {
let pos = this.pos.copy();
let ori = this.ori.copy();
let tmp = this.rotTowardVec(pos, ori, stepSize);
this.pos = tmp[0].normalize();
this.ori = tmp[1].normalize();
}
moveBack(stepSize) {
let pos = this.pos.copy();
let ori = this.ori.copy().mult(-1);
let tmp = this.rotTowardVec(pos, ori, stepSize);
this.pos = tmp[0].normalize();
this.ori = tmp[1].mult(-1).normalize();
}
rotLeft(stepSize) {
let pos = this.pos.copy();
let ori = this.ori.copy();
let left = p5.Vector.cross(pos, ori);
let tmp = this.rotTowardVec(ori, left, stepSize);
this.ori = tmp[0].normalize();
}
rotRight(stepSize) {
let pos = this.pos.copy();
let ori = this.ori.copy();
let right = p5.Vector.cross(pos, ori).mult(-1);
let tmp = this.rotTowardVec(ori, right, stepSize);
this.ori = tmp[0].normalize();
}
flip() {
this.ori.mult(-1);
}
rotTowardVec(pos, ori, theta) {
const u = p5.Vector.cross(pos, ori);
//let tmpVec = p5.Vector.random3D();
//const u = this.findOrthVec(pos, ori, tmpVec);
const M1 = [
[pos.x, ori.x, u.x],
[pos.y, ori.y, u.y],
[pos.z, ori.z, u.z]
];
const M2 = [
[cos(theta), -sin(theta), 0],
[sin(theta), cos(theta), 0],
[0, 0, 1]
];
//const R = this.MatMul2T(this.MatMul(M1, M2), M1);
//let new_pos = (this.MatVec(R, [pos.x, pos.y, pos.z]));
//new_pos = createVector(new_pos[0], new_pos[1], new_pos[2])
let new_pos = math.multiply(M1,math.multiply(M2,math.multiply(math.transpose(M1),[[pos.x], [pos.y], [pos.z]])));
new_pos = createVector(new_pos[0][0],new_pos[1][0],new_pos[2][0])
return [new_pos, p5.Vector.cross(u, new_pos)];
//return [new_pos, this.findOrthVec(u, new_pos, ori)];
}
MatMul(M1, M2) {
const m = M1.length;
const p = M2.length;
if (M1[0].length != p) throw ("Matrix dimension mismatch");
const n = M2[0].length;
let M3 = [];
for (let mi = 0; mi < m; mi++) {
let M3_tmp = [];
for (let ni = 0; ni < n; ni++) {
let tmp = 0;
for (let pi = 0; pi < p; pi++) {
tmp += M1[mi][pi] * M2[pi][ni]
}
M3_tmp.push(tmp);
}
M3.push(M3_tmp);
}
return M3
}
MatVec(M1, V2) {
const m = M1.length;
const p = V2.length;
if (M1[0].length != p) throw ("Matrix dimension mismatch");
let V3 = [];
for (let mi = 0; mi < m; mi++) {
let tmp = 0;
for (let pi = 0; pi < p; pi++) {
tmp += M1[mi][pi] * V2[pi]
}
V3.push(tmp);
}
return V3
}
MatMul2T(M1, M2) {
const m = M1.length;
const n = M2.length;
const p = M2[0].length;
if (M1[0].length != p) throw ("Matrix dimension mismatch");
let M3 = [];
for (let mi = 0; mi < m; mi++) {
let M3_tmp = [];
for (let ni = 0; ni < n; ni++) {
let tmp = 0;
for (let pi = 0; pi < p; pi++) {
tmp += M1[mi][pi] * M2[ni][pi]
}
M3_tmp.push(tmp);
}
M3.push(M3_tmp);
}
return M3
}
rayMarch(pos, direction, objects,depth) {
let d = TWO_PI;
const thresh = 0.001;
for (let ni = 0; ni < objects.length; ni++) {
let tmp_d = objects[ni].signedDistanceToObject(pos);
if (tmp_d < d) {
d = tmp_d;
}
}
if (depth>50){
return (d);
}
if (d < thresh) {
return (d);
} else if (TWO_PI - d < thresh) {
return (d);
} else {
let tmp = this.rotTowardVec(pos, direction, d);
pos = tmp[0].normalize();
direction = tmp[1].normalize();
return (d + this.rayMarch(pos, direction, objects,depth+1));
}
}
findOrthVec(P1, P2, P3) {
const max_its = 10;
let p1 = math.matrix([
[P1.x],
[P1.y],
[P1.z]
]);
let p2 = math.matrix([
[P2.x],
[P2.y],
[P2.z]
]);
let p3 = math.matrix([
[P3.x],
[P3.y],
[P3.z]
]);
let v = math.matrix([
[0],
[0],
[-1]
]);
let S = math.matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 0.5]
]);
for (let ni = 0; ni < max_its; ni++) {
let G = math.transpose(math.concat(p1, p2, p3, 1));
p3 = math.subtract(p3, math.multiply(math.multiply(math.inv(G), S), math.add(math.multiply(G, p3), v)));
}
return createVector(p3.subset(math.index(0, 0)), p3.subset(math.index(1, 0)), p3.subset(math.index(2, 0)))
}
signedDistanceToObject(pos) {
const delta = 0.1;
let C = p5.Vector.sub(this.pos, pos).mag();
let alpha = 2 * asin(C / 2);
if (alpha-this.r<0) {
return (alpha - this.r + TWO_PI - delta);
} else {
return (alpha - this.r);
}
}
}