更多有趣示例 尽在小红砖社区
示例
HTML
<html lang="en">
<head>
<title>AlphabetTriangle</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<!-- CSS -->
<link type="text/css" rel="stylesheet" href="main.css">
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/renderers/CSS2DRenderer.js"></script>
</head>
<body>
<!-- WEB GL RENDERING -->
<div id="container"></div>
<!-- MENU BAR -->
<div id="menu">
<button id="button_labels">ID</button>
<button id="button_grid">GRID</button>
<button id="button_fixed">FIXED</button>
<button id="button_shuffle">SHUFFLE</button>
<button id="button_config">CONFIG</button>
</div>
<!-- CONFIG BAR -->
<span id="config" style="display: none;">
Configuration
<!-- Examples
#01r#09r#21r#02l#03m#08m#07r#06l#14r#10r#11r#12r#13r#16l#25l#05r#17m#18l#19l#20r#24l#23r#22l#15m#04l#
#08r#10m#21r#02l#03m#01m#07r#06r#14r#05m#11r#12r#13r#16m#25l#15l#17m#18l#19l#20r#24l#23m#22l#09l#04l#
#08r#05l#21r#02l#03m#01m#07r#06r#14r#10m#11r#12r#13r#16m#25l#15l#17m#18l#19l#20r#24l#23m#22l#09l#04l#
#01r#25r#16r#23m#09m#05r#06l#21r#11l#08m#10l#12r#13l#02m#19r#24m#17m#18l#03l#14r#20m#07l#15r#22r#04l#
#12l#22m#11r#03l#15r#05l#02l#14m#20m#19l#09m#01l#06l#10r#23l#07r#17m#18l#24r#13r#08m#21r#25m#16m#04l#
#03m#15l#05r#09r#02l#22m#01l#14m#20m#11l#19m#13r#16r#24m#23l#07r#17m#18l#10m#06r#08r#21l#25l#12l#04l#
#01r#22r#16r#24m#10l#13r#12l#11m#04m#14l#20l#23r#19l#02r#06m#08m#15r#07l#09r#03m#05l#17r#21m#25l#18m#
#01r#22r#16r#24m#10l#13r#09r#15m#02r#25r#23m#12r#07m#21l#19l#08m#18r#04r#05r#11r#03l#06l#14l#20l#17r#
#01r#22r#16r#24m#10l#13r#21m#11r#03m#07m#17r#02r#12m#25r#06r#23l#18r#19l#08l#09m#04m#14r#20m#15m#05m#
-->
<input id="input_config" type="text" style="margin-left: 10px; width: 600px;" value="">
<button id="copy_config">COPY</button>
<button id="delete_config">DELETE</button>
</span>
<!-- AlphabetTriangle Code -->
<script src="figures.js"></script>
<script src="figureBuilder.js"></script>
<script src="main.js"></script>
</body>
</html>
CSS
#stats {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
}
#menu {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
background-color: rgba(70,255,255,0.12);
color: rgba(127,255,255,0.75);
font-family: futurama;
}
#config {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
background-color: rgba(70,255,255,0.12);
color: rgba(127,255,255,0.75);
font-family: futurama;
}
button {
color: rgba(127,255,255,0.7);
background: transparent;
outline: 1px solid rgba(127,255,255,0.75);
border: 0px;
padding: 5px 10px;
cursor: pointer;
z-index: 100;
}
button:hover {
background-color: rgba(255,255,255,0.5);
}
button:active {
color: #000000;
background-color: rgba(0,255,255,0.75);
}
.label {
color: #FFF;
font-family: futurama;
padding: 2px;
font-size: 10px;
background: rgba( 0, 0, 0, .6 );
}
JS
///////////////////////////////////////////////////////////////////////////
// CLASS Figure //////////////
// containing all 25 figures //////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
class Figure {
constructor() {
this.figures = new Array(26);
for(var i = 0; i<26; i+=1){
this.figures[i] = new Array(2);
}
this.figures[ 0][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 1][0] = [ 0,
0,0,0,
0,0,0,0,0,
1,1,1,1,1,0,0,
0,1,1,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 2][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,0,0,0,0,1,
0,0,0,0,0,0,1,1,1,
0,0,0,0,0,0,0,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 3][0] = [ 0,
0,0,0,
0,0,0,0,0,
1,0,0,0,0,0,0,
0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 4][0] = [ 0,
0,0,0,
0,0,0,0,0,
1,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 5][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 6][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,1,1,1,1,1,
0,0,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 7][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,0,1,1,1,1,
1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 8][0] = [ 0,
0,0,0,
1,1,1,1,1,
1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[ 9][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[10][0] = [ 0,
0,0,0,
1,0,0,0,0,
1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[11][0] = [ 0,
0,0,0,
0,0,0,0,1,
0,0,0,0,0,1,1,
0,0,1,0,0,0,0,0,0,
0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[12][0] = [ 0,
1,0,0,
1,1,0,0,0,
1,1,0,0,0,0,0,
1,1,1,0,0,0,0,0,0,
1,1,1,1,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,0,1,1,0,0,0
]
this.figures[13][0] = [ 0,
0,0,0,
1,1,1,1,1,
0,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,
0,1,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[14][0] = [ 0,
1,1,1,
0,1,1,1,1,
1,1,1,1,1,1,1,
1,1,1,1,0,0,0,0,0,
1,1,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[15][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,1,0,0,0,0,
0,0,1,1,0,0,0,0,0,
0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[16][0] = [ 0,
0,0,0,
1,1,1,1,1,
1,1,1,1,1,1,0,
1,1,1,1,1,1,0,0,0,
1,1,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[17][0] = [ 0,
0,0,0,
0,0,1,1,1,
0,0,1,1,1,1,0,
0,0,1,1,1,1,0,0,0,
0,0,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[18][0] = [ 0,
0,0,0,
1,0,0,0,0,
1,1,0,0,0,0,0,
1,1,0,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[19][0] = [ 0,
0,0,0,
1,0,0,0,0,
1,1,1,0,0,0,0,
1,1,0,0,1,0,0,0,0,
0,1,1,0,1,1,1,0,0,0,0,
0,0,0,0,0,1,1,1,1,0,0,0,0
]
this.figures[20][0] = [ 0,
1,0,0,
1,1,0,0,0,
1,1,0,0,0,0,0,
0,0,1,1,1,0,0,0,0,
1,0,1,1,1,1,1,0,0,0,0,
0,0,0,1,1,1,1,1,1,0,0,0,0
]
this.figures[21][0] = [ 0,
1,0,0,
1,1,1,0,0,
1,1,1,1,0,0,0,
1,1,1,1,0,0,0,0,0,
0,1,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0
]
this.figures[22][0] = [ 0,
0,0,0,
0,0,0,0,0,
0,0,1,0,0,0,0,
0,0,0,1,1,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0
]
this.figures[23][0] = [ 0,
0,0,0,
0,0,0,0,1,
0,0,0,0,1,1,1,
0,0,0,0,1,1,1,1,1,
0,0,0,0,0,1,1,1,1,1,0,
0,0,0,0,0,0,0,1,1,1,0,0,0
]
this.figures[24][0] = [ 0,
0,0,0,
1,0,0,0,0,
0,1,1,0,0,0,0,
0,0,0,1,1,0,0,0,0,
0,0,0,0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0
]
this.figures[25][0] = [ 0,
1,0,0,
1,1,1,0,0,
0,1,1,1,1,0,0,
0,0,0,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,0,0,
0,0,0,0,0,0,0,1,1,1,0,0,0
]
this.figures[ 0][1] = "EMPTY";
this.figures[ 1][1] = "tg";
this.figures[ 2][1] = "tj";
this.figures[ 3][1] = "lg";
this.figures[ 4][1] = "kg/tp"
this.figures[ 5][1] = "tq";
this.figures[ 6][1] = "lj";
this.figures[ 7][1] = "hg/kj";
this.figures[ 8][1] = "fg";
this.figures[ 9][1] = "hj";
this.figures[10][1] = "dg";
this.figures[11][1] = "fj/lp";
this.figures[12][1] = "bg/kp/lq/ty";
this.figures[13][1] = "dj/kq";
this.figures[14][1] = "bj/hp";
this.figures[15][1] = "hq";
this.figures[16][1] = "fp";
this.figures[17][1] = "fq";
this.figures[18][1] = "dp";
this.figures[19][1] = "dq/ly";
this.figures[20][1] = "bp/ky";
this.figures[21][1] = "bq";
this.figures[22][1] = "hy";
this.figures[23][1] = "fy";
this.figures[24][1] = "dy";
this.figures[25][1] = "by";
}
rotate(id){
var o = this.figures[id][0];
var r = [
o[48],
o[35],o[47],o[46],
o[24],o[34],o[33],o[45],o[44],
o[15],o[23],o[22],o[32],o[31],o[43],o[42],
o[ 8],o[14],o[13],o[21],o[20],o[30],o[29],o[41],o[40],
o[ 3],o[ 7],o[ 6],o[12],o[11],o[19],o[18],o[28],o[27],o[39],o[38],
o[ 0],o[ 2],o[ 1],o[ 5],o[ 4],o[10],o[ 9],o[17],o[16],o[26],o[25],o[37],o[36]
]
return r;
}
getFigure(id, rot, flip){
var figure = this.figures[id][0];
if(rot == -1){
figure = this.rotate(id);
}
if(rot == 1){
figure = this.rotate(id);
figure = this.rotate(id);
}
return figure;
}
getFigureName(id){
var name = this.figures[id][1];
return name;
}
}
///////////////////////////////////////////////////////////////////////////
// CLASS FigureBuilder //////////////
// organize figures in list-form and pyramide-form //////////////
// create Mesh-Data //////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
class FigureBuilder {
constructor(size, f_color, bg_color) {
var tri_height = 866025403784;
var tri_height = tri_height;
var tri_side = 1000000000000;
var tri_side_half = tri_side/2;
this.tri = new THREE.Vector2();
this.tri.x = tri_side_half;
this.tri.y = tri_height;
this.tri.normalize();
this.SIZE = size * 25/100;
this.F_COLOR = f_color;
this.BG_COLOR = bg_color;
//Construction of 1 single figure out of alternating triangles
this.idMap = [
[0,0,0],
[1,0,0], [1,0,1], [1,1,0],
[2,0,0], [2,0,1], [2,1,0], [2,1,1], [2,2,0],
[3,0,0], [3,0,1], [3,1,0], [3,1,1], [3,2,0], [3,2,1], [3,3,0],
[4,0,0], [4,0,1], [4,1,0], [4,1,1], [4,2,0], [4,2,1], [4,3,0], [4,3,1], [4,4,0],
[5,0,0], [5,0,1], [5,1,0], [5,1,1], [5,2,0], [5,2,1], [5,3,0], [5,3,1], [5,4,0], [5,4,1], [5,5,0],
[6,0,0], [6,0,1], [6,1,0], [6,1,1], [6,2,0], [6,2,1], [6,3,0], [6,3,1], [6,4,0], [6,4,1], [6,5,0], [6,5,1], [6,6,0],
[7,0,0], [7,0,1], [7,1,0], [7,1,1], [7,2,0], [7,2,1], [7,3,0], [7,3,1], [7,4,0], [7,4,1], [7,5,0], [7,5,1], [7,6,0], [7,6,1], [7,7,0]
]
this.flippedSlots = [3,6,8,11,13,15,18,20,22,24];
this.figure_collection = new Figure();
this.figurePositions = this.createFigurePositions();
this.figureRotations = this.createFigureRotations();
this.slotToPositionMap = this.createSlotToPositionMap();
this.positionMapForList = this.createPositionMapForList();
this.listOfFigures = this.createListOfFigures();
this.pyramideOfFigures = this.createPyramideOfFigures();
}
//Returns: [(x1,y1),(x2,y2),(x2,y2)]
getTriangleCoords(row, col, mir, size, flip){
var vector_l = new THREE.Vector2();
var vector_r = new THREE.Vector2();
var vector_s = new THREE.Vector2();
var point_1 = new THREE.Vector2();
var point_2 = new THREE.Vector2();
var point_3 = new THREE.Vector2();
vector_l.x = -this.tri.x*size*flip;
vector_l.y = -this.tri.y*size*flip;
vector_r.x = this.tri.x*size*flip;
vector_r.y = -this.tri.y*size*flip;
vector_s.x = 2*this.tri.x*size*flip;
vector_s.y = 0*flip;
point_1.x = vector_l.x*row + vector_s.x*col; //Top (or if mirrored) Left Top
point_1.y = vector_l.y*row + vector_s.y*col;
point_2.x = point_1.x+vector_l.x + (vector_s.x-vector_l.x)*mir; //Left Bottom (or if mirrored) Right Top
point_2.y = point_1.y+vector_l.y + (vector_s.y-vector_l.y)*mir;
point_3.x = point_1.x+vector_r.x; //Right Bottom (or if mirrored) Bottom
point_3.y = point_1.y+vector_r.y;
var points = [point_1, point_2, point_3];
return points;
}
//returns triangles[ triangle1, triangle2, triangle3, ... ]
//with triangle[ x1,y1, x2,y2, x3,y3 , color ]
createFigure(fig_id, size, x, y, rot, flip){
var triangles = [];
var figure = this.figure_collection.getFigure(fig_id, rot, flip);
var vector_pos = new THREE.Vector2();
vector_pos.x = x;
vector_pos.y = y;
var vector_h = new THREE.Vector2();
vector_h.x = 0;
vector_h.y = this.tri.y*7*size;
var tri_center_vector = new THREE.Vector2();
tri_center_vector.x = 0;
tri_center_vector.y = (0 + vector_h.y + vector_h.y)/3;
for (var id = 0; id < 49; id++) {
var idMapEl = this.idMap[id];
var points = this.getTriangleCoords(idMapEl[0],idMapEl[1],idMapEl[2], size, flip);
var point1 = new THREE.Vector2();
var point2 = new THREE.Vector2();
var point3 = new THREE.Vector2();
// tri_center_vector centers the Figure to its barycenter
if(flip==1){
point1.x = points[0].x + vector_pos.x;
point1.y = points[0].y + vector_pos.y + tri_center_vector.y;
point2.x = points[1].x + vector_pos.x;
point2.y = points[1].y + vector_pos.y + tri_center_vector.y;
point3.x = points[2].x + vector_pos.x;
point3.y = points[2].y + vector_pos.y + tri_center_vector.y;
}else{
point1.x = points[0].x + vector_pos.x;
point1.y = points[0].y + vector_pos.y - tri_center_vector.y;
point2.x = points[1].x + vector_pos.x;
point2.y = points[1].y + vector_pos.y - tri_center_vector.y;
point3.x = points[2].x + vector_pos.x;
point3.y = points[2].y + vector_pos.y - tri_center_vector.y;
}
var value = figure[id];
var color = this.F_COLOR;
if(value == 0){ color = this.BG_COLOR; }
var triangle = [];
triangle.push(point1.x);
triangle.push(point1.y);
triangle.push(point2.x);
triangle.push(point2.y);
triangle.push(point3.x);
triangle.push(point3.y);
triangle.push(color);
triangles.push(triangle);
}
return triangles;
}
createOutline(size, x, y, rot, flip){
var triangles = [];
var vector_pos = new THREE.Vector2();
vector_pos.x = x;
vector_pos.y = y;
var vector_h = new THREE.Vector2();
vector_h.x = 0;
vector_h.y = this.tri.y*7*size;
var side = this.tri.x*3.5;
var tri_center_vector = new THREE.Vector2();
tri_center_vector.x = 0;
tri_center_vector.y = (0 + vector_h.y + vector_h.y)/3;
var idMapEl = this.idMap[0];
var points = this.getTriangleCoords(idMapEl[0],idMapEl[1],idMapEl[2], size*7, flip);
var point1 = new THREE.Vector2();
var point2 = new THREE.Vector2();
var point3 = new THREE.Vector2();
// tri_center_vector centers the Figure to its barycenter
if(flip==1){
point1.x = points[0].x + vector_pos.x;
point1.y = points[0].y + vector_pos.y + tri_center_vector.y;
point2.x = points[1].x + vector_pos.x;
point2.y = points[1].y + vector_pos.y + tri_center_vector.y;
point3.x = points[2].x + vector_pos.x;
point3.y = points[2].y + vector_pos.y + tri_center_vector.y;
}else{
point1.x = points[0].x + vector_pos.x;
point1.y = points[0].y + vector_pos.y - tri_center_vector.y;
point2.x = points[1].x + vector_pos.x;
point2.y = points[1].y + vector_pos.y - tri_center_vector.y;
point3.x = points[2].x + vector_pos.x;
point3.y = points[2].y + vector_pos.y - tri_center_vector.y;
}
var color = 0.90;
var triangle = [];
triangle.push(point1.x);
triangle.push(point1.y);
triangle.push(point2.x);
triangle.push(point2.y);
triangle.push(point3.x);
triangle.push(point3.y);
triangle.push(color);
triangles.push(triangle);
return triangles;
}
//returns figures[ triangles1, triangles2, triangles3, ... ]
//with triangles[ triangle1, triangle2, triangle3, ... ]
//with triangle[ x1,y1, x2,y2, x3,y3 , color ]
createListOfFigures(){ //Local Positions for each Figure -> must be transformed to right positions
var figure_list = [];
var center_x = 0;
var center_y = 0;
for(var id = 1; id <= 25; id++){
figure_list.push(this.createFigure( id, this.SIZE, center_x, center_y, 0, 1));
}
return figure_list;
}
createPositionMapForList(){
var positionMapForList = new Array(25);
var center_x = -4*8*this.SIZE / 2;
var center_y = 4*8*this.SIZE / 2;
for(var fig_id = 1; fig_id <= 25; fig_id++){
positionMapForList[fig_id-1] = [center_x + ((fig_id-1)%5) * 8 * this.SIZE, center_y - (parseInt((fig_id-1)/5)) * 8 * this.SIZE, 0];
}
return positionMapForList;
}
//Pyramide of Figures
createPyramideOfFigures(){
var figure_pyramide = new Array(25);
for(var id = 1; id <= 25; id++){
var layers = new Array();
layers.push( this.createFigure( this.getFigureForSlot(id), this.SIZE, 0, 0, this.getFigureRotation(id), 1) );
layers.push( this.createOutline( this.SIZE, 0, 0, this.getFigureRotation(id), 1) );
figure_pyramide[id-1] = layers;
}
return figure_pyramide;
}
createSlotToPositionMap(){
var side = 7*(this.tri.x)*this.SIZE;
var fside = 2*side;
var height = 7*(this.tri.y)*this.SIZE;
var flipoffset = -(0 + height + height)/3 + height;
var center_x = 0;
var center_y = 5*height/2;
var slotToPositionMap = new Array(25);
slotToPositionMap[ 0] = [ center_x - side*0 + fside*0 , center_y - height*0 ]; // #row 0 #Slot 1
slotToPositionMap[ 1] = [ center_x - side*1 + fside*0 , center_y - height*1 ]; // #row 1 #Slot 2
slotToPositionMap[ 3] = [ center_x - side*1 + fside*1 , center_y - height*1 ]; // #Slot 4
slotToPositionMap[ 4] = [ center_x - side*2 + fside*0 , center_y - height*2 ]; // #row 2 #Slot 5
slotToPositionMap[ 6] = [ center_x - side*2 + fside*1 , center_y - height*2 ]; // #Slot 7
slotToPositionMap[ 8] = [ center_x - side*2 + fside*2 , center_y - height*2 ]; // #Slot 9
slotToPositionMap[ 9] = [ center_x - side*3 + fside*0 , center_y - height*3 ]; // #row 3 #Slot 10
slotToPositionMap[11] = [ center_x - side*3 + fside*1 , center_y - height*3 ]; // #Slot 12
slotToPositionMap[13] = [ center_x - side*3 + fside*2 , center_y - height*3 ]; // #Slot 14
slotToPositionMap[15] = [ center_x - side*3 + fside*3 , center_y - height*3 ]; // #Slot 16
slotToPositionMap[16] = [ center_x - side*4 + fside*0 , center_y - height*4 ]; // #row 4 #Slot 17
slotToPositionMap[18] = [ center_x - side*4 + fside*1 , center_y - height*4 ]; // #Slot 19
slotToPositionMap[20] = [ center_x - side*4 + fside*2 , center_y - height*4 ]; // #Slot 21
slotToPositionMap[22] = [ center_x - side*4 + fside*3 , center_y - height*4 ]; // #Slot 23
slotToPositionMap[24] = [ center_x - side*4 + fside*4 , center_y - height*4 ]; // #Slot 25
//#MIRROR
slotToPositionMap[ 2] = [ center_x - side*1 + side*1 , center_y - height*1 + flipoffset ]; // #row 1 #Slot 3
slotToPositionMap[ 5] = [ center_x - side*2 + side*1 , center_y - height*2 + flipoffset ]; // #row 2 #Slot 6
slotToPositionMap[ 7] = [ center_x - side*2 + side*3 , center_y - height*2 + flipoffset ]; // #Slot 8
slotToPositionMap[10] = [ center_x - side*3 + side*1 , center_y - height*3 + flipoffset ]; // #row 3 #Slot 11
slotToPositionMap[12] = [ center_x - side*3 + side*3 , center_y - height*3 + flipoffset ]; // #Slot 13
slotToPositionMap[14] = [ center_x - side*3 + side*5 , center_y - height*3 + flipoffset ]; // #Slot 15
slotToPositionMap[17] = [ center_x - side*4 + side*1 , center_y - height*4 + flipoffset ]; // #row 4 #Slot 18
slotToPositionMap[19] = [ center_x - side*4 + side*3 , center_y - height*4 + flipoffset ]; // #Slot 20
slotToPositionMap[21] = [ center_x - side*4 + side*5 , center_y - height*4 + flipoffset ]; // #Slot 22
slotToPositionMap[23] = [ center_x - side*4 + side*7 , center_y - height*4 + flipoffset ]; // #Slot 24
return slotToPositionMap;
}
slotXPosition(slot){ return this.slotToPositionMap[slot-1][0]; }
slotYPosition(slot){ return this.slotToPositionMap[slot-1][1]; }
getFigureForSlot(slot){ return this.figurePositions[slot-1]; }
setFigureForSlot(slot, fig_id){ this.figurePositions[slot-1] = fig_id; }
getFigureRotation(fig_id){ return this.figureRotations[fig_id-1]; }
setFigureRotation(fig_id, fig_rot){ this.figureRotations[fig_id-1] = fig_rot; }
getIfFlipped(slot){ return this.flippedSlots.includes(slot); }
getSlotForFigure(fig_id){
for(var slot = 1; slot<=25; slot+=1){
if(this.getFigureForSlot(slot) == fig_id){
return slot;
}
}
return 1; //ERROR
}
rotateFigure(slot){
var rot = this.getFigureRotation(slot);
rot -= 1;
if(rot == -2){ rot = 1; }
this.setFigureRotation(slot,rot);
}
switchSlotFigures(slot1, slot2){
var sf1 = this.getFigureForSlot(slot1);
var sf2 = this.getFigureForSlot(slot2);
this.setFigureForSlot(slot1, sf2);
this.setFigureForSlot(slot2, sf1);
}
//https://stackoverflow.com/questions/2464902/determine-if-a-point-is-inside-a-triangle-formed-by-3-points-with-given-latitude
pointInTriange(P, A, B, C) {
// Compute vectors
function vec(from, to) { return [to[0] - from[0], to[1] - from[1]]; }
var v0 = vec(A, C);
var v1 = vec(A, B);
var v2 = vec(A, P);
// Compute dot products
function dot(u, v) { return u[0] * v[0] + u[1] * v[1]; }
var dot00 = dot(v0, v0);
var dot01 = dot(v0, v1);
var dot02 = dot(v0, v2);
var dot11 = dot(v1, v1);
var dot12 = dot(v1, v2);
// Compute barycentric coordinates
var invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
// Check if point is in triangle
return (u >= 0) && (v >= 0) && (u + v < 1);
}
getCorners(slot) {
//var corners = [[0.0, 0.0],[0.5, 0.0],[0.0, 0.5]];
var cx = this.slotXPosition(slot);
var cy = this.slotYPosition(slot);
var side = 7*(this.tri.x)*this.SIZE;
var fside = 2*side;
var height = 7*(this.tri.y)*this.SIZE;
var tri_center_vector = new THREE.Vector2();
//tri_center_vector.x = 0;
//tri_center_vector.y = (0 + height + height)/3;
tri_center_vector.y = 0;
var x1 = 0 + cx;
var y1 = 0 + cy + tri_center_vector.y;
var x2 = -fside + cx;
var y2 = height + cy + tri_center_vector.y;
var x3 = fside + cx;
var y3 = height + cy + tri_center_vector.y;
var corners = [[x1,y1],[x2,y2],[x3,y3]];
return corners;
}
getSlotForXY(x,y) {
for(var slot = 1; slot <= 25; slot += 1){
var P = [x, y];
var corners = this.getCorners(slot);
var A = [corners[0][0],corners[0][1]];
var B = [corners[1][0],corners[1][1]];
var C = [corners[2][0],corners[2][1]];
if(this.pointInTriange(P, A, B, C)){
return slot;
}
}
return null;
}
createFigurePositions(){
var p01 = 1; var p02 = 2; var p03 = 3; var p04 = 4; var p05 = 5;
var p06 = 6; var p07 = 7; var p08 = 8; var p09 = 9; var p10 = 10;
var p11 = 11; var p12 = 12; var p13 = 13; var p14 = 14; var p15 = 15;
var p16 = 16; var p17 = 17; var p18 = 18; var p19 = 19; var p20 = 20;
var p21 = 21; var p22 = 22; var p23 = 23; var p24 = 24; var p25 = 25;
var FigurePositions = [
p01,
p02,p03,p04,
p05,p06,p07,p08,p09,
p10,p11,p12,p13,p14,p15,p16,
p17,p18,p19,p20,p21,p22,p23,p24,p25
];
return FigurePositions;
}
setConfiguration(positions, rotations){
this.figurePositions = positions;
this.figureRotations = rotations;
}
getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
setRandomConfiguration(){
var ids = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
this.figurePositions = this.shuffle(ids);
}
permuteConfiguration(){
}
createFigureRotations(){
var figureRotations = new Array();
for(var i = 0; i<25; i+=1){
figureRotations.push(0);
}
return figureRotations;
}
getCoord(array_ref, fig_id, layer, triangle_index, coord_index){
var coord;
if(array_ref==0){ coord = this.listOfFigures[fig_id-1][triangle_index][coord_index]; }
if(array_ref==1){ coord = this.pyramideOfFigures[fig_id-1][layer][triangle_index][coord_index]; }
return parseFloat(coord);
}
getName(fig_id){
return this.figure_collection.getFigureName(fig_id);
}
//Mesh_Group 0 -> List of Figures
//Mesh_Group 1 -> Pyramide of Figures - Grid
//Mesh_Group 2 -> Pyramide of Figures - Outline
toPositionBuffer(fig_id, mesh_group){
var triangles, array_ref, layer;
if(mesh_group == 0){ triangles = 49; array_ref = 0; layer = null;}
if(mesh_group == 1){ triangles = 49; array_ref = 1; layer = 0;}
if(mesh_group == 2){ triangles = 1; array_ref = 1; layer = 1;}
var positions = new Float32Array( triangles * 3 * 3 );
for ( var t = 0; t < triangles; t += 1 ) {
var i = t*9;
positions[ i + 0 ] = this.getCoord(array_ref, fig_id, layer, t, 0); //Point 1 -> x
positions[ i + 1 ] = this.getCoord(array_ref, fig_id, layer, t, 1); //Point 1 -> y
positions[ i + 2 ] = parseFloat(0); //Point 1 -> z
positions[ i + 3 ] = this.getCoord(array_ref, fig_id, layer, t, 2); //Point 2 -> x
positions[ i + 4 ] = this.getCoord(array_ref, fig_id, layer, t, 3); //Point 2 -> y
positions[ i + 5 ] = parseFloat(0); //Point 2 -> z
positions[ i + 6 ] = this.getCoord(array_ref, fig_id, layer, t, 4); //Point 3 -> x
positions[ i + 7 ] = this.getCoord(array_ref, fig_id, layer, t, 5); //Point 3 -> y
positions[ i + 8 ] = parseFloat(0); //Point 3 -> z
}
return positions;
}
toNormalBuffer(fig_id){
var normals = new Float32Array( 49 * 3 * 3 );
for ( var t = 0; t < 49; t += 1 ) {
var i = t*9;
normals[ i + 0 ] = parseFloat(0);
normals[ i + 1 ] = parseFloat(0);
normals[ i + 2 ] = parseFloat(1);
normals[ i + 3 ] = parseFloat(0);
normals[ i + 4 ] = parseFloat(0);
normals[ i + 5 ] = parseFloat(1);
normals[ i + 6 ] = parseFloat(0);
normals[ i + 7 ] = parseFloat(0);
normals[ i + 8 ] = parseFloat(1);
}
return normals;
}
toColorBuffer(fig_id){
var colors = new Float32Array(49 * 3 * 3 );
var color = new THREE.Color();
for ( var t = 0; t < 49; t += 1 ) {
var i = t*9;
var c = this.listOfFigures[fig_id-1][t][6];
color.setRGB(c[0], c[1], c[2]);
colors[ i + 0 ] = color.r;
colors[ i + 1 ] = color.g;
colors[ i + 2 ] = color.b;
colors[ i + 3 ] = color.r;
colors[ i + 4 ] = color.g;
colors[ i + 5 ] = color.b;
colors[ i + 6 ] = color.r;
colors[ i + 7 ] = color.g;
colors[ i + 8 ] = color.b;
}
return colors;
}
}
///////////////////////////////////////////////////////////////////////////
// MAIN CODE //////////////
// Use Mesh-Data from FigureBuilder //////////////
// Rendering & Program Logic //////////////
// Interaction with Figures //////////////
// "Saving/Loading" via Config Button //////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Size of All Figures
var SIZE = 100;
//Background
var HEX_BACKGROUND = 0x151515;
//Scene Light
var HEX_AMBIENT_LIGHT = 0xff00ff;
var HEX_DIRECT_LIGHT = 0x000000;
//Front and Background Colors of Figure
var BG_COLOR = [0,20,20];
var F_COLOR = [200,200,200];
var HEX_FIGURE_AREA_COLOR = 0x011010; //0x333333;
var HEX_FIGURE_AREA_HOVERED = 0x333333; //0xff6666; //Color when hovered
var HEX_FIGURE_AREA_EMISSIVE = 0x000000;
var HEX_FIGURE_OUTLINE = 0x333333;
var HEX_FIGURE_GRID = 0x101010;
//Button Colors
var BUTTON_INACTIVE_COLOR = "transparent";
var BUTTON_ACTIVE_COLOR = "rgba(0,255,255,0.5)";
//Button States
var GRID_ACTIVE = true;
var FIXED_ACTIVE = true;
var SHUFFLE_ACTIVE = false;
var LABELS_ACTIVE = false;
var CONFIG_ACTIVE = false;
var CONTAINER;
var STATS;
var button_labels = document.getElementById( 'button_labels' );
var button_grid = document.getElementById( 'button_grid' );
var button_fixed = document.getElementById( 'button_fixed' );
var button_shuffle = document.getElementById( 'button_shuffle' );
var button_config = document.getElementById( 'button_config' );
var config_span = document.getElementById( 'config' );
var input_config = document.getElementById( 'input_config' );
var copy_config = document.getElementById( 'copy_config' );
var delete_config = document.getElementById( 'delete_config' );
var menu = document.getElementById( 'menu' );
var CAMERA, SCENE;
var RENDERER, LABEL_RENDERER;
var RAYCASTER;
var MOUSE, MOUSE_PYR;
var ARRAY_LF = [];
var GROUP_L, GROUP_P, GROUP_LABEL_NR_L, GROUP_LABEL_NR_P, GROUP_LABEL_NAME;
var FB;
init();
animate();
function init() {
CONTAINER = document.getElementById( 'container' );
////////////////////////////////////////////////////////////////////////////////////////
// Scene Creation
////////////////////////////////////////////////////////////////////////////////////////
CAMERA = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 3500 );
CAMERA.position.z = 2750;
SCENE = new THREE.Scene();
SCENE.background = new THREE.Color( HEX_BACKGROUND );
SCENE.fog = new THREE.Fog( 0x050505, 2000, 3500 );
SCENE.add( new THREE.AmbientLight( HEX_AMBIENT_LIGHT ) );
var light1 = new THREE.DirectionalLight( HEX_DIRECT_LIGHT, 0.5 );
light1.position.set( 1, 1, 1 );
SCENE.add( light1 );
////////////////////////////////////////////////////////////////////////////////////
// Init Figures
////////////////////////////////////////////////////////////////////////////////////
FB = new FigureBuilder(SIZE, F_COLOR, BG_COLOR);
////////////////////////////////////////////////////////////////////////////////////
// Set Materials
////////////////////////////////////////////////////////////////////////////////////
var MATERIAL_AREA = new THREE.MeshPhongMaterial( {
color: HEX_FIGURE_AREA_COLOR,
specular: 0xffffff,
shininess: 250,
side: THREE.DoubleSide,
vertexColors: THREE.VertexColors,
emissive: HEX_FIGURE_AREA_EMISSIVE
} );
var MATERIAL_GRID = new THREE.LineBasicMaterial( {
color: HEX_FIGURE_GRID
} );
var MATERIAL_OUTLINE = new THREE.LineBasicMaterial( {
color: HEX_FIGURE_OUTLINE
} );
////////////////////////////////////////////////////////////////////////////////////
// Helper Function for Creating Meshes
////////////////////////////////////////////////////////////////////////////////////
function createMesh(buffer_positions, buffer_normals, buffer_colors, material){
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.BufferAttribute( buffer_positions, 3 ) );
geometry.addAttribute( 'normal', new THREE.BufferAttribute( buffer_normals, 3 ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( buffer_colors, 3 ) );
return new THREE.Mesh( geometry, material);
}
function createLine(buffer_positions, material){
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.BufferAttribute( buffer_positions, 3 ) );
return new THREE.Line( geometry, material);
}
////////////////////////////////////////////////////////////////////////////////////////
// ////
// + + + + + ////
// + + + + + ////
// + + + + + ////
// + + + + + ////
// + + + + + ////
// ////
////////////////////////////////////////////////////////////////////////////////////////
GROUP_L = new THREE.Group();
GROUP_LABEL_NR_L = new THREE.Group();
GROUP_LABEL_NR_P = new THREE.Group();
GROUP_LABEL_NAME = new THREE.Group();
for(var fig_id = 1; fig_id<=25; fig_id+=1){
var GROUP_LF = new THREE.Group();
var MESH_LF_AREA = createMesh(
FB.toPositionBuffer(fig_id, 0),
FB.toNormalBuffer(fig_id),
FB.toColorBuffer(fig_id),
MATERIAL_AREA
);
var MESH_LF_GRID = createLine(
FB.toPositionBuffer(fig_id, 0),
MATERIAL_GRID
);
var local_pos = FB.positionMapForList[fig_id-1];
MESH_LF_AREA.position.set(local_pos[0],local_pos[1],local_pos[2]);
MESH_LF_GRID.position.set(local_pos[0],local_pos[1],local_pos[2]);
GROUP_LF.add( MESH_LF_AREA );
GROUP_LF.add( MESH_LF_GRID );
GROUP_L.add( GROUP_LF );
var PF_LABEL_DIV = document.createElement( 'div' );
PF_LABEL_DIV.className = 'label';
PF_LABEL_DIV.textContent = fig_id;
PF_LABEL_DIV.style.marginTop = '-1em';
var PF_LABEL = new THREE.CSS2DObject( PF_LABEL_DIV );
GROUP_LABEL_NR_L.add( PF_LABEL );
//Position depending on Slot
PF_LABEL.position.set(local_pos[0],local_pos[1]-FB.SIZE*4/12,local_pos[2]);
var pf_nameDiv = document.createElement( 'div' );
pf_nameDiv.className = 'label';
pf_nameDiv.textContent = "Figure "+FB.getName(fig_id);
pf_nameDiv.style.marginTop = '-1em';
var pf_name = new THREE.CSS2DObject( pf_nameDiv );
GROUP_LABEL_NAME.add( pf_name );
//Position depending on Slot
pf_name.position.set(local_pos[0],local_pos[1]-FB.SIZE*12/4,local_pos[2]);
}
////////////////////////////////////////////////////////////////////////////////////////
// ////
// + ////
// + + + ////
// + + + + + ////
// + + + + + + + ////
// + + + + + + + + + ////
// ////
////////////////////////////////////////////////////////////////////////////////////////
GROUP_P = new THREE.Group();
for(var slot = 1; slot<=25; slot+=1){
var GROUP_PF = new THREE.Group();
var fig_id = FB.getFigureForSlot(slot);
var MATERIAL_PF = new THREE.MeshPhongMaterial( {
color: HEX_FIGURE_AREA_COLOR,
specular: 0xffffff,
shininess: 250,
side: THREE.DoubleSide,
vertexColors: THREE.VertexColors,
opacity: 1.0,
transparent: true,
emissive: HEX_FIGURE_AREA_EMISSIVE
} );
var MESH_PF_AREA = createMesh(
FB.toPositionBuffer(fig_id, 1),
FB.toNormalBuffer(fig_id),
FB.toColorBuffer(fig_id),
MATERIAL_PF
);
var MESH_PF_GRID = createLine(
FB.toPositionBuffer(fig_id, 1),
MATERIAL_GRID
);
//Position in front of Area
MESH_PF_GRID.position.set( 0,0,1 );
var MESH_PF_OUTLINE = createLine(
FB.toPositionBuffer(fig_id, 2),
MATERIAL_OUTLINE
);
GROUP_PF.add( MESH_PF_AREA );
GROUP_PF.add( MESH_PF_GRID );
GROUP_PF.add( MESH_PF_OUTLINE );
GROUP_PF.scale.set(0.99,0.99,0.99);
GROUP_PF.position.set(FB.slotXPosition(slot), FB.slotYPosition(slot), 0 );
var flipped = FB.getIfFlipped(slot);
if( flipped ){ GROUP_PF.rotation.z = Math.PI; } else { GROUP_PF.rotation.z = 0; }
GROUP_PF.name = slot;
GROUP_P.add( GROUP_PF );
var PF_LABEL_DIV = document.createElement( 'div' );
PF_LABEL_DIV.className = 'label';
PF_LABEL_DIV.textContent = fig_id;
PF_LABEL_DIV.style.marginTop = '-1em';
var PF_LABEL = new THREE.CSS2DObject( PF_LABEL_DIV );
PF_LABEL.position.set(FB.slotXPosition(slot), FB.slotYPosition(slot)-20, 0 );
GROUP_LABEL_NR_P.add( PF_LABEL );
}
var POS_X_LIST = -FB.SIZE * 100 * 3/15;
var POS_Y_LIST = 0;
var POS_X_PYR = FB.SIZE * 100 * 3/15;
var POS_Y_PYR = 0;
GROUP_L.position.set( POS_X_LIST, POS_Y_LIST, 0 );
GROUP_LABEL_NR_L.position.set( POS_X_LIST, POS_Y_LIST, 0 );
GROUP_LABEL_NAME.position.set( POS_X_LIST, POS_Y_LIST, 0 );
GROUP_LABEL_NR_P.position.set( POS_X_PYR, POS_Y_PYR, 0 );
GROUP_P.position.set( POS_X_PYR, POS_Y_PYR, 0 );
//GROUP_P.rotation.z = Math.PI*2/3;
SCENE.add( GROUP_L );
SCENE.add( GROUP_P );
SCENE.add( GROUP_LABEL_NR_L );
SCENE.add( GROUP_LABEL_NR_P );
SCENE.add( GROUP_LABEL_NAME );
//Shortcut
ARRAY_LF = GROUP_L.children;
////////////////////////////////////////////////////////////////////////////////////////
// Raycasting & Mouse
////////////////////////////////////////////////////////////////////////////////////////
RAYCASTER = new THREE.Raycaster();
MOUSE = new THREE.Vector2();
MOUSE_PYR = new THREE.Vector2();
////////////////////////////////////////////////////////////////////////////////////////
// RENDERER
////////////////////////////////////////////////////////////////////////////////////////
RENDERER = new THREE.WebGLRenderer();
RENDERER.setPixelRatio( window.devicePixelRatio );
RENDERER.setSize( window.innerWidth, window.innerHeight );
CONTAINER.appendChild( RENDERER.domElement );
STATS = new Stats();
CONTAINER.appendChild( STATS.domElement );
STATS.domElement.id = "stats";
////////////////////////////////////////////////////////////////////////////////////////
// LABEL RENDERER
////////////////////////////////////////////////////////////////////////////////////////
LABEL_RENDERER = new THREE.CSS2DRenderer();
LABEL_RENDERER.setSize( window.innerWidth, window.innerHeight );
LABEL_RENDERER.domElement.style.position = 'absolute';
LABEL_RENDERER.domElement.style.top = 0;
CONTAINER.appendChild( LABEL_RENDERER.domElement );
////////////////////////////////////////////////////////////////////////////////////////
// Event Listener
////////////////////////////////////////////////////////////////////////////////////////
window.addEventListener( 'resize', onWindowResize, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
////////////////////////////////////////////////////////////////////////////////////////
// Init Button CSS
////////////////////////////////////////////////////////////////////////////////////////
updateButtonCSS(GRID_ACTIVE, button_grid);
updateButtonCSS(FIXED_ACTIVE, button_fixed);
updateButtonCSS(SHUFFLE_ACTIVE, button_shuffle);
updateButtonCSS(LABELS_ACTIVE, button_labels);
updateButtonCSS(CONFIG_ACTIVE, button_config);
for(var i = 0; i<GROUP_LABEL_NR_L.children.length; i+=1){ GROUP_LABEL_NR_L.children[i].element.hidden = !(LABELS_ACTIVE); }
for(var i = 0; i<GROUP_LABEL_NR_P.children.length; i+=1){ GROUP_LABEL_NR_P.children[i].element.hidden = !(LABELS_ACTIVE); }
for(var i = 0; i<GROUP_LABEL_NAME.children.length; i+=1){ GROUP_LABEL_NAME.children[i].element.hidden = true; }
if(CONFIG_ACTIVE){ config_span.style.display = "inherit";
}else{ config_span.style.display = "none"; }
updatePyramide();
}
////////////////////////////////////////////////////////////////////////////////////////
// Update Button CSS
////////////////////////////////////////////////////////////////////////////////////////
function updateButtonCSS(status, button) {
if(status){ button.style.background = ""+BUTTON_ACTIVE_COLOR;
}else{ button.style.background = ""+BUTTON_INACTIVE_COLOR; }
}
////////////////////////////////////////////////////////////////////////////////////////
// UPDATE MESHES from changed LOGIC
////////////////////////////////////////////////////////////////////////////////////////
function updatePyramide() {
for(var fig_id = 1; fig_id <= 25; fig_id += 1){
var figure_in_slot = GROUP_P.children[fig_id-1]; //GROUP_P.children = [figure1, figure2, figure3, ...]
var label_in_slot = GROUP_LABEL_NR_P.children[fig_id-1];
var slot = FB.getSlotForFigure(fig_id);
var flipped = FB.getIfFlipped(slot);
var rotation = FB.getFigureRotation(fig_id);
var totalr = 0;
if(flipped){ totalr = Math.PI; }
totalr += rotation * Math.PI*2/3;
figure_in_slot.rotation.z = totalr;
figure_in_slot.position.set(FB.slotXPosition(slot), FB.slotYPosition(slot), 0); //slotXPosition and slotYPosition are fixed constants for each slot
figure_in_slot.position.z = 0;
label_in_slot.position.set(FB.slotXPosition(slot), FB.slotYPosition(slot), 0);
}
setConfig();
}
////////////////////////////////////////////////////////////////////////////////////////
// WINDOW
////////////////////////////////////////////////////////////////////////////////////////
function onWindowResize() {
CAMERA.aspect = window.innerWidth / window.innerHeight;
CAMERA.updateProjectionMatrix();
RENDERER.setSize( window.innerWidth, window.innerHeight );
LABEL_RENDERER.setSize( window.innerWidth, window.innerHeight );
//centerFigures();
}
////////////////////////////////////////////////////////////////////////////////////////
// BUTTONS / INPUTS
////////////////////////////////////////////////////////////////////////////////////////
button_grid.addEventListener( 'click', function () {
GRID_ACTIVE = !GRID_ACTIVE;
updateButtonCSS(GRID_ACTIVE, button_grid);
for(var i = 0; i<GROUP_P.children.length; i+=1){ GROUP_P.children[i].children[1].visible = GRID_ACTIVE; } //Show or Hide: PYRAMIDE GRID
for(var i = 0; i<GROUP_L.children.length; i+=1){ GROUP_L.children[i].children[1].visible = GRID_ACTIVE; } //Show or Hide: LIST GRID
}, false );
button_labels.addEventListener( 'click', function () {
LABELS_ACTIVE = !LABELS_ACTIVE;
updateButtonCSS(LABELS_ACTIVE, button_labels);
for(var i = 0; i<GROUP_LABEL_NR_L.children.length; i+=1){ GROUP_LABEL_NR_L.children[i].element.hidden = !(LABELS_ACTIVE); }
for(var i = 0; i<GROUP_LABEL_NR_P.children.length; i+=1){ GROUP_LABEL_NR_P.children[i].element.hidden = !(LABELS_ACTIVE); }
}, false );
button_fixed.addEventListener( 'click', function () {
FIXED_ACTIVE = !FIXED_ACTIVE;
if(FIXED_ACTIVE){ button_fixed.style.background = ""+BUTTON_ACTIVE_COLOR;
updatePyramide();
}else{ button_fixed.style.background = ""+BUTTON_INACTIVE_COLOR;} //Change GRID-BUTTON CSS
}, false );
button_shuffle.addEventListener( 'click', function () {
SHUFFLE_ACTIVE = !SHUFFLE_ACTIVE;
if(SHUFFLE_ACTIVE){ button_shuffle.style.background = ""+BUTTON_ACTIVE_COLOR;
updatePyramide();
}else{ button_shuffle.style.background = ""+BUTTON_INACTIVE_COLOR;}
}, false );
button_config.addEventListener( 'click', function () {
CONFIG_ACTIVE = !CONFIG_ACTIVE;
updateButtonCSS(CONFIG_ACTIVE, button_config);
if(CONFIG_ACTIVE){ config_span.style.display = "inherit";
}else{ config_span.style.display = "none"; }
}, false );
// Default
// #1m#2m#3m#4m#5m#6m#7m#8m#9m#10m#11m#12m#13m#14m#15m#16m#17m#18m#19m#20m#21m#22m#23m#24m#25m
function loadConfig(string){
var regex = /^([#][0-9][0-9][l|m|r]){25}$/;
var figures = string.split(/['#']+/);
var config_p = Array(25);
var config_r = Array(25);
for(var slot = 1; slot<=25; slot+=1){
var figure = figures[slot];
var fig_id = figure.substring(0,figure.length-1);
fig_id = parseInt(fig_id);
var fig_rotation = figure.substring(figure.length-1,figure.length);
switch(fig_rotation){
case 'l': fig_rotation = -1; break;
case 'm': fig_rotation = 0; break;
case 'r': fig_rotation = 1; break;
default: return;
}
config_p[slot-1] = fig_id;
config_r[fig_id-1] = fig_rotation;
}
if(new Set(config_p).size !== config_p.length ){return;}
for(var i=0; i<config_p.length; i+=1){
var x = config_p[i];
if(x<1||x>25){return;}
}
FB.setConfiguration(config_p, config_r);
updatePyramide();
}
function setConfig(){
var string = "#";
for(var slot = 1; slot <= 25; slot+=1){
var fig_id = FB.getFigureForSlot(slot);
var fig_rot = FB.getFigureRotation(fig_id);
if(fig_id<=9){ string += "0"+fig_id; }else{ string += fig_id; }
switch(fig_rot){
case -1: string += "l"; break;
case 0: string += "m"; break;
case 1: string += "r"; break;
}
string += "#";
}
input_config.value = string;
}
input_config.addEventListener( 'keydown', function (e) {
if (e.keyCode == 13) {
loadConfig(input_config.value);
}
}, false );
input_config.addEventListener( 'click', function (e) {
input_config.select();
}, false );
copy_config.addEventListener( 'click', function () {
var copyText = document.getElementById("input_config"); // Get the text field
copyText.select(); // Select the text field
copyText.setSelectionRange(0, 99999); // For mobile devices
document.execCommand("copy"); // Copy the text inside the text field
}, false );
delete_config.addEventListener( 'click', function () {
var deleteField = document.getElementById("input_config");
deleteField.value = "";
}, false );
////////////////////////////////////////////////////////////////////////////////////////
// MOUSE FIGURE INTERACTION
////////////////////////////////////////////////////////////////////////////////////////
function getPickedFigure(){ return parseInt(PICKED.name, 10); }
function getHoveredFigure(){ return parseInt(HOVERED.name, 10); }
function getPickedSlot(){ return FB.getSlotForFigure(getPickedFigure()); }
////////////////////////////////////////////////////////////////////////////////////////
// MOUSE ACTIONS
////////////////////////////////////////////////////////////////////////////////////////
var MOUSE_DOWN = false;
var DRAGGED = false;
var PICKED = null;
var HOVERED = null;
function updateMousePyr(){
var vector = new THREE.Vector3(MOUSE.x, MOUSE.y, 0.5);
vector.unproject( CAMERA );
var dir = vector.sub( CAMERA.position ).normalize();
var distance = - CAMERA.position.z / dir.z;
var pos = CAMERA.position.clone().add( dir.multiplyScalar( distance ) );
pos.sub(PICKED.parent.position); //Position of Pyramide
MOUSE_PYR = pos;
}
function onDocumentMouseMove( event ) {
if(SHUFFLE_ACTIVE){ return; }
event.preventDefault();
MOUSE.x = ( event.clientX / window.innerWidth ) * 2 - 1;
MOUSE.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// Dragging
DRAGGED = false;
if (MOUSE_DOWN){
if (PICKED){
updateMousePyr();
//Move Picked Figure
PICKED.position.x = MOUSE_PYR.x;
PICKED.position.y = MOUSE_PYR.y;
PICKED.position.z = 1;
PICKED.children[0].material.opacity = 0.7;
//Move Assigned NR Label
GROUP_LABEL_NR_P.children[getPickedFigure()-1].position.set(MOUSE_PYR.x, MOUSE_PYR.y, 0 );
DRAGGED = true;
}
}
// Hovering
RAYCASTER.setFromCamera( MOUSE, CAMERA );
var intersects = RAYCASTER.intersectObjects(GROUP_P.children, true); //--> RAYCASTING ON PYRAMIDE FIGURES
if ( intersects.length > 0 ) { //--> SOMETHING WAS HOVERED
var new_hovered = intersects[intersects.length-1].object.parent; //Pick farest Layer
if(HOVERED != new_hovered){ //HOVERED Object has changed
if(HOVERED){ HOVERED.children[0].material.color.setHex(HEX_FIGURE_AREA_COLOR); } //Reset old HOVERED Object's color
HOVERED = new_hovered; //Set new HOVERED Object
HOVERED.children[0].material.color.setHex(HEX_FIGURE_AREA_HOVERED); //Set new HOVERED Object's color
}
}else{ //--> NOTHING WAS HOVERED
if(HOVERED){ //Reset old HOVERED Object's color
HOVERED.children[0].material.color.setHex(HEX_FIGURE_AREA_COLOR);
HOVERED = null;
}
}
}
function onDocumentMouseDown( event ) {
if(SHUFFLE_ACTIVE){ return; }
RAYCASTER.setFromCamera( MOUSE, CAMERA );
var intersects = RAYCASTER.intersectObjects(GROUP_P.children, true);
if ( intersects.length > 0 ) {
PICKED = intersects[0].object.parent; //GROUP_Pf
}
MOUSE_DOWN = true;
}
function onDocumentMouseUp( event ) {
if(SHUFFLE_ACTIVE){ return; }
//ONE CLICK -> ROTATE (Save to LOGIC)
if(DRAGGED == false){
if(PICKED){
FB.rotateFigure(getPickedFigure());
updatePyramide();
}
}
if(FIXED_ACTIVE){
//DRAG CLICK -> SWITCH (Save to LOGIC)
if(DRAGGED == true){
var slot_picked = getPickedSlot();
var slot_hover = FB.getSlotForFigure(getHoveredFigure());
if(slot_hover){ FB.switchSlotFigures(slot_picked,slot_hover); }
updatePyramide();
}
}
MOUSE_DOWN = false;
if(PICKED){
PICKED.children[0].material.opacity = 1.0; //Reset Opacity After PICKED dropped
PICKED = null;
}
if(HOVERED){
HOVERED.children[0].material.color.setHex(HEX_FIGURE_AREA_COLOR); //Reset HOVERED
HOVERED = null;
}
DRAGGED = false;
}
var t = 0;
var START = true;
function animate() {
requestAnimationFrame( animate );
if(START){
renderStart();
}else{
render();
}
STATS.update();
}
var t_s = 0.0;
function renderStart() {
var zoom = t_s;
var opacity = t_s;
if(t_s >= 1){
//Show Labels
for(var i = 0; i<GROUP_LABEL_NAME.children.length; i+=1){ GROUP_LABEL_NAME.children[i].element.hidden = false; }
//Leave Start-Animation
t_s = 0.0;
START = false;
}
//Fade in Scene and Menu
SCENE.scale.set(zoom,zoom,zoom);
menu.style.opacity = ""+opacity;
RENDERER.render( SCENE, CAMERA );
t_s += 0.01;
}
function render() {
var time = Date.now() * 0.0001;
for (var m = 0; m < ARRAY_LF.length; m+=1) {
var amp = 0.004;
var t = time + m;
ARRAY_LF[m].rotation.z = amp - Math.abs((t * 0.05) % (2*amp) - amp);
}
if(SHUFFLE_ACTIVE){
t += 0.1;
if(t>=1){
FB.setRandomConfiguration();
updatePyramide();
t=0;
}
}
RENDERER.render( SCENE, CAMERA );
LABEL_RENDERER.render( SCENE, CAMERA );
}