You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
5.5 KiB
272 lines
5.5 KiB
"use strict"
|
|
|
|
class Cube{
|
|
|
|
constructor(){
|
|
this.bricks = [];
|
|
for (let x = -1; x < 2; x++){
|
|
for (let y = -1; y < 2; y++){
|
|
for (let z = -1; z < 2; z++){
|
|
this.bricks.push(new Brick(x, y, z));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
show(){
|
|
push();
|
|
if (this.rotation){
|
|
|
|
for (let i = -1; i < 2; i++){
|
|
if (i === this.rotation.index){
|
|
push();
|
|
eval("rotate" + this.rotation.axis.toUpperCase() + "(this.rotation.angle);");
|
|
for (let b of this.getLayer(this.rotation.axis, i)) b.show();
|
|
pop();
|
|
}
|
|
else {
|
|
for (let b of this.getLayer(this.rotation.axis, i)) b.show();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (let b of this.bricks) b.show();
|
|
}
|
|
pop();
|
|
}
|
|
|
|
update(){
|
|
if (this.rotation) this.rotation.update();
|
|
}
|
|
|
|
updatePos(){
|
|
let m = new Matrix();
|
|
m.rotate(this.rotation.angle);
|
|
let o = other(this.rotation.axis),
|
|
bricks = [],
|
|
fields = [],
|
|
resultBricks = [], iBricks = 0, pBricks,
|
|
resultFields = [], iFields = 0, pFields;
|
|
|
|
for (let b of this.getLayer(this.rotation.axis, this.rotation.index)){
|
|
eval("bricks.push({x: b.pos." + o[0] + ", y: b.pos." + o[1] + "});");
|
|
for (let f of b.fields){
|
|
for (let p of f.points){
|
|
eval("fields.push({x: p." + o[0] + ", y: p." + o[1] + "});");
|
|
}
|
|
}
|
|
}
|
|
// transform points
|
|
while(pBricks = bricks[iBricks++]) resultBricks.push(m.applyToPoint(pBricks));
|
|
while(pFields = fields[iFields++]) resultFields.push(m.applyToPoint(pFields));
|
|
|
|
iBricks = 0, iFields = 0;
|
|
|
|
for (let b of this.getLayer(this.rotation.axis, this.rotation.index)){
|
|
let p = resultBricks[iBricks];
|
|
eval("b.pos." + o[0] + " = p.x;");
|
|
eval("b.pos." + o[1] + " = p.y;");
|
|
iBricks++;
|
|
for (let f of b.fields){
|
|
for (let pt of f.points){
|
|
let pf = resultFields[iFields];
|
|
eval("pt." + o[0] + " = pf.x;");
|
|
eval("pt." + o[1] + " = pf.y;");
|
|
iFields++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
getLayer(axis, index){
|
|
let bricks = [];
|
|
for (let b of this.bricks){
|
|
if (eval("b.pos." + axis) === index){
|
|
bricks.push(b);
|
|
}
|
|
}
|
|
return bricks;
|
|
}
|
|
|
|
rotate(axis, index, dir, v){
|
|
if (!this.rotation)
|
|
this.rotation = new Rotation(axis, index, dir, v, () => {
|
|
cube.updatePos();
|
|
cube.rotation = null;
|
|
});
|
|
}
|
|
|
|
scramble(count){
|
|
let cube = this;
|
|
if (count === 0)
|
|
this.rotation = null;
|
|
else
|
|
this.rotation = new Rotation(random(["x", "y", "z"]), random([-1, 1]), random([-1, 1]), PI / 32, () => {
|
|
cube.updatePos();
|
|
cube.scramble(count - 1);
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
function other(axis){
|
|
switch(axis){
|
|
case "x":
|
|
return ["y", "z"];
|
|
case "y":
|
|
return ["z", "x"];
|
|
case "z":
|
|
return ["x", "y"];
|
|
}
|
|
}
|
|
|
|
class Brick{
|
|
|
|
constructor(x, y, z){
|
|
this.pos = createVector(x, y, z);
|
|
this.size = 85;
|
|
this.createFields();
|
|
}
|
|
|
|
show(){
|
|
this.pos.mult(this.size);
|
|
push();
|
|
translate(this.pos.x, this.pos.y, this.pos.z);
|
|
for (let f of this.fields) f.show();
|
|
pop();
|
|
this.pos.div(this.size);
|
|
}
|
|
|
|
createFields(){
|
|
this.fields = [];
|
|
|
|
let sides = [[],[],[],[],[],[]];
|
|
let c = [
|
|
"#F00",
|
|
"#F90",
|
|
"#FFF",
|
|
"#FF0",
|
|
"#00F",
|
|
"#0F0",
|
|
"#000"
|
|
];
|
|
for (let x = -1; x < 2; x++){
|
|
for (let y = -1; y < 2; y++){
|
|
for (let z = -1; z < 2; z++){
|
|
let arr = [];
|
|
if (x > 0 && y && z){
|
|
if (this.pos.x > 0) arr.push({i: 0, colored: true});
|
|
else arr.push({i: 0});
|
|
}
|
|
if (x < 0 && y && z){
|
|
if (this.pos.x < 0) arr.push({i: 1, colored: true});
|
|
else arr.push({i: 1});
|
|
}
|
|
if (y > 0 && x && z){
|
|
if (this.pos.y > 0) arr.push({i: 2, colored: true});
|
|
else arr.push({i: 2});
|
|
}
|
|
if (y < 0 && x && z){
|
|
if (this.pos.y < 0) arr.push({i: 3, colored: true});
|
|
else arr.push({i: 3});
|
|
}
|
|
if (z > 0 && x && y){
|
|
if (this.pos.z > 0) arr.push({i: 4, colored: true});
|
|
else arr.push({i: 4});
|
|
}
|
|
if (z < 0 && x && y){
|
|
if (this.pos.z < 0) arr.push({i: 5, colored: true});
|
|
else arr.push({i: 5});
|
|
}
|
|
for (let a of arr){
|
|
sides[a.i].push({p: createVector(x, y, z), colored: a.colored});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let s of sides){
|
|
let points = [];
|
|
for (let a of s) points.push(a.p);
|
|
let color = s[0].colored ? c[sides.indexOf(s)] : c[6];
|
|
this.fields.push(new Field(points, color, this.size));
|
|
}
|
|
}
|
|
|
|
hasColor(c){
|
|
for (let f of this.fields){
|
|
if (f.colorEquals(c)){
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
get isEdge(){
|
|
return this.coloredCount === 2;
|
|
}
|
|
|
|
get isCorner(){
|
|
return this.coloredCount === 3;
|
|
}
|
|
|
|
get isFlat(){
|
|
return this.coloredCount === 1;
|
|
}
|
|
|
|
get coloredCount(){
|
|
let count = 0;
|
|
for (let f of this.fields){
|
|
if (!f.colorEquals("#000")) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
}
|
|
|
|
class Field{
|
|
|
|
constructor(points, c, size){
|
|
//relative to brick
|
|
this.color = {
|
|
light: color(c),
|
|
dark: dark(color(c), 0.4)
|
|
};
|
|
this.bSize = size;
|
|
this.size = size * 0.95;
|
|
this.points = points;
|
|
}
|
|
|
|
show(){
|
|
for (let p of this.points) p.mult(this.size / 2);
|
|
let p = this.points;
|
|
|
|
if (this.dark) fill(this.color.dark);
|
|
else fill(this.color.light);
|
|
strokeWeight(8);
|
|
stroke(0);
|
|
beginShape();
|
|
vertex(p[0].x, p[0].y, p[0].z);
|
|
vertex(p[2].x, p[2].y, p[2].z);
|
|
vertex(p[3].x, p[3].y, p[3].z);
|
|
vertex(p[1].x, p[1].y, p[1].z);
|
|
endShape(CLOSE);
|
|
|
|
for (let p of this.points) p.div(this.size / 2);
|
|
}
|
|
|
|
colorEquals(c){
|
|
let equal = true;
|
|
for (let i = 0; i < 3; i++){
|
|
if (this.color.light.levels[i] !== color(c).levels[i]){
|
|
equal = false;
|
|
}
|
|
}
|
|
return equal;
|
|
}
|
|
|
|
}
|
|
|
|
function dark(c, val){
|
|
return color(red(c) * val, green(c) * val, blue(c) * val);
|
|
} |