diff --git a/canvas.js b/canvas.js new file mode 100644 index 0000000..cc7a78a --- /dev/null +++ b/canvas.js @@ -0,0 +1,1313 @@ +#!/bin/node + +let g_y_rotation = Math.PI/4; +let g_x_rotation = Math.PI/4; + +let vertexcount = 0; + +class Axis { + static x = new Axis('x'); + static y = new Axis('y'); + static z = new Axis('z'); + + constructor(name) { + this.name = name; + } +} + +class Rotation { + static x1 = new Rotation('x1'); + static x1i = new Rotation('x1i'); + static x2 = new Rotation('x2'); + static x2i = new Rotation('x2i'); + static x3 = new Rotation('x3'); + static x3i = new Rotation('x3i'); + static y1 = new Rotation('y1'); + static y1i = new Rotation('y1i'); + static y2 = new Rotation('y2'); + static y2i = new Rotation('y2i'); + static y3 = new Rotation('y3'); + static y3i = new Rotation('y3i'); + static z1 = new Rotation('z1'); + static z1i = new Rotation('z1i'); + static z2 = new Rotation('z2'); + static z2i = new Rotation('z2i'); + static z3 = new Rotation('z3'); + static z3i = new Rotation('z3i'); + + constructor(name) { + this.name = name; + } +} + +const turn = (vertices, axis, angle) => { + let coord1_offset = ''; + let coord2_offset = ''; + switch(axis) { + case Axis.x: + coord1_offset = 0; + coord2_offset = 1; + break; + case Axis.y: + coord1_offset = 2; + coord2_offset = 0; + break; + case Axis.z: + coord1_offset = 1; + coord2_offset = 2; + break; + } + for(let i = 0; i*3 < vertices.length; ++i ) { + let coord1 = vertices[3 * i + coord1_offset] * Math.cos(angle) + + vertices[3 * i + coord2_offset] * Math.sin(angle); + let coord2 = vertices[3 * i + coord2_offset] * Math.cos(angle) - + vertices[3 * i + coord1_offset] * Math.sin(angle); + vertices[3 * i + coord1_offset] = coord1; + vertices[3 * i + coord2_offset] = coord2; + } + return vertices; +} + +let Colors = { + blue: [0.0, 0.27, 0.68, 1.0], + green: [0.0, 0.61, 0.28, 1.0], + white: [1.0, 1.0, 1.0, 1.0], + yellow: [1.0, 0.84, 0.0, 1.0], + red: [0.73, 0.0, 0.0, 1.0], + orange: [1.0, 0.35, 0.0, 1.0], + black: [0.0, 0.0, 0.0, 1.0], + }; + +class Cube { + static jjj + constructor(center_pos, width, starting_indices, + front_color, back_color, + bottom_color, top_color, + right_color, left_color) { + const half_width = width / 2; + this.positions = [ + // front face + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + + // back face + -1.0, -1.0, -1.0, + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, -1.0, -1.0, + + // bottom face + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, + + // top face + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + + // right face + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, -1.0, + + // left face + -1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 1.0, -1.0, + ]; + for (let i = 0; i < this.positions.length; ++i) { + this.positions[i] *= half_width; + this.positions[i] += center_pos[i%3]; + } + this.indices = [ + 0, 1, 2, 0, 2, 3, // front + 4, 5, 6, 4, 6, 7, // back + 8, 9, 10, 8, 10, 11, // bottom + 12, 13, 14, 12, 14, 15, // top + 16, 17, 18, 16, 18, 19, // right + 20, 21, 22, 20, 22, 23, // left + ]; + for ( let i = 0; i < this.indices.length; ++i ) { + this.indices[i] += starting_indices; + } + this.colors = []; + this.colors = this.colors.concat( front_color, front_color, front_color, front_color ); + this.colors = this.colors.concat( back_color, back_color, back_color, back_color ); + this.colors = this.colors.concat( bottom_color, bottom_color, bottom_color, bottom_color ); + this.colors = this.colors.concat( top_color, top_color, top_color, top_color ); + this.colors = this.colors.concat( right_color, right_color, right_color, right_color ); + this.colors = this.colors.concat( left_color, left_color, left_color, left_color ); + } + + rotate(axis, angle) { + this.positions = turn( this.positions, axis, angle ); + } + + get_positions() { + return this.positions; + } + + get_trig_indices() { + return this.indices; + } + + get_colors() { + return this.colors; + } + + get_vertices_count() { + return this.positions.length / 3; + } +} + +let rubik = ((width) => { + let positions = []; + let colors = []; + let indices = []; + const createCube = (pos, cols) => { + let cube = new Cube(pos, width, vertexcount, + cols[0], cols[1], cols[2], + cols[3], cols[4], cols[5]); + vertexcount += cube.get_vertices_count(); + positions = positions.concat(cube.get_positions()); + colors = colors.concat(cube.get_colors()); + indices = indices.concat(cube.get_trig_indices()); + return cube; + } + // ----------------------- front face ---------------------------------------------------------- + let front_top_left_cube = createCube([-1.0, 1.0, 1.0], [ + Colors.blue, Colors.black, Colors.black, + Colors.yellow, Colors.black, Colors.orange]); + + let front_top_cube = createCube([0.0, 1.0, 1.0], [ + Colors.blue, Colors.black, Colors.black, + Colors.yellow, Colors.black, Colors.black]); + + let front_top_right_cube = createCube([1.0, 1.0, 1.0], [ + Colors.blue, Colors.black, Colors.black, + Colors.yellow, Colors.red, Colors.black]); + // ----------------------- next row ------------------------------------------------------------ + let front_left_cube = createCube([-1.0, 0.0, 1.0], [ + Colors.blue, Colors.black, Colors.black, + Colors.black, Colors.black, Colors.orange]); + + let front_cube = createCube([0.0, 0.0, 1.0], [ + Colors.blue, Colors.black, Colors.black, + Colors.black, Colors.black, Colors.black]); + + let front_right_cube = createCube([1.0, 0.0, 1.0], [ + Colors.blue, Colors.black, Colors.black, + Colors.black, Colors.red, Colors.black]); + // ----------------------- next row ------------------------------------------------------------ + let front_bottom_left_cube = createCube([-1.0, -1.0, 1.0], [ + Colors.blue, Colors.black, Colors.white, + Colors.black, Colors.black, Colors.orange]); + + let front_bottom_cube = createCube([0.0, -1.0, 1.0], [ + Colors.blue, Colors.black, Colors.white, + Colors.black, Colors.black, Colors.black]); + + let front_bottom_right_cube = createCube([1.0, -1.0, 1.0], [ + Colors.blue, Colors.black, Colors.white, + Colors.black, Colors.red, Colors.black]); + // ----------------------- middle layer -------------------------------------------------------- + let top_left_cube = createCube([-1.0, 1.0, 0.0], [ + Colors.black, Colors.black, Colors.black, + Colors.yellow, Colors.black, Colors.orange]); + + let top_cube = createCube([0.0, 1.0, 0.0], [ + Colors.black, Colors.black, Colors.black, + Colors.yellow, Colors.black, Colors.black]); + + let top_right_cube = createCube([1.0, 1.0, 0.0], [ + Colors.black, Colors.black, Colors.black, + Colors.yellow, Colors.red, Colors.black]); + // ----------------------- next row ------------------------------------------------------------ + let left_cube = createCube([-1.0, 0.0, 0.0], [ + Colors.black, Colors.black, Colors.black, + Colors.black, Colors.black, Colors.orange]); + + let center_cube = createCube([0.0, 0.0, 0.0], [ + Colors.black, Colors.black, Colors.black, + Colors.black, Colors.black, Colors.black]); + + let right_cube = createCube([1.0, 0.0, 0.0], [ + Colors.black, Colors.black, Colors.black, + Colors.black, Colors.red, Colors.black]); + // ----------------------- next row ------------------------------------------------------------ + let bottom_left_cube = createCube([-1.0, -1.0, 0.0], [ + Colors.black, Colors.black, Colors.white, + Colors.black, Colors.black, Colors.orange]); + + let bottom_cube = createCube([0.0, -1.0, 0.0], [ + Colors.black, Colors.black, Colors.white, + Colors.black, Colors.black, Colors.black]); + + let bottom_right_cube = createCube([1.0, -1.0, 0.0], [ + Colors.black, Colors.black, Colors.white, + Colors.black, Colors.red, Colors.black]); + // ----------------------- back face ----------------------------------------------------------- + let back_top_left_cube = createCube([-1.0, 1.0, -1.0], [ + Colors.black, Colors.green, Colors.black, + Colors.yellow, Colors.black, Colors.orange]); + + let back_top_cube = createCube([0.0, 1.0, -1.0], [ + Colors.black, Colors.green, Colors.black, + Colors.yellow, Colors.black, Colors.black]); + + let back_top_right_cube = createCube([1.0, 1.0, -1.0], [ + Colors.black, Colors.green, Colors.black, + Colors.yellow, Colors.red, Colors.black]); + // ----------------------- next row ------------------------------------------------------------ + let back_left_cube = createCube([-1.0, 0.0, -1.0], [ + Colors.black, Colors.green, Colors.black, + Colors.black, Colors.black, Colors.orange]); + + let back_cube = createCube([0.0, 0.0, -1.0], [ + Colors.black, Colors.green, Colors.black, + Colors.black, Colors.black, Colors.black]); + + let back_right_cube = createCube([1.0, 0.0, -1.0], [ + Colors.black, Colors.green, Colors.black, + Colors.black, Colors.red, Colors.black]); + // ----------------------- next row ------------------------------------------------------------ + let back_bottom_left_cube = createCube([-1.0, -1.0, -1.0], [ + Colors.black, Colors.green, Colors.white, + Colors.black, Colors.black, Colors.orange]); + + let back_bottom_cube = createCube([0.0, -1.0, -1.0], [ + Colors.black, Colors.green, Colors.white, + Colors.black, Colors.black, Colors.black]); + + let back_bottom_right_cube = createCube([1.0, -1.0, -1.0], [ + Colors.black, Colors.green, Colors.white, + Colors.black, Colors.red, Colors.black]); + + return { + cubes: { + front_top_left: front_top_left_cube, + front_top: front_top_cube, + front_top_right: front_top_right_cube, + front_left: front_left_cube, + front: front_cube, + front_right: front_right_cube, + front_bottom_left: front_bottom_left_cube, + front_bottom: front_bottom_cube, + front_bottom_right: front_bottom_right_cube, + + top_left: top_left_cube, + top: top_cube, + top_right: top_right_cube, + left: left_cube, + center : center_cube, + right: right_cube, + bottom_left: bottom_left_cube, + bottom: bottom_cube, + bottom_right: bottom_right_cube, + + back_top_left: back_top_left_cube, + back_top: back_top_cube, + back_top_right: back_top_right_cube, + back_left: back_left_cube, + back: back_cube, + back_right: back_right_cube, + back_bottom_left: back_bottom_left_cube, + back_bottom: back_bottom_cube, + back_bottom_right: back_bottom_right_cube, + }, + rendering_order: [...Array(27).keys()], + positions: positions, + colors: colors, + indices: indices, + indices_length: indices.length, + updateColors() { + this.colors = []; + this.colors = this.colors.concat(this.cubes.front_top_left.get_colors()); + this.colors = this.colors.concat(this.cubes.front_top.get_colors()); + this.colors = this.colors.concat(this.cubes.front_top_right.get_colors()); + this.colors = this.colors.concat(this.cubes.front_left.get_colors()); + this.colors = this.colors.concat(this.cubes.front.get_colors()); + this.colors = this.colors.concat(this.cubes.front_right.get_colors()); + this.colors = this.colors.concat(this.cubes.front_bottom_left.get_colors()); + this.colors = this.colors.concat(this.cubes.front_bottom.get_colors()); + this.colors = this.colors.concat(this.cubes.front_bottom_right.get_colors()); + this.colors = this.colors.concat(this.cubes.top_left.get_colors()); + this.colors = this.colors.concat(this.cubes.top.get_colors()); + this.colors = this.colors.concat(this.cubes.top_right.get_colors()); + this.colors = this.colors.concat(this.cubes.left.get_colors()); + this.colors = this.colors.concat(this.cubes.center .get_colors()); + this.colors = this.colors.concat(this.cubes.right.get_colors()); + this.colors = this.colors.concat(this.cubes.bottom_left.get_colors()); + this.colors = this.colors.concat(this.cubes.bottom.get_colors()); + this.colors = this.colors.concat(this.cubes.bottom_right.get_colors()); + this.colors = this.colors.concat(this.cubes.back_top_left.get_colors()); + this.colors = this.colors.concat(this.cubes.back_top.get_colors()); + this.colors = this.colors.concat(this.cubes.back_top_right.get_colors()); + this.colors = this.colors.concat(this.cubes.back_left.get_colors()); + this.colors = this.colors.concat(this.cubes.back.get_colors()); + this.colors = this.colors.concat(this.cubes.back_right.get_colors()); + this.colors = this.colors.concat(this.cubes.back_bottom_left.get_colors()); + this.colors = this.colors.concat(this.cubes.back_bottom.get_colors()); + this.colors = this.colors.concat(this.cubes.back_bottom_right.get_colors()); + }, + updatepos() { + this.positions = []; + this.positions = this.positions.concat(this.cubes.front_top_left.get_positions()); + this.positions = this.positions.concat(this.cubes.front_top.get_positions()); + this.positions = this.positions.concat(this.cubes.front_top_right.get_positions()); + this.positions = this.positions.concat(this.cubes.front_left.get_positions()); + this.positions = this.positions.concat(this.cubes.front.get_positions()); + this.positions = this.positions.concat(this.cubes.front_right.get_positions()); + this.positions = this.positions.concat(this.cubes.front_bottom_left.get_positions()); + this.positions = this.positions.concat(this.cubes.front_bottom.get_positions()); + this.positions = this.positions.concat(this.cubes.front_bottom_right.get_positions()); + this.positions = this.positions.concat(this.cubes.top_left.get_positions()); + this.positions = this.positions.concat(this.cubes.top.get_positions()); + this.positions = this.positions.concat(this.cubes.top_right.get_positions()); + this.positions = this.positions.concat(this.cubes.left.get_positions()); + this.positions = this.positions.concat(this.cubes.center .get_positions()); + this.positions = this.positions.concat(this.cubes.right.get_positions()); + this.positions = this.positions.concat(this.cubes.bottom_left.get_positions()); + this.positions = this.positions.concat(this.cubes.bottom.get_positions()); + this.positions = this.positions.concat(this.cubes.bottom_right.get_positions()); + this.positions = this.positions.concat(this.cubes.back_top_left.get_positions()); + this.positions = this.positions.concat(this.cubes.back_top.get_positions()); + this.positions = this.positions.concat(this.cubes.back_top_right.get_positions()); + this.positions = this.positions.concat(this.cubes.back_left.get_positions()); + this.positions = this.positions.concat(this.cubes.back.get_positions()); + this.positions = this.positions.concat(this.cubes.back_right.get_positions()); + this.positions = this.positions.concat(this.cubes.back_bottom_left.get_positions()); + this.positions = this.positions.concat(this.cubes.back_bottom.get_positions()); + this.positions = this.positions.concat(this.cubes.back_bottom_right.get_positions()); + }, + rotate_only(dir) { + switch(dir) { + case Rotation.x1: + this.cubes.front_top_left.rotate(Axis.x, Math.PI / 2); + this.cubes.front_top.rotate(Axis.x, Math.PI / 2); + this.cubes.front_top_right.rotate(Axis.x, Math.PI / 2); + this.cubes.front_left.rotate(Axis.x, Math.PI / 2); + this.cubes.front.rotate(Axis.x, Math.PI / 2); + this.cubes.front_right.rotate(Axis.x, Math.PI / 2); + this.cubes.front_bottom_left.rotate(Axis.x, Math.PI / 2); + this.cubes.front_bottom.rotate(Axis.x, Math.PI / 2); + this.cubes.front_bottom_right.rotate(Axis.x, Math.PI / 2); + + [this.cubes.front_top_right, this.cubes.front_bottom_right, + this.cubes.front_bottom_left, this.cubes.front_top_left,] = + [this.cubes.front_top_left, this.cubes.front_top_right, + this.cubes.front_bottom_right, this.cubes.front_bottom_left]; + + [this.cubes.front_top, this.cubes.front_left, + this.cubes.front_bottom, this.cubes.front_right] = + [this.cubes.front_left, this.cubes.front_bottom, + this.cubes.front_right, this.cubes.front_top]; + + [this.rendering_order[2], this.rendering_order[8], + this.rendering_order[6], this.rendering_order[0],] = + [this.rendering_order[0], this.rendering_order[2], + this.rendering_order[8], this.rendering_order[6]]; + + [this.rendering_order[1], this.rendering_order[3], + this.rendering_order[7], this.rendering_order[6]] = + [this.rendering_order[3], this.rendering_order[7], + this.rendering_order[6], this.rendering_order[1]]; + break; + case Rotation.x1i: + this.cubes.front_top_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_top.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_top_right.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.front.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_right.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_bottom_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_bottom.rotate(Axis.x, -Math.PI / 2); + this.cubes.front_bottom_right.rotate(Axis.x, -Math.PI / 2); + + [this.cubes.front_top_right, this.cubes.front_bottom_right, + this.cubes.front_bottom_left, this.cubes.front_top_left,] = + [this.cubes.front_bottom_right, this.cubes.front_bottom_left, + this.cubes.front_top_left, this.cubes.front_top_right]; + + [this.cubes.front_top, this.cubes.front_left, + this.cubes.front_bottom, this.cubes.front_right] = + [this.cubes.front_right, this.cubes.front_top, + this.cubes.front_left, this.cubes.front_bottom]; + + [this.rendering_order[2], this.rendering_order[8], + this.rendering_order[6], this.rendering_order[0],] = + [this.rendering_order[8], this.rendering_order[6], + this.rendering_order[0], this.rendering_order[2]]; + + [this.rendering_order[1], this.rendering_order[3], + this.rendering_order[7], this.rendering_order[5]] = + [this.rendering_order[5], this.rendering_order[1], + this.rendering_order[3], this.rendering_order[7]]; + break; + case Rotation.x2: + this.cubes.top_left.rotate(Axis.x, Math.PI / 2); + this.cubes.top.rotate(Axis.x, Math.PI / 2); + this.cubes.top_right.rotate(Axis.x, Math.PI / 2); + this.cubes.left.rotate(Axis.x, Math.PI / 2); + this.cubes.center.rotate(Axis.x, Math.PI / 2); + this.cubes.right.rotate(Axis.x, Math.PI / 2); + this.cubes.bottom_left.rotate(Axis.x, Math.PI / 2); + this.cubes.bottom.rotate(Axis.x, Math.PI / 2); + this.cubes.bottom_right.rotate(Axis.x, Math.PI / 2); + + [this.cubes.top_right, this.cubes.bottom_right, + this.cubes.bottom_left, this.cubes.top_left,] = + [this.cubes.top_left, this.cubes.top_right, + this.cubes.bottom_right, this.cubes.bottom_left]; + + [this.cubes.top, this.cubes.left, + this.cubes.bottom, this.cubes.right] = + [this.cubes.left, this.cubes.bottom, + this.cubes.right, this.cubes.top]; + + [this.rendering_order[11], this.rendering_order[17], + this.rendering_order[15], this.rendering_order[9],] = + [this.rendering_order[9], this.rendering_order[11], + this.rendering_order[17], this.rendering_order[15]]; + + [this.rendering_order[10], this.rendering_order[12], + this.rendering_order[16], this.rendering_order[14]] = + [this.rendering_order[12], this.rendering_order[16], + this.rendering_order[14], this.rendering_order[10]]; + break; + case Rotation.x2i: + this.cubes.top_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.top.rotate(Axis.x, -Math.PI / 2); + this.cubes.top_right.rotate(Axis.x, -Math.PI / 2); + this.cubes.left.rotate(Axis.x, -Math.PI / 2); + this.cubes.center.rotate(Axis.x, -Math.PI / 2); + this.cubes.right.rotate(Axis.x, -Math.PI / 2); + this.cubes.bottom_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.bottom.rotate(Axis.x, -Math.PI / 2); + this.cubes.bottom_right.rotate(Axis.x, -Math.PI / 2); + + [this.cubes.top_right, this.cubes.bottom_right, + this.cubes.bottom_left, this.cubes.top_left,] = + [this.cubes.bottom_right, this.cubes.bottom_left, + this.cubes.top_left, this.cubes.top_right]; + + [this.cubes.top, this.cubes.left, + this.cubes.bottom, this.cubes.right] = + [this.cubes.right, this.cubes.top, + this.cubes.left, this.cubes.bottom]; + + [this.rendering_order[11], this.rendering_order[17], + this.rendering_order[15], this.rendering_order[9],] = + [this.rendering_order[9], this.rendering_order[11], + this.rendering_order[17], this.rendering_order[15]]; + + [this.rendering_order[10], this.rendering_order[12], + this.rendering_order[16], this.rendering_order[14]] = + [this.rendering_order[12], this.rendering_order[16], + this.rendering_order[14], this.rendering_order[10]]; + break; + case Rotation.x3: + this.cubes.back_top_left.rotate(Axis.x, Math.PI / 2); + this.cubes.back_top.rotate(Axis.x, Math.PI / 2); + this.cubes.back_top_right.rotate(Axis.x, Math.PI / 2); + this.cubes.back_left.rotate(Axis.x, Math.PI / 2); + this.cubes.back.rotate(Axis.x, Math.PI / 2); + this.cubes.back_right.rotate(Axis.x, Math.PI / 2); + this.cubes.back_bottom_left.rotate(Axis.x, Math.PI / 2); + this.cubes.back_bottom.rotate(Axis.x, Math.PI / 2); + this.cubes.back_bottom_right.rotate(Axis.x, Math.PI / 2); + + [this.cubes.back_top_right, this.cubes.back_bottom_right, + this.cubes.back_bottom_left, this.cubes.back_top_left,] = + [this.cubes.back_top_left, this.cubes.back_top_right, + this.cubes.back_bottom_right, this.cubes.back_bottom_left]; + + [this.cubes.back_top, this.cubes.back_left, + this.cubes.back_bottom, this.cubes.back_right] = + [this.cubes.back_left, this.cubes.back_bottom, + this.cubes.back_right, this.cubes.back_top]; + + [this.rendering_order[20], this.rendering_order[26], + this.rendering_order[24], this.rendering_order[18],] = + [this.rendering_order[18], this.rendering_order[20], + this.rendering_order[26], this.rendering_order[24]]; + + [this.rendering_order[19], this.rendering_order[21], + this.rendering_order[25], this.rendering_order[23]] = + [this.rendering_order[21], this.rendering_order[25], + this.rendering_order[23], this.rendering_order[19]]; + break; + case Rotation.x3i: + this.cubes.back_top_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_top.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_top_right.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.back.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_right.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_bottom_left.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_bottom.rotate(Axis.x, -Math.PI / 2); + this.cubes.back_bottom_right.rotate(Axis.x, -Math.PI / 2); + + [this.cubes.back_top_right, this.cubes.back_bottom_right, + this.cubes.back_bottom_left, this.cubes.back_top_left,] = + [this.cubes.back_bottom_right, this.cubes.back_bottom_left, + this.cubes.back_top_left, this.cubes.back_top_right]; + + [this.cubes.back_top, this.cubes.back_left, + this.cubes.back_bottom, this.cubes.back_right] = + [this.cubes.back_right, this.cubes.back_top, + this.cubes.back_left, this.cubes.back_bottom]; + + [this.rendering_order[20], this.rendering_order[26], + this.rendering_order[24], this.rendering_order[18],] = + [this.rendering_order[18], this.rendering_order[20], + this.rendering_order[26], this.rendering_order[24]]; + + [this.rendering_order[19], this.rendering_order[21], + this.rendering_order[25], this.rendering_order[23]] = + [this.rendering_order[21], this.rendering_order[25], + this.rendering_order[23], this.rendering_order[19]]; + break; + case Rotation.y1: + this.cubes.back_top_right.rotate(Axis.y, Math.PI / 2); + this.cubes.back_top.rotate(Axis.y, Math.PI / 2); + this.cubes.back_top_left.rotate(Axis.y, Math.PI / 2); + this.cubes.top_right.rotate(Axis.y, Math.PI / 2); + this.cubes.top.rotate(Axis.y, Math.PI / 2); + this.cubes.top_left.rotate(Axis.y, Math.PI / 2); + this.cubes.front_top_right.rotate(Axis.y, Math.PI / 2); + this.cubes.front_top.rotate(Axis.y, Math.PI / 2); + this.cubes.front_top_left.rotate(Axis.y, Math.PI / 2); + + [this.cubes.back_top_right, this.cubes.front_top_right, + this.cubes.front_top_left, this.cubes.back_top_left] = + [this.cubes.back_top_left, this.cubes.back_top_right, + this.cubes.front_top_right, this.cubes.front_top_left]; + + [this.cubes.back_top, this.cubes.top_left, + this.cubes.front_top, this.cubes.top_right] = + [this.cubes.top_left, this.cubes.front_top, + this.cubes.top_right, this.cubes.back_top]; + + [this.rendering_order[20], this.rendering_order[2], + this.rendering_order[0], this.rendering_order[18]] = + [this.rendering_order[18], this.rendering_order[20], + this.rendering_order[2], this.rendering_order[0]]; + + [this.rendering_order[19], this.rendering_order[9], + this.rendering_order[1], this.rendering_order[11]] = + [this.rendering_order[9], this.rendering_order[1], + this.rendering_order[11], this.rendering_order[19]]; + break; + case Rotation.y1i: + this.cubes.back_top_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.back_top.rotate(Axis.y, -Math.PI / 2); + this.cubes.back_top_left.rotate(Axis.y, -Math.PI / 2); + this.cubes.top_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.top.rotate(Axis.y, -Math.PI / 2); + this.cubes.top_left.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_top_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_top.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_top_left.rotate(Axis.y, -Math.PI / 2); + + [this.cubes.back_top_right, this.cubes.front_top_right, + this.cubes.front_top_left, this.cubes.back_top_left] = + [this.cubes.front_top_right, this.cubes.front_top_left, + this.cubes.back_top_left, this.cubes.back_top_right]; + + [this.cubes.back_top, this.cubes.top_left, + this.cubes.front_top, this.cubes.top_right] = + [this.cubes.top_right, this.cubes.back_top, + this.cubes.top_left, this.cubes.front_top]; + + [this.rendering_order[20], this.rendering_order[2], + this.rendering_order[0], this.rendering_order[18]] = + [this.rendering_order[2], this.rendering_order[0], + this.rendering_order[18], this.rendering_order[20]]; + + [this.rendering_order[19], this.rendering_order[9], + this.rendering_order[1], this.rendering_order[11]] = + [this.rendering_order[11], this.rendering_order[19], + this.rendering_order[9], this.rendering_order[1]]; + break; + case Rotation.y2: + this.cubes.back_right.rotate(Axis.y, Math.PI / 2); + this.cubes.back.rotate(Axis.y, Math.PI / 2); + this.cubes.back_left.rotate(Axis.y, Math.PI / 2); + this.cubes.right.rotate(Axis.y, Math.PI / 2); + this.cubes.center.rotate(Axis.y, Math.PI / 2); + this.cubes.left.rotate(Axis.y, Math.PI / 2); + this.cubes.front_right.rotate(Axis.y, Math.PI / 2); + this.cubes.front.rotate(Axis.y, Math.PI / 2); + this.cubes.front_left.rotate(Axis.y, Math.PI / 2); + + [this.cubes.back_right, this.cubes.front_right, + this.cubes.front_left, this.cubes.back_left] = + [this.cubes.back_left, this.cubes.back_right, + this.cubes.front_right, this.cubes.front_left]; + + [this.cubes.back, this.cubes.left, + this.cubes.front, this.cubes.right] = + [this.cubes.left, this.cubes.front, + this.cubes.right, this.cubes.back]; + + [this.rendering_order[23], this.rendering_order[5], + this.rendering_order[3], this.rendering_order[21]] = + [this.rendering_order[21], this.rendering_order[23], + this.rendering_order[5], this.rendering_order[3]]; + + [this.rendering_order[22], this.rendering_order[12], + this.rendering_order[4], this.rendering_order[14]] = + [this.rendering_order[12], this.rendering_order[4], + this.rendering_order[14], this.rendering_order[22]]; + break; + case Rotation.y2i: + this.cubes.back_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.back.rotate(Axis.y, -Math.PI / 2); + this.cubes.back_left.rotate(Axis.y, -Math.PI / 2); + this.cubes.right.rotate(Axis.y, -Math.PI / 2); + this.cubes.center.rotate(Axis.y, -Math.PI / 2); + this.cubes.left.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.front.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_left.rotate(Axis.y, -Math.PI / 2); + + [this.cubes.back_right, this.cubes.front_right, + this.cubes.front_left, this.cubes.back_left] = + [this.cubes.front_right, this.cubes.front_left, + this.cubes.back_left, this.cubes.back_right]; + + [this.cubes.back, this.cubes.left, + this.cubes.front, this.cubes.right] = + [this.cubes.right, this.cubes.back, + this.cubes.left, this.cubes.front]; + + [this.rendering_order[23], this.rendering_order[5], + this.rendering_order[3], this.rendering_order[21]] = + [this.rendering_order[5], this.rendering_order[3], + this.rendering_order[21], this.rendering_order[23]]; + + [this.rendering_order[22], this.rendering_order[12], + this.rendering_order[4], this.rendering_order[14]] = + [this.rendering_order[14], this.rendering_order[22], + this.rendering_order[12], this.rendering_order[4]]; + break; + case Rotation.y3: + this.cubes.back_bottom_right.rotate(Axis.y, Math.PI / 2); + this.cubes.back_bottom.rotate(Axis.y, Math.PI / 2); + this.cubes.back_bottom_left.rotate(Axis.y, Math.PI / 2); + this.cubes.bottom_right.rotate(Axis.y, Math.PI / 2); + this.cubes.bottom.rotate(Axis.y, Math.PI / 2); + this.cubes.bottom_left.rotate(Axis.y, Math.PI / 2); + this.cubes.front_bottom_right.rotate(Axis.y, Math.PI / 2); + this.cubes.front_bottom.rotate(Axis.y, Math.PI / 2); + this.cubes.front_bottom_left.rotate(Axis.y, Math.PI / 2); + + [this.cubes.back_bottom_right, this.cubes.front_bottom_right, + this.cubes.front_bottom_left, this.cubes.back_bottom_left] = + [this.cubes.back_bottom_left, this.cubes.back_bottom_right, + this.cubes.front_bottom_right, this.cubes.front_bottom_left]; + + [this.cubes.back_bottom, this.cubes.bottom_left, + this.cubes.front_bottom, this.cubes.bottom_right] = + [this.cubes.bottom_left, this.cubes.front_bottom, + this.cubes.bottom_right, this.cubes.back_bottom]; + + [this.rendering_order[26], this.rendering_order[8], + this.rendering_order[6], this.rendering_order[24]] = + [this.rendering_order[24], this.rendering_order[26], + this.rendering_order[8], this.rendering_order[6]]; + + [this.rendering_order[25], this.rendering_order[15], + this.rendering_order[7], this.rendering_order[17]] = + [this.rendering_order[15], this.rendering_order[7], + this.rendering_order[17], this.rendering_order[25]]; + break; + case Rotation.y3i: + this.cubes.back_bottom_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.back_bottom.rotate(Axis.y, -Math.PI / 2); + this.cubes.back_bottom_left.rotate(Axis.y, -Math.PI / 2); + this.cubes.bottom_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.bottom.rotate(Axis.y, -Math.PI / 2); + this.cubes.bottom_left.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_bottom_right.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_bottom.rotate(Axis.y, -Math.PI / 2); + this.cubes.front_bottom_left.rotate(Axis.y, -Math.PI / 2); + + [this.cubes.back_bottom_right, this.cubes.front_bottom_right, + this.cubes.front_bottom_left, this.cubes.back_bottom_left] = + [this.cubes.front_bottom_right, this.cubes.front_bottom_left, + this.cubes.back_bottom_left, this.cubes.back_bottom_right]; + + [this.cubes.back_bottom, this.cubes.bottom_left, + this.cubes.front_bottom, this.cubes.bottom_right] = + [this.cubes.bottom_right, this.cubes.back_bottom, + this.cubes.bottom_left, this.cubes.front_bottom]; + + [this.rendering_order[26], this.rendering_order[8], + this.rendering_order[6], this.rendering_order[24]] = + [this.rendering_order[8], this.rendering_order[6], + this.rendering_order[24], this.rendering_order[26]]; + + [this.rendering_order[25], this.rendering_order[15], + this.rendering_order[7], this.rendering_order[17]] = + [this.rendering_order[17], this.rendering_order[25], + this.rendering_order[15], this.rendering_order[7]]; + break; + case Rotation.z1: + this.cubes.back_top_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.top_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_top_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.back_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.left.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.back_bottom_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.bottom_left.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_bottom_left.rotate(Axis.z, -Math.PI / 2); + + [this.cubes.back_top_left, this.cubes.front_top_left, + this.cubes.front_bottom_left, this.cubes.back_bottom_left] = + [this.cubes.back_bottom_left, this.cubes.back_top_left, + this.cubes.front_top_left, this.cubes.front_bottom_left]; + + [this.cubes.top_left, this.cubes.back_left, + this.cubes.bottom_left, this.cubes.front_left] = + [this.cubes.back_left, this.cubes.bottom_left, + this.cubes.front_left, this.cubes.top_left]; + + [this.rendering_order[18], this.rendering_order[0], + this.rendering_order[6], this.rendering_order[24]] = + [this.rendering_order[24], this.rendering_order[18], + this.rendering_order[0], this.rendering_order[6]]; + + [this.rendering_order[9], this.rendering_order[21], + this.rendering_order[15], this.rendering_order[3]] = + [this.rendering_order[21], this.rendering_order[15], + this.rendering_order[3], this.rendering_order[9]]; + break; + case Rotation.z1i: + this.cubes.back_top_left.rotate(Axis.z, Math.PI / 2); + this.cubes.top_left.rotate(Axis.z, Math.PI / 2); + this.cubes.front_top_left.rotate(Axis.z, Math.PI / 2); + this.cubes.back_left.rotate(Axis.z, Math.PI / 2); + this.cubes.left.rotate(Axis.z, Math.PI / 2); + this.cubes.front_left.rotate(Axis.z, Math.PI / 2); + this.cubes.back_bottom_left.rotate(Axis.z, Math.PI / 2); + this.cubes.bottom_left.rotate(Axis.z, Math.PI / 2); + this.cubes.front_bottom_left.rotate(Axis.z, Math.PI / 2); + + [this.cubes.back_top_left, this.cubes.front_top_left, + this.cubes.front_bottom_left, this.cubes.back_bottom_left] = + [this.cubes.front_top_left, this.cubes.front_bottom_left, + this.cubes.back_bottom_left, this.cubes.back_top_left]; + + [this.cubes.top_left, this.cubes.back_left, + this.cubes.bottom_left, this.cubes.front_left] = + [this.cubes.front_left, this.cubes.top_left, + this.cubes.back_left, this.cubes.bottom_left]; + + [this.rendering_order[18], this.rendering_order[0], + this.rendering_order[6], this.rendering_order[24]] = + [this.rendering_order[0], this.rendering_order[6], + this.rendering_order[24], this.rendering_order[18]]; + + [this.rendering_order[9], this.rendering_order[21], + this.rendering_order[15], this.rendering_order[3]] = + [this.rendering_order[3], this.rendering_order[9], + this.rendering_order[21], this.rendering_order[15]]; + break; + case Rotation.z2: + this.cubes.back_top.rotate(Axis.z, -Math.PI / 2); + this.cubes.top.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_top.rotate(Axis.z, -Math.PI / 2); + this.cubes.back.rotate(Axis.z, -Math.PI / 2); + this.cubes.center.rotate(Axis.z, -Math.PI / 2); + this.cubes.front.rotate(Axis.z, -Math.PI / 2); + this.cubes.back_bottom.rotate(Axis.z, -Math.PI / 2); + this.cubes.bottom.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_bottom.rotate(Axis.z, -Math.PI / 2); + + [this.cubes.back_top, this.cubes.front_top, + this.cubes.front_bottom, this.cubes.back_bottom] = + [this.cubes.back_bottom, this.cubes.back_top, + this.cubes.front_top, this.cubes.front_bottom]; + + [this.cubes.top, this.cubes.back, + this.cubes.bottom, this.cubes.front] = + [this.cubes.back, this.cubes.bottom, + this.cubes.front, this.cubes.top]; + + [this.rendering_order[19], this.rendering_order[1], + this.rendering_order[7], this.rendering_order[25]] = + [this.rendering_order[25], this.rendering_order[19], + this.rendering_order[1], this.rendering_order[7]]; + + [this.rendering_order[10], this.rendering_order[22], + this.rendering_order[16], this.rendering_order[4]] = + [this.rendering_order[22], this.rendering_order[16], + this.rendering_order[4], this.rendering_order[10]]; + break; + case Rotation.z2i: + this.cubes.back_top.rotate(Axis.z, Math.PI / 2); + this.cubes.top.rotate(Axis.z, Math.PI / 2); + this.cubes.front_top.rotate(Axis.z, Math.PI / 2); + this.cubes.back.rotate(Axis.z, Math.PI / 2); + this.cubes.center.rotate(Axis.z, Math.PI / 2); + this.cubes.front.rotate(Axis.z, Math.PI / 2); + this.cubes.back_bottom.rotate(Axis.z, Math.PI / 2); + this.cubes.bottom.rotate(Axis.z, Math.PI / 2); + this.cubes.front_bottom.rotate(Axis.z, Math.PI / 2); + + [this.cubes.back_top, this.cubes.front_top, + this.cubes.front_bottom, this.cubes.back_bottom] = + [this.cubes.front_top, this.cubes.front_bottom, + this.cubes.back_bottom, this.cubes.back_top]; + + [this.cubes.top, this.cubes.back, + this.cubes.bottom, this.cubes.front] = + [this.cubes.front, this.cubes.top, + this.cubes.back, this.cubes.bottom]; + + [this.rendering_order[19], this.rendering_order[1], + this.rendering_order[7], this.rendering_order[25]] = + [this.rendering_order[1], this.rendering_order[7], + this.rendering_order[25], this.rendering_order[19]]; + + [this.rendering_order[10], this.rendering_order[22], + this.rendering_order[16], this.rendering_order[4]] = + [this.rendering_order[4], this.rendering_order[10], + this.rendering_order[22], this.rendering_order[16]]; + break; + case Rotation.z3: + this.cubes.back_top_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.top_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_top_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.back_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.right.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.back_bottom_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.bottom_right.rotate(Axis.z, -Math.PI / 2); + this.cubes.front_bottom_right.rotate(Axis.z, -Math.PI / 2); + + [this.cubes.back_top_right, this.cubes.front_top_right, + this.cubes.front_bottom_right, this.cubes.back_bottom_right] = + [this.cubes.back_bottom_right, this.cubes.back_top_right, + this.cubes.front_top_right, this.cubes.front_bottom_right]; + + [this.cubes.top_right, this.cubes.back_right, + this.cubes.bottom_right, this.cubes.front_right] = + [this.cubes.back_right, this.cubes.bottom_right, + this.cubes.front_right, this.cubes.top_right]; + + [this.rendering_order[20], this.rendering_order[2], + this.rendering_order[8], this.rendering_order[26]] = + [this.rendering_order[26], this.rendering_order[20], + this.rendering_order[2], this.rendering_order[8]]; + + [this.rendering_order[11], this.rendering_order[23], + this.rendering_order[17], this.rendering_order[5]] = + [this.rendering_order[23], this.rendering_order[17], + this.rendering_order[5], this.rendering_order[11]]; + break; + case Rotation.z3i: + this.cubes.back_top_right.rotate(Axis.z, Math.PI / 2); + this.cubes.top_right.rotate(Axis.z, Math.PI / 2); + this.cubes.front_top_right.rotate(Axis.z, Math.PI / 2); + this.cubes.back_right.rotate(Axis.z, Math.PI / 2); + this.cubes.right.rotate(Axis.z, Math.PI / 2); + this.cubes.front_right.rotate(Axis.z, Math.PI / 2); + this.cubes.back_bottom_right.rotate(Axis.z, Math.PI / 2); + this.cubes.bottom_right.rotate(Axis.z, Math.PI / 2); + this.cubes.front_bottom_right.rotate(Axis.z, Math.PI / 2); + + [this.cubes.back_top_right, this.cubes.front_top_right, + this.cubes.front_bottom_right, this.cubes.back_bottom_right] = + [this.cubes.front_top_right, this.cubes.front_bottom_right, + this.cubes.back_bottom_right, this.cubes.back_top_right]; + + [this.cubes.top_right, this.cubes.back_right, + this.cubes.bottom_right, this.cubes.front_right] = + [this.cubes.front_right, this.cubes.top_right, + this.cubes.back_right, this.cubes.bottom_right]; + + [this.rendering_order[20], this.rendering_order[2], + this.rendering_order[8], this.rendering_order[26]] = + [this.rendering_order[2], this.rendering_order[8], + this.rendering_order[26], this.rendering_order[20]]; + + [this.rendering_order[11], this.rendering_order[23], + this.rendering_order[17], this.rendering_order[5]] = + [this.rendering_order[5], this.rendering_order[11], + this.rendering_order[23], this.rendering_order[17]]; + break; + } + this.updatepos(); + this.updateColors(); + }, + rotate(dir) { + this.rotate_only(dir); + this.updateColors(); + this.updatepos(); + if ( this.is_solved() ) { + console.log("is_solved"); + } + }, + shuffle(nb_shuffle) { + for(let i = 0; i < nb_shuffle; ++i) { + switch (Math.floor( Math.random() * 18 )) { + case 0: + this.rotate_only( Rotation.x1); + break; + case 1: + this.rotate_only( Rotation.x1i); + break; + case 2: + this.rotate_only( Rotation.x2); + break; + case 3: + this.rotate_only( Rotation.x2i); + break; + case 4: + this.rotate_only( Rotation.x3); + break; + case 5: + this.rotate_only( Rotation.x3i); + break; + case 6: + this.rotate_only( Rotation.y1); + break; + case 7: + this.rotate_only( Rotation.y1i); + break; + case 8: + this.rotate_only( Rotation.y2); + break; + case 9: + this.rotate_only( Rotation.y2i); + break; + case 10: + this.rotate_only( Rotation.y3); + break; + case 11: + this.rotate_only( Rotation.y3i); + break; + case 12: + this.rotate_only( Rotation.z1); + break; + case 13: + this.rotate_only( Rotation.z1i); + break; + case 14: + this.rotate_only( Rotation.z2); + break; + case 15: + this.rotate_only( Rotation.z2i); + break; + case 16: + this.rotate_only( Rotation.z3); + break; + case 17: + this.rotate_only( Rotation.z3i); + break; + } + } + this.updateColors(); + this.updatepos(); + }, + is_solved() { + for ( let i = 0; i < this.rendering_order.length; ++i ) { + if ( this.rendering_order[i] != i ) { + return false; + } + } + return true; + }, + } +})(0.85); + +function loadShader( gl, type, source ) { + const shader = gl.createShader( type ); + gl.shaderSource( shader, source ); + gl.compileShader( shader ); + if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) { + alert( + "An error has occured while compiling the shader: " + gl.getShaderInfoLog(shader) + ); + gl.deleteShader(shader); + return null; + } + + return shader; +} + +function initShaderProgram(gl, vsSource, fsSource) { + const vertexShader = loadShader( gl, gl.VERTEX_SHADER, vsSource ); + const fragmentShader = loadShader( gl, gl.FRAGMENT_SHADER, fsSource ); + + const shaderProgram = gl.createProgram(); + gl.attachShader( shaderProgram, vertexShader ); + gl.attachShader( shaderProgram, fragmentShader ); + gl.linkProgram( shaderProgram ); + + if ( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) ) { + alert( `Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgram)}` ); + return null; + } + + return shaderProgram; +} + +function initBuffers(gl) { + const positionBuffer = gl.createBuffer(); + gl.bindBuffer( gl.ARRAY_BUFFER, positionBuffer ); + + const positions = rubik.positions; + gl.bufferData( gl.ARRAY_BUFFER, + new Float32Array(positions), + gl.DYNAMIC_DRAW); + + const colors = rubik.colors; + + const colorBuffer = gl.createBuffer(); + gl.bindBuffer( gl.ARRAY_BUFFER, colorBuffer ); + gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW); + + const indexBuffer = gl.createBuffer(); + gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, indexBuffer ); + + const indices = rubik.indices; + gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, + new Uint16Array(indices), + gl.STATIC_DRAW); + return { + position : positionBuffer, + // textureCoord: textureCoordBuffer, + color: colorBuffer, + indices: indexBuffer, + }; +} + +function drawScene( gl, programInfo, buffers, cubeRotation ) { + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.clearDepth(1.0); + gl.enable( gl.DEPTH_TEST ); + gl.depthFunc( gl.LEQUAL ); + + gl.clear(gl.COLOR_BUFFER_BIT, gl.DEPTH_BUFFER_BIT); + + gl.bindBuffer( gl.ARRAY_BUFFER, buffers.position ); + gl.bufferData( gl.ARRAY_BUFFER, + new Float32Array(rubik.positions), + gl.DYNAMIC_DRAW); + + gl.bindBuffer( gl.ARRAY_BUFFER, buffers.color ); + gl.bufferData( gl.ARRAY_BUFFER, + new Float32Array(rubik.colors), + gl.DYNAMIC_DRAW); + + const fieldOfView = Math.PI / 4; + const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight; + const zNear = 0.1; + const zFar = 100.0; + const projectionMatrix = mat4.create(); + + mat4.perspective( projectionMatrix, fieldOfView, aspect, zNear, zFar ); + + const modelViewMatrix = mat4.create(); + + mat4.translate( modelViewMatrix, + modelViewMatrix, + [ 0.0, 0.0, -9.0 ]); + mat4.rotate( modelViewMatrix, + modelViewMatrix, + g_x_rotation, + [1, 0, 0]); + + mat4.rotate( modelViewMatrix, + modelViewMatrix, + g_y_rotation, + [0, 1, 0]); + + + { + const numComponents = 3; + const type = gl.FLOAT; + const normalize = false; + const stride = 0; + const offset = 0; + gl.bindBuffer( gl.ARRAY_BUFFER, buffers.position ); + gl.vertexAttribPointer( programInfo.attribLocations.vertexPosition, + numComponents, + type, + normalize, + stride, + offset ); + gl.enableVertexAttribArray( + programInfo.attribLocations.vertexPosition + ); + } + + { + const numComponents = 4; + const type = gl.FLOAT; + const normalize = false; + const stride = 0; + const offset = 0; + gl.bindBuffer( gl.ARRAY_BUFFER, buffers.color ); + gl.vertexAttribPointer( programInfo.attribLocations.vertexColor, + numComponents, + type, + normalize, + stride, + offset); + gl.enableVertexAttribArray( programInfo.attribLocations.vertexColor ); + } + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices); + + + gl.useProgram( programInfo.program ); + + gl.uniformMatrix4fv( programInfo.uniformLocations.projectionMatrix, + false, + projectionMatrix); + gl.uniformMatrix4fv( programInfo.uniformLocations.modelViewMatrix, + false, + modelViewMatrix); + + { + const type = gl.UNSIGNED_SHORT; + const offset = 0; + gl.drawElements( gl.TRIANGLES, rubik.indices.length, type, offset ); + } +} + +function main() { + let slider_y = document.getElementById("y_rotation"); + slider_y.oninput = () => { + g_y_rotation = slider_y.value * Math.PI / 180; + }; + + let slider_x = document.getElementById("x_rotation"); + slider_x.oninput = () => { + g_x_rotation = slider_x.value * Math.PI / 180; + }; + + const canvas = document.querySelector('#glCanvas'); + const gl = canvas.getContext("webgl"); + + if ( !gl ) { + alert("Unable to initialize WebGl. Your browser or your machine may not support it."); + return; + } + const vsSource = ` + attribute vec4 aVertexPosition; + attribute vec4 aVertexColor; + + uniform mat4 uModelViewMatrix; + uniform mat4 uProjectionMatrix; + + varying lowp vec4 vColor; + + void main() { + gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition; + vColor = aVertexColor; + } + ` + const fsSource = ` + varying lowp vec4 vColor; + void main() { + gl_FragColor = vColor; + } + ` + const shaderProgram = initShaderProgram(gl, vsSource, fsSource); + const programInfo = { + program: shaderProgram, + attribLocations: { + vertexPosition: gl.getAttribLocation( shaderProgram, "aVertexPosition" ), + vertexColor: gl.getAttribLocation( shaderProgram, "aVertexColor" ), + }, + uniformLocations: { + projectionMatrix: gl.getUniformLocation( shaderProgram, "uProjectionMatrix" ), + modelViewMatrix: gl.getUniformLocation( shaderProgram, "uModelViewMatrix" ), + }, + }; + + const buffers = initBuffers(gl); + + + document.getElementById("rotate_x1").onclick = () => { + rubik.rotate(Rotation.x1); + } + document.getElementById("rotate_x1i").onclick = () => { + rubik.rotate(Rotation.x1i); + } + document.getElementById("rotate_x2").onclick = () => { + rubik.rotate(Rotation.x2); + } + document.getElementById("rotate_x2i").onclick = () => { + rubik.rotate(Rotation.x2i); + } + document.getElementById("rotate_x3").onclick = () => { + rubik.rotate(Rotation.x3); + } + document.getElementById("rotate_x3i").onclick = () => { + rubik.rotate(Rotation.x3i); + } + + document.getElementById("rotate_y1").onclick = () => { + rubik.rotate(Rotation.y1); + } + document.getElementById("rotate_y1i").onclick = () => { + rubik.rotate(Rotation.y1i); + } + document.getElementById("rotate_y2").onclick = () => { + rubik.rotate(Rotation.y2); + } + document.getElementById("rotate_y2i").onclick = () => { + rubik.rotate(Rotation.y2i); + } + document.getElementById("rotate_y3").onclick = () => { + rubik.rotate(Rotation.y3); + } + document.getElementById("rotate_y3i").onclick = () => { + rubik.rotate(Rotation.y3i); + } + + document.getElementById("rotate_z1").onclick = () => { + rubik.rotate(Rotation.z1); + } + document.getElementById("rotate_z1i").onclick = () => { + rubik.rotate(Rotation.z1i); + } + document.getElementById("rotate_z2").onclick = () => { + rubik.rotate(Rotation.z2); + } + document.getElementById("rotate_z2i").onclick = () => { + rubik.rotate(Rotation.z2i); + } + document.getElementById("rotate_z3").onclick = () => { + rubik.rotate(Rotation.z3); + } + document.getElementById("rotate_z3i").onclick = () => { + rubik.rotate(Rotation.z3i); + } + + document.getElementById("shuffle").onclick = () => { + rubik.shuffle(4); + } + + const render = (now) => { + drawScene( gl, programInfo, buffers, now * 0.001 ); + requestAnimationFrame(render); + } + requestAnimationFrame(render); +} +window.onload = main; diff --git a/index.html b/index.html new file mode 100644 index 0000000..830c13f --- /dev/null +++ b/index.html @@ -0,0 +1,59 @@ + + +
+ + +