420 lines
10 KiB
JavaScript
420 lines
10 KiB
JavaScript
|
// ECMAScript 5 strict mode
|
||
|
/* jshint globalstrict: true*/
|
||
|
/* global THREE, $, document, window, console */
|
||
|
/* global LOADING_BAR_SCALE,ROWS,COLS,PIECE_SIZE, BOARD_SIZE, FLOOR_SIZE, WIREFRAME, DEBUG, Cell, WHITE, BLACK, FEEDBACK, SHADOW */
|
||
|
/* global createCell */
|
||
|
|
||
|
/*
|
||
|
* initPieceFactory and initCellFactory need to be called after
|
||
|
* all ressources are loaded (geometry and texture)
|
||
|
*
|
||
|
* they will create the createPiece and createCell function
|
||
|
* and keep some texture/material objects in a closure to avoid
|
||
|
* unnecessary cloning
|
||
|
*/
|
||
|
|
||
|
"use strict";
|
||
|
var geometries = {};
|
||
|
var textures = {};
|
||
|
function initPieceFactory () {
|
||
|
|
||
|
// common textures
|
||
|
var tiling = 4;
|
||
|
var colors = [];
|
||
|
for(var c = 0; c<2; c++) {
|
||
|
colors[c] = textures['texture/wood-'+c+'.jpg'].clone();
|
||
|
colors[c].tile(tiling);
|
||
|
}
|
||
|
var norm = textures['texture/wood_N.jpg'].clone();
|
||
|
norm.tile(tiling);
|
||
|
var spec = textures['texture/wood_S.jpg'].clone();
|
||
|
spec.tile(tiling);
|
||
|
|
||
|
function createPiece(name,color) {
|
||
|
var size = BOARD_SIZE/COLS * PIECE_SIZE;
|
||
|
// container for the piece and its reflexion
|
||
|
var piece = new THREE.Object3D();
|
||
|
// base material for all the piece (only lightmap changes)
|
||
|
var material = new THREE.MeshPhongMaterial({
|
||
|
color:0xffffff,
|
||
|
specular:0xaaaaaa,
|
||
|
shininess:60.0,
|
||
|
map:colors[color],
|
||
|
normalMap:norm,
|
||
|
specularMap:spec,
|
||
|
wireframe:WIREFRAME
|
||
|
});
|
||
|
material.normalScale.set(0.3,0.3);
|
||
|
|
||
|
// urls of geometry and lightmap
|
||
|
var urlJson = '3D/json/'+name+'.json';
|
||
|
var urlAO = 'texture/'+name+'-ao.jpg';
|
||
|
|
||
|
var geo = geometries[urlJson];
|
||
|
// no need to clone this texture
|
||
|
// since its pretty specific
|
||
|
var light = textures[urlAO];
|
||
|
light.format = THREE.LuminanceFormat;
|
||
|
|
||
|
material.lightMap = light;
|
||
|
|
||
|
var mesh = new THREE.Mesh(geo,material);
|
||
|
if (SHADOW) {
|
||
|
mesh.castShadow = true;
|
||
|
mesh.receiveShadow = true;
|
||
|
}
|
||
|
mesh.scale.set(size,size,size);
|
||
|
// we rotate pieces so they face each other (mostly relevant for knight)
|
||
|
mesh.rotation.y += (color == WHITE) ? -Math.PI/2 : Math.PI/2;
|
||
|
|
||
|
// we create the reflection
|
||
|
// it's a cloned with a negative scale on the Y axis
|
||
|
var reflexion = mesh.clone();
|
||
|
reflexion.scale.y *= -1;
|
||
|
reflexion.material = reflexion.material.clone();
|
||
|
reflexion.material.side = THREE.BackSide;
|
||
|
|
||
|
piece.add(mesh);
|
||
|
piece.add(reflexion);
|
||
|
|
||
|
piece.name = name;
|
||
|
piece.color = color;
|
||
|
|
||
|
return piece;
|
||
|
}
|
||
|
|
||
|
// make it global
|
||
|
window.createPiece = createPiece;
|
||
|
}
|
||
|
|
||
|
function initCellFactory() {
|
||
|
|
||
|
var materials = [];
|
||
|
var tiling = 2;
|
||
|
|
||
|
|
||
|
// common textures
|
||
|
var diff;
|
||
|
var norm = textures['texture/wood_N.jpg'].clone();
|
||
|
norm.tile(tiling);
|
||
|
var spec = textures['texture/wood_S.jpg'].clone();
|
||
|
spec.tile(tiling);
|
||
|
|
||
|
for(var c = 0; c<2; c++) {
|
||
|
|
||
|
diff = textures['texture/wood-'+c+'.jpg'].clone();
|
||
|
diff.tile(tiling);
|
||
|
|
||
|
//common material
|
||
|
materials[c] = new THREE.MeshPhongMaterial({
|
||
|
color:0xffffff,
|
||
|
specular:[0xAAAAAA,0x444444][c],
|
||
|
shininess:30.0,
|
||
|
wireframe:WIREFRAME,
|
||
|
transparent:true,
|
||
|
map:diff,
|
||
|
specularMap:spec,
|
||
|
normalMap:norm,
|
||
|
//blending: THREE.AdditiveBlending,
|
||
|
opacity:0.5
|
||
|
});
|
||
|
//materials[c].normalScale.set(0.5,0.5);
|
||
|
}
|
||
|
|
||
|
function createCell(size,color) {
|
||
|
// container for the cell and its reflexion
|
||
|
var geo = new THREE.PlaneGeometry(size,size);
|
||
|
|
||
|
// randomize uv offset to ad a bit of variety
|
||
|
var randU = Math.random();
|
||
|
var randV = Math.random();
|
||
|
|
||
|
var uvs = geo.faceVertexUvs[0][0];
|
||
|
for (var j = 0; j < uvs.length; j++) {
|
||
|
uvs[j].x += randU;
|
||
|
uvs[j].y += randV;
|
||
|
}
|
||
|
|
||
|
var cell = new THREE.Mesh(geo,materials[color]);
|
||
|
|
||
|
if (SHADOW) {
|
||
|
cell.receiveShadow = true;
|
||
|
}
|
||
|
|
||
|
// by default PlaneGeometry is vertical
|
||
|
cell.rotation.x = -Math.PI/2;
|
||
|
cell.color = color;
|
||
|
return cell;
|
||
|
}
|
||
|
|
||
|
// make it global
|
||
|
window.createCell = createCell;
|
||
|
}
|
||
|
|
||
|
|
||
|
function createChessBoard(size) {
|
||
|
// contains everything that makes the board
|
||
|
var lChessBoard = new THREE.Object3D();
|
||
|
|
||
|
var cellSize = size/COLS;
|
||
|
var square,cell;
|
||
|
|
||
|
for(var i=0; i< ROWS*COLS; i++) {
|
||
|
|
||
|
var col = i%COLS;
|
||
|
var row = Math.floor(i/COLS);
|
||
|
|
||
|
cell = new Cell(i);
|
||
|
square = createCell(cellSize,1-(i+row)%2);
|
||
|
square.position = cell.getWorldPosition();
|
||
|
square.name = cell.position;
|
||
|
|
||
|
lChessBoard.add(square);
|
||
|
}
|
||
|
|
||
|
// some fake inner environment color for reflexion
|
||
|
var innerBoard = new THREE.Mesh (
|
||
|
geometries['3D/json/innerBoard.json'],
|
||
|
new THREE.MeshBasicMaterial({
|
||
|
color:0x783e12
|
||
|
})
|
||
|
);
|
||
|
innerBoard.scale.set(size,size,size);
|
||
|
|
||
|
/// board borders
|
||
|
var tiling = 6;
|
||
|
var wood = textures['texture/wood-0.jpg'].clone();
|
||
|
var spec = textures['texture/wood_S.jpg'].clone();
|
||
|
var norm = textures['texture/wood_N.jpg'].clone();
|
||
|
wood.tile(tiling);
|
||
|
spec.tile(tiling);
|
||
|
norm.tile(tiling);
|
||
|
|
||
|
var geo = geometries['3D/json/board.json'];
|
||
|
geo.computeBoundingBox();
|
||
|
|
||
|
var board = new THREE.Mesh (
|
||
|
geo,
|
||
|
new THREE.MeshPhongMaterial({
|
||
|
color:0xffffff,
|
||
|
map:wood,
|
||
|
specular: 0xffffff,
|
||
|
specularMap: spec,
|
||
|
normalMap: norm,
|
||
|
shininess: 60,
|
||
|
normalScale: new THREE.Vector2(0.2,0.2)
|
||
|
})
|
||
|
);
|
||
|
var hCorrection = 0.62; // yeah I should just create a better geometry
|
||
|
board.scale.set(size,size*hCorrection,size);
|
||
|
lChessBoard.height = geo.boundingBox.min.y * board.scale.y;
|
||
|
|
||
|
if (SHADOW) {
|
||
|
board.receiveShadow = true;
|
||
|
board.castShadow = true;
|
||
|
}
|
||
|
|
||
|
lChessBoard.add(innerBoard);
|
||
|
lChessBoard.add(board);
|
||
|
|
||
|
lChessBoard.name = "chessboard";
|
||
|
return lChessBoard;
|
||
|
}
|
||
|
|
||
|
function createFloor(size,chessboardSize) {
|
||
|
// The floor is a fake plane with a hole in it to allow
|
||
|
// for the fake reflexion trick to work
|
||
|
// so we build it vertices by vertices
|
||
|
|
||
|
// material
|
||
|
var tiling = 30*size/1000;
|
||
|
var material = new THREE.MeshPhongMaterial({
|
||
|
color:0xffffff,
|
||
|
wireframe:WIREFRAME ,
|
||
|
specular:0xaaaaaa,
|
||
|
shininess:30
|
||
|
|
||
|
});
|
||
|
var diff = textures['texture/floor.jpg'];
|
||
|
var spec = textures['texture/floor_S.jpg'];
|
||
|
var norm = textures['texture/floor_N.jpg'];
|
||
|
var light = textures['texture/fakeShadow.jpg'];
|
||
|
|
||
|
diff.tile(tiling);
|
||
|
spec.tile(tiling);
|
||
|
norm.tile(tiling);
|
||
|
light.format = THREE.RGBFormat;
|
||
|
|
||
|
material.map = diff;
|
||
|
material.normalMap = norm;
|
||
|
material.normalScale.set(0.6,0.6);
|
||
|
material.specularMap = spec;
|
||
|
material.lightMap = light;
|
||
|
|
||
|
// geometry
|
||
|
var halfBoard = chessboardSize/2;
|
||
|
var halfSize = size/2;
|
||
|
|
||
|
var floorGeo = new THREE.Geometry();
|
||
|
// outter vertices
|
||
|
floorGeo.vertices.push(new THREE.Vector3(-halfSize,0,-halfSize));
|
||
|
floorGeo.vertices.push(new THREE.Vector3( halfSize,0,-halfSize));
|
||
|
floorGeo.vertices.push(new THREE.Vector3( halfSize,0, halfSize));
|
||
|
floorGeo.vertices.push(new THREE.Vector3(-halfSize,0, halfSize));
|
||
|
// hole vertices
|
||
|
floorGeo.vertices.push(new THREE.Vector3(-halfBoard,0,-halfBoard));
|
||
|
floorGeo.vertices.push(new THREE.Vector3( halfBoard,0,-halfBoard));
|
||
|
floorGeo.vertices.push(new THREE.Vector3( halfBoard,0, halfBoard));
|
||
|
floorGeo.vertices.push(new THREE.Vector3(-halfBoard,0, halfBoard));
|
||
|
|
||
|
floorGeo.faceVertexUvs[ 0 ] = [];
|
||
|
floorGeo.faceVertexUvs[ 1 ] = [];
|
||
|
|
||
|
/*
|
||
|
* vertices uvs-lightmap
|
||
|
* 0-----------1 80-----------80
|
||
|
* |\ /| |\ /|
|
||
|
* | \ / | | \ / |
|
||
|
* | \ / | | \ / |
|
||
|
* | 4---5 | | 0---0 |
|
||
|
* | | | | | | | |
|
||
|
* | 7---6 | | 0---0 |
|
||
|
* | / \ | | / \ |
|
||
|
* | / \ | | / \ |
|
||
|
* |/ \| |/ \|
|
||
|
* 3-----------2 80-----------80
|
||
|
*/
|
||
|
|
||
|
// all normals just points upward
|
||
|
var normal = new THREE.Vector3( 0, 1, 0 );
|
||
|
|
||
|
// list of vertex index for each face
|
||
|
var faces = [
|
||
|
[0,4,5,1],
|
||
|
[1,5,6,2],
|
||
|
[2,6,7,3],
|
||
|
[3,7,4,0]
|
||
|
];
|
||
|
|
||
|
faces.forEach( function(f) {
|
||
|
var uvs1 = [];
|
||
|
var uvs2 = [];
|
||
|
var lightU,lightV;
|
||
|
f.forEach(function(v,i) {
|
||
|
// we linearily transform positions
|
||
|
// from a -halfSize-halfSize space
|
||
|
// to a 0-1 space
|
||
|
uvs1.push(new THREE.Vector2(
|
||
|
(floorGeo.vertices[v].x+halfSize)/size,
|
||
|
(floorGeo.vertices[v].z+halfSize)/size
|
||
|
));
|
||
|
lightU = (v < 4) ? 80 : 0;
|
||
|
lightV = (i < 2) ? 0 : 1;
|
||
|
uvs2.push(new THREE.Vector2(lightU,lightV));
|
||
|
});
|
||
|
|
||
|
// we create a new face folowing the faces list
|
||
|
var face = new THREE.Face4(
|
||
|
f[0],f[1],f[2],f[3]
|
||
|
);
|
||
|
|
||
|
// and apply normals (without this, no proper lighting)
|
||
|
face.normal.copy( normal );
|
||
|
face.vertexNormals.push(
|
||
|
normal.clone(),
|
||
|
normal.clone(),
|
||
|
normal.clone(),
|
||
|
normal.clone()
|
||
|
);
|
||
|
|
||
|
// add the face to the geometry's faces list
|
||
|
floorGeo.faces.push(face);
|
||
|
|
||
|
// add uv coordinates to uv channels.
|
||
|
floorGeo.faceVertexUvs[ 0 ].push(uvs1); // for diffuse/normal
|
||
|
floorGeo.faceVertexUvs[ 1 ].push(uvs2); // for lightmap
|
||
|
|
||
|
});
|
||
|
|
||
|
// not sure it's needed but since it's in THREE.PlaneGeometry...
|
||
|
floorGeo.computeCentroids();
|
||
|
|
||
|
var floor = new THREE.Mesh(floorGeo,material);
|
||
|
|
||
|
if(SHADOW) {
|
||
|
floor.receiveShadow = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
floor.name = "floor";
|
||
|
return floor;
|
||
|
}
|
||
|
|
||
|
// special highlighting materials
|
||
|
var validCellMaterial = null;
|
||
|
function createValidCellMaterial () {
|
||
|
validCellMaterial = [];
|
||
|
var tiling = 2;
|
||
|
|
||
|
|
||
|
// common textures
|
||
|
var diff;
|
||
|
var norm = textures['texture/wood_N.jpg'].clone();
|
||
|
norm.tile(tiling);
|
||
|
var spec = textures['texture/wood_S.jpg'].clone();
|
||
|
spec.tile(tiling);
|
||
|
|
||
|
for(var c = 0; c<2; c++) {
|
||
|
|
||
|
diff = textures['texture/wood-1.jpg'].clone();
|
||
|
diff.tile(tiling);
|
||
|
|
||
|
//common material
|
||
|
validCellMaterial[c] = new THREE.MeshPhongMaterial({
|
||
|
color:0x00ff00,
|
||
|
specular:0x999999,
|
||
|
shininess:60.0,
|
||
|
wireframe:WIREFRAME,
|
||
|
map:diff,
|
||
|
specularMap:spec,
|
||
|
normalMap:norm
|
||
|
});
|
||
|
//materials[c].normalScale.set(0.5,0.5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var selectedMaterial = null;
|
||
|
function createSelectedMaterial() {
|
||
|
selectedMaterial = [];
|
||
|
var tiling = 4;
|
||
|
|
||
|
|
||
|
// common textures
|
||
|
var diff;
|
||
|
var norm = textures['texture/wood_N.jpg'].clone();
|
||
|
norm.tile(tiling);
|
||
|
var spec = textures['texture/wood_S.jpg'].clone();
|
||
|
spec.tile(tiling);
|
||
|
|
||
|
for(var c = 0; c<2; c++) {
|
||
|
|
||
|
diff = textures['texture/wood-1.jpg'].clone();
|
||
|
diff.tile(tiling);
|
||
|
|
||
|
//common material
|
||
|
selectedMaterial[c] = new THREE.MeshPhongMaterial({
|
||
|
color:0x00ff00,
|
||
|
emissive:0x009900,
|
||
|
specular:0x999999,
|
||
|
shininess:60.0,
|
||
|
wireframe:WIREFRAME,
|
||
|
transparent:false,
|
||
|
map:diff,
|
||
|
specularMap:spec,
|
||
|
normalMap:norm
|
||
|
//opacity:0.4
|
||
|
});
|
||
|
selectedMaterial[c].normalScale.set(0.3,0.3);
|
||
|
}
|
||
|
|
||
|
}
|