emsApplication/applications/WebConfigure/web/js/arena.js

1527 lines
45 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

var Arena ={
create:function(id, config, options){
var ar = {};
///////// function init code here /////////
ar.init = function(id){
// public vars
ar.units = [];
ar.options = {
showSky: true,
dynamicSky: false,
showShadow: true,
dynamicShadow: true
};
ar.id = id;
ar.domId = "#" + id;
ar.cruise = {
target : new THREE.Vector3(),
lon: 90,
lat: 0,
phi: 0,
theta : 0
};
ar.temp = {};
ar.shape3Ds = [];
ar.mouse = new THREE.Vector2();
function getViewSize(){
var SCREEN_WIDTH = window.innerWidth - $(ar.domId).offset().left;
var SCREEN_HEIGHT = window.innerHeight - $(ar.domId).offset().top - 17;
return { width: SCREEN_WIDTH, height: SCREEN_HEIGHT };
}
function initScene(){
ar.raycaster = new THREE.Raycaster();
ar.scene = new THREE.Scene();
//ar.scene.overrideMaterial = new THREE.MeshDepthMaterial();
}
function initRender(){
if(Detector.webgl){
ar.renderer = new THREE.WebGLRenderer({ antialias:true});
if (ar.options.showShadow){
ar.renderer.shadowMap.enabled = true;
ar.renderer.shadowMapSoft = true;
ar.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
}
console.info("webGL render is working.");
}else{
ar.renderer = new THREE.CanvasRenderer(); //WebGLRenderer
console.info("canvas render is working. restart brower remote to enable WebGL");
}
ar.renderer.sortObjects = false;
ar.renderer.setClearColor( 0x0086b3 ,1);
ar.renderer.setPixelRatio( window.devicePixelRatio );
ar.renderer.setSize(getViewSize().width,getViewSize().height);
}
function initCamera(){
// camera attributes
var VIEW_ANGLE = 45, ASPECT = getViewSize().width / getViewSize().height,
NEAR = 10, FAR = 50000;
ar.camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
ar.camera.position.set(-100, 1600, 1800);
ar.camera.lookAt(ar.scene.position);
ar.scene.add(ar.camera);
//ar.scene.fog = new THREE.Fog( 0xffffff, 1, 5000 );
//ar.scene.fog.color.setHSL( 0.6, 0, 1 );
}
function initSky(){
var texture_placeholder = document.createElement( 'canvas' );
texture_placeholder.width = 128;
texture_placeholder.height = 128;
var context = texture_placeholder.getContext( '2d' );
context.fillStyle = 'rgb( 200, 200, 200 )';
context.fillRect( 0, 0, texture_placeholder.width, texture_placeholder.height );
function loadTexture( path ) {
var texture = new THREE.Texture( texture_placeholder );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
var image = new Image();
image.onload = function () {
texture.image = this;
texture.needsUpdate = true;
};
image.src = path;
return material;
}
var materials = [
loadTexture('/img/3d/skybox/skybox_02.png'),
loadTexture('/img/3d/skybox/skybox_04.png'),
loadTexture('/img/3d/skybox/skybox_05.png'),
loadTexture('/img/3d/skybox/skybox_06.png'),
loadTexture('/img/3d/skybox/skybox_01.png'),
loadTexture('/img/3d/skybox/skybox_03.png')
];
// var materials = [
// loadTexture( '/img/3d/skybox/px.jpg' ), // right
// loadTexture( '/img/3d/skybox/nx.jpg' ), // left
// loadTexture( '/img/3d/skybox/py.jpg' ), // top
// loadTexture( '/img/3d/skybox/ny.jpg' ), // bottom
// loadTexture( '/img/3d/skybox/pz.jpg' ), // back
// loadTexture( '/img/3d/skybox/nz.jpg' ) // front
// ];
var mesh = new THREE.Mesh(
new THREE.BoxGeometry( 30000, 30000, 30000, 7, 7, 7 ),
new THREE.MeshFaceMaterial( materials ) );
mesh.scale.x = - 1;
ar.scene.add( mesh );
}
function initResize(){
$(window).resize(function (){
ar.camera.aspect = getViewSize().width / getViewSize().height;
ar.camera.updateProjectionMatrix();
ar.renderer.setSize( getViewSize().width, getViewSize().height);
});
}
function initControl(){
//ar.controls = new THREE.OrbitControls(ar.camera, ar.renderer.domElement);
ar.controls = new THREE.OrbitControls( ar.camera );
ar.controls.addEventListener( 'change', ar.render );
ar.controls.minDistance = 500;
ar.controls.maxDistance = 5000;
ar.controls.maxPolarAngle = Math.PI * 0.5;
//ar.controls.minPolarAngle = Math.PI * 0.1;
ar.container.style.position = "relative";
var btnContainer = document.createElement('div');
btnContainer.id = "btnContainer";
btnContainer.style.cssText = "position:absolute;left:20px;bottom:20px;margin:10px;";
var vi = document.createElement('img');
vi.id = "veilimg";
vi.style.cssText = "padding:3px;cursor:pointer;";
vi.src = 'img/3d/veilView-h.png';
vi.onclick = function(){
if (this.src.indexOf('img/3d/veilView-h.png') >= 0)
{
this.src = 'img/3d/veilView-i.png';
document.getElementById("overimg").src="img/3d/overview-h.png";
ar.cartoon('veilview');
}
};
var oi = document.createElement('img');
oi.id = "overimg";
oi.style.cssText = "padding:3px;cursor:pointer;";
oi.src = "img/3d/overview-h.png";
oi.onclick = function(){
if (this.src.indexOf('img/3d/overview-h.png') >= 0)
{
this.src = 'img/3d/overview-i.png';
document.getElementById("veilimg").src="img/3d/veilView-h.png";
ar.cartoon('overview');
}
};
btnContainer.appendChild(vi);
btnContainer.appendChild(oi);
ar.container.appendChild(btnContainer);
}
function initDebugParts(){
// axes
var axes = new THREE.AxisHelper(100);
ar.scene.add( axes );
// displays current and past frames per second attained by scene
ar.stats = new Stats();
ar.stats.domElement.style.position = 'absolute';
ar.stats.domElement.style.bottom = '0px';
ar.stats.domElement.style.zIndex = 100;
ar.container.appendChild(ar.stats.domElement);
// Grid
var size = 800, step = 80;
var geometry = new THREE.Geometry();
for (var i = -size; i <= size; i += step) {
geometry.vertices.push(new THREE.Vector3(-size, 0, i));
geometry.vertices.push(new THREE.Vector3(size, 0, i));
geometry.vertices.push(new THREE.Vector3(i, 0, -size));
geometry.vertices.push(new THREE.Vector3(i, 0, size));
}
var material = new THREE.LineBasicMaterial({color: 0xeeeeee, opacity: 0.7});
var line = new THREE.Line(geometry, material, THREE.LinePieces);
ar.scene.add(line);
//ArrowHelper
var directionV3 = new THREE.Vector3(1, 0, 1);
var originV3 = new THREE.Vector3(0, 200, 0);
// 100 is length, 20 and 10 are head length and width
var arrowHelper = new THREE.ArrowHelper(directionV3, originV3, 100, 0xff0000, 20, 10);
ar.scene.add(arrowHelper);
// 3. BoundingBoxHelper
//bboxHelper = new THREE.BoundingBoxHelper(group, 0x999999);
//ar.scene.add(bboxHelper);
}
function defineMouseBehavior(){
ar.container.addEventListener( 'mousemove', onDocumentMouseMove, false );
ar.container.addEventListener( 'mousedown', onDocumentMouseDown, false );
function onDocumentMouseMove( event ) {
ar.mouse.x = ( (event.clientX - $(ar.domId).position().left)/ $(ar.domId).width()) * 2 - 1;
ar.mouse.y = - ( (event.clientY - $(ar.domId).position().top) / $(ar.domId).height()) * 2 + 1;
event.preventDefault();
}
function onDocumentMouseDown( e ) {
e.preventDefault();
if (ar.INTERSECTED){
var shp = ar.getShapeByMesh(ar.INTERSECTED);
if (shp.config.bindings.length > 0) {
var devId = shp.config.bindings[0].id;
ar.options.shell.$location.url('/deviceInfo/' + devId);
//alert(angular.toJson(shp.config));
}
}
}
}
function attachToDom(){
ar.container = document.getElementById(ar.id);
ar.container.appendChild(ar.renderer.domElement);
}
initScene();
initRender();
initCamera();
attachToDom();
if (ar.options.showSky) initSky();
initResize();
initControl();
//initDebugParts();
defineMouseBehavior();
};
ar.clear = function(){
ar.shape3Ds = [];
};
ar.load = function(config){
ar.clear();
if (config) {
ar.loadConfig = config;
}
else {
ar.loadConfig = bn.demoConfig;
}
ar.loadConfig.shapes.forEach(function (shp) {
if (shp.param3D) ar.loadUnit(shp.param3D);
});
ar.initLight();
};
ar.loadUnit = function(param) {
var ut = _.find(ar.units, function (item) {
return item.name === param.unit;
});
if (_.isUndefined(ut)) return;
if (_.isUndefined(ut.create)) return;
var mesh = ut.create(param);
mesh.unit = ut;
var shp = _.extend({}, ar.shape3DClass);
shp.mesh = mesh;
shp.config = param;
shp.id = _.uniqueId();
ar.shape3Ds.push(shp);
ar.scene.add(mesh);
};
ar.animate = function(){
ar.aniframeId = requestAnimationFrame(ar.animate);
TWEEN.update();
ar.render();
ar.controls.update();
};
ar.render = function(){
if (!ar) return;
ar.update();
ar.renderer.render(ar.scene, ar.camera);
};
ar.update = function() {
if (ar.options.dynamicSky){
ar.cruise.lon += 0.1;
ar.cruise.lat = Math.max( - 85, Math.min( 85, ar.cruise.lat ) );
ar.cruise.phi = THREE.Math.degToRad( 90 - ar.cruise.lat );
ar.cruise.theta = THREE.Math.degToRad( ar.cruise.lon );
ar.cruise.target.x = 500 * Math.sin( ar.cruise.phi ) * Math.cos( ar.cruise.theta );
ar.cruise.target.y = 500 * Math.cos( ar.cruise.phi );
ar.cruise.target.z = 500 * Math.sin( ar.cruise.phi ) * Math.sin( ar.cruise.theta );
ar.camera.lookAt( ar.cruise.target );
}
if (ar.options.dynamicShadow){
var timer = Date.now() * 0.0001;
ar.light.position.x = Math.sin(timer) * 1000;
ar.light.position.z = Math.cos(timer) * 1000;
ar.light.target.position.set(0, 0, 0);
}
ar.shape3Ds.forEach(function(shp){
if (shp.mesh.unit.isFlat) shp.mesh.lookAt( ar.camera.position );
});
// high light mouse indicator
ar.raycaster.setFromCamera( ar.mouse, ar.camera );
var intersects = ar.raycaster.intersectObjects( ar.scene.children, true );
if ( intersects.length > 0 ) {
if ( ar.INTERSECTED != intersects[ 0 ].object ) {
if ( ar.INTERSECTED ) ar.util.maskColor(ar.INTERSECTED, ar.INTERSECTED.currentHex);
ar.INTERSECTED = intersects[ 0 ].object;
ar.INTERSECTED.currentHex = ar.util.getMaskColor(ar.INTERSECTED);
ar.util.maskColor(ar.INTERSECTED, 0x223366);
}
} else {
if ( ar.INTERSECTED ) ar.util.maskColor(ar.INTERSECTED, ar.INTERSECTED.currentHex);
ar.INTERSECTED = null;
}
};
ar.getUnit = function(name){
return _.find(ar.units, function (unit) {
return unit.name === name;
});
};
ar.initLight = function () {
//泛光可调整整个房间的明暗度
//var ambient = new THREE.AmbientLight( 0x888888);
//ar.scene.add( ambient );
//半球面环境光,模拟天空到大地的光线,可作为主环境光
var envlight = new THREE.HemisphereLight( 0xffffff, 0xA2C9ED, 0.8);
//var envlight = new THREE.HemisphereLight( 0x888888, 0x111111, 0.8);
//envlight.position.set( 0, 1500, 0 );
//envlight.shadowCameraFov = 60;
ar.scene.add(envlight);
// 5000 is sphere size, 3000 is arrow length
//var hlightHelper = new THREE.HemisphereLightHelper(envlight, 10000, 1000);
//ar.scene.add(hlightHelper);
//平行光,用于产生阴影
var light = new THREE.DirectionalLight(0x222222);
light.position.set(0, 1000, 2000);
light.target.position.set(0, 0, 0);
light.castShadow = true;
light.shadowDarkness = 0.7;
//light.shadowCameraNear = 2;
//light.shadowCameraFar = 5000;
light.shadowCameraLeft = -3000;
light.shadowCameraRight = 3000;
light.shadowCameraTop = 3000;
light.shadowCameraBottom = -3000;
//light.shadowCameraFov = 60000;
light.shadowMapWidth = light.shadowMapHeight = 1024;
ar.scene.add(light);
ar.light = light;
//ar.camera.updateMatrix();
//var cameraHelper = new THREE.CameraHelper( light.shadow );
//this.scene.add(cameraHelper);
//// 50 is helper size
//dlightHelper = new THREE.DirectionalLightHelper(light, 500);
//ar.scene.add(dlightHelper);
};
ar.dispose = function(){
var disposeObject = function(obj){
for(var b in obj){
if(typeof(obj[b]) === "function" && obj[b].name === "event"){
obj[b] = undefined;
}
else if(typeof(obj[b]) === "function" && obj[b].length > 0){
disposeObject(obj[b]);
}
else if(typeof(obj[b]) === "object" && b === "dispatch"){
disposeObject(obj[b]);
}
}
};
var disposeNode = function(node)
{
if (node instanceof THREE.Camera)
{
node = undefined;
}
else if (node instanceof THREE.Light)
{
if (!node.dispose){
disposeObject(node);
}
else
node.dispose ();
node = undefined;
}
else if (node instanceof THREE.Mesh)
{
if (node.geometry)
{
node.geometry.dispose ();
node.geometry = undefined;
delete node.geometry;
}
if (node.material)
{
if (node.material instanceof THREE.MeshFaceMaterial)
{
$.each (node.material.materials, function (idx, mtrl)
{
if (!mtrl) return;
mtrl.dispose();
if (mtrl.map)
{
mtrl.map.dispose();
mtrl.map = undefined;
delete mtrl.map;
}
if (mtrl.lightMap) mtrl.lightMap.dispose();
if (mtrl.bumpMap) mtrl.bumpMap.dispose();
if (mtrl.normalMap) mtrl.normalMap.dispose();
if (mtrl.specularMap) mtrl.specularMap.dispose();
if (mtrl.envMap) mtrl.envMap.dispose();
mtrl.dispose(); // disposes any programs associated with the material
mtrl = undefined;
delete mtrl;
});
}
else
{
if (node.material.map)
{
node.material.map.dispose();
node.material.map = undefined;
delete node.material.map;
}
if (node.material.lightMap) node.material.lightMap.dispose ();
if (node.material.bumpMap) node.material.bumpMap.dispose ();
if (node.material.normalMap) node.material.normalMap.dispose ();
if (node.material.specularMap) node.material.specularMap.dispose ();
if (node.material.envMap) node.material.envMap.dispose ();
node.material.dispose (); // disposes any programs associated with the material
node.material = undefined;
delete node.material;
}
}
node = undefined;
}
else if (node instanceof THREE.Object3D)
{
node = undefined;
delete node;
}
};
var disposeHierarchy = function(node, callback)
{
for (var i = node.children.length - 1; i >= 0; i--)
{
var child = node.children[i];
disposeHierarchy (child, callback);
callback (child);
}
};
//stop data pooling
if (ar.provider) ar.provider.dispose();
//remove event for controller
$(window).off();
$(window).unbind();
$(document).off();
$(document).unbind();
$(ar.domId).off();
$(ar.domId).unbind();
if (ar.renderer) $(ar.renderer.domElement).off();
//stop animation
TWEEN.removeAll();
if (ar.aniframeId) window.cancelAnimationFrame(ar.aniframeId);
//remove shapes
// if (ar.shape3Ds){
// ar.shape3Ds.forEach(function(shp){
// if (shp.mesh){
// ar.scene.remove(shp.mesh);
// disposeHierarchy(shp.mesh, disposeNode);
// }
// });
// disposeObject(ar.shape3Ds);
// ar.shape3Ds = undefined;
// delete ar.shape3Ds;
// }
//remove scene
if (ar.controls) ar.controls.dispose();
if (ar.raycaster) disposeObject(ar.raycaster);
// $.each(ar.scene.children, function(idx, obj) {
// if (obj !== undefined) {
// if (obj.geometry) {
// obj.geometry.dispose();
// }
// if (obj.material) {
// if (obj.material instanceof THREE.MeshFaceMaterial) {
// $.each(obj.material.materials, function(idx, obj) {
// obj.dispose();
// });
// } else {
// obj.material.dispose();
// }
// }
// if (obj.dispose) {
// obj.dispose();
// }
// }
// });
//clear all resource
if (ar.camera) disposeObject(ar.camera);
//if (ar.scene) disposeHierarchy (ar.scene, disposeNode);
if (ar.container) disposeObject(ar.container);
if (ar.renderer)
{
ar.renderer.forceContextLoss();
ar.renderer.context = null;
ar.renderer.domElement = null;
disposeObject(ar.renderer);
ar.renderer = null;
}
doDispose(ar.scene);
function doDispose(obj) {
if (obj !== null) {
for (var i = 0; i < obj.children.length; i++) {
doDispose(obj.children[i]);
}
if (obj.geometry) {
obj.geometry.dispose();
obj.geometry = undefined;
}
if (obj.material) {
if (obj.material instanceof THREE.MeshFaceMaterial) {
$.each(obj.material.materials, function(idx, o) {
if (!o) return;
if (o.map)
{
o.map.dispose();
o.map = undefined;
delete o.map;
}
o.dispose();
});
} else {
obj.material.dispose();
}
}
if(obj.dispose) {
obj.dispose();
}
}
obj = undefined;
}
ar.scene = null;
disposeObject(ar);
ar = undefined;
};
ar.cartoon = function(type){
if (type == "overview"){
var position = {x:0,y:3000,z:0};
var target = {x:0,y:0,z:-1};
ar.tweenCamera(position, target);
}
if (type == "veilview"){
var position = {x:-3000,y:3000,z:-3000};
var target = {x:0,y:0,z:0};
ar.tweenCamera(position, target);
}
};
ar.tweenCamera = function tweenCamera(position, target){
//TWEEN.removeAll();
new TWEEN.Tween(ar.camera.position).to({
x: position.x,
y: position.y,
z: position.z
},3000).easing(TWEEN.Easing.Linear.None).onUpdate(function () {
ar.camera.lookAt(target);
}).onComplete(function () {
}).start();
};
ar.getShapeByMesh = function (mesh){
if (!mesh) return;
var obj = mesh;
while(!(obj.parent instanceof THREE.Scene)){
obj = obj.parent;
}
var selected;
ar.shape3Ds.forEach(function(shp){
if (shp.mesh === obj){
selected = shp;
}
});
return selected;
};
ar.loadUnits = function(){
ar.units = [
{
name : "floor",
buildFloor: function(param){
//因为SVG无法使用底图只能使用UV贴图作为地板非常难看。
//这里取消平面自动地板生成功能可生成不规则地板限制为仅能使用矩形地板使用BOX模拟
//所以下面代码注释掉:
//var floorG = ar.transformSVGPath(param.path);
//var planeMesh = ar.createShape(floorG, 0xdddddd, 0, 0, 0, Math.PI/2, 0, 0, 1);
//group.add(planeMesh);
//planeMesh.geometry.center();
var tileSize = 64;
var floorTexture = new THREE.TextureLoader().load(param.floorTexture);
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( param.floorWidth / tileSize, param.floorHeight / tileSize );
var floorMaterial = new THREE.MeshPhongMaterial( {
map: floorTexture, side: THREE.DoubleSide} );
var floorGeometry = new THREE.PlaneGeometry(param.floorWidth, param.floorHeight,1,1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
floor.receiveShadow = true;
return floor;
},
create: function (param){
//create an empty container
var group = new THREE.Object3D();
var floor = this.buildFloor(param);
group.add(floor);
//get enclosure lines
var lines = [];
var lineX1 = {};
lineX1.start = {x: -(param.floorWidth / 2), y:0, z: -(param.floorHeight / 2)};
lineX1.end = {x: param.floorWidth / 2, y:0, z: -(param.floorHeight / 2)};
lines.push(lineX1);
var lineX2 = {};
lineX2.start = {x: -(param.floorWidth / 2), y:0, z: param.floorHeight / 2};
lineX2.end = {x: param.floorWidth / 2, y:0, z: param.floorHeight / 2};
lines.push(lineX2);
var lineX3 = {};
lineX3.start = {x: -(param.floorWidth / 2), y:0, z: -(param.floorHeight / 2)};
lineX3.end = {x: -(param.floorWidth / 2), y:0, z: param.floorHeight / 2};
lines.push(lineX3);
var lineX4 = {};
lineX4.start = {x: param.floorWidth / 2, y:0, z: -(param.floorHeight / 2)};
lineX4.end = {x: param.floorWidth / 2, y:0, z: param.floorHeight / 2};
lines.push(lineX4);
//build walls
lines.forEach(function(line){
var mold = ar.util.getMold(param.moldId);
group.add(ar.util.buildWall(mold, line));
});
return group;
}
},{
name : "door",
create: function (param) {
return ar.util.buildWallPart(param);
}
//},{
// name : "window",
// create: function (param) {
// return ar.util.buildWallPart(param);
// }
},{
name:"rack",
create: function(param){
var mold = ar.util.getMold(param.moldId);
var faces = [];
// order of faces: x+,x-,y+,y-,z+,z-
var rightFace = ar.util.newFace(mold.faces.rightFace);
faces.push(rightFace);
var leftFace = ar.util.newFace(mold.faces.leftFace);
faces.push(leftFace);
var topFace = ar.util.newFace(mold.faces.topFace);
faces.push(topFace);
var bottomFace = ar.util.newFace(mold.faces.bottomFace);
faces.push(bottomFace);
var frontFace = ar.util.newFace(mold.faces.frontFace);
faces.push(frontFace);
var backFace = ar.util.newFace(mold.faces.backFace);
faces.push(backFace);
var cubeMaterials = new THREE.MeshFaceMaterial(faces);
var cubeGeometry = new THREE.CubeGeometry(
mold.size.width, mold.size.high, mold.size.depth);
var cube = new THREE.Mesh(cubeGeometry, cubeMaterials);
cube.position.x = param.position.x;
cube.position.y = mold.size.high / 2 + param.aboveGround;
cube.position.z = param.position.z;
//if (param.angle > 0 )
cube.rotateY( 0 - ar.util.radians(param.angle));
cube.castShadow = true;
return cube;
}
},{
name:"line",
create: function(param){
var geometry = new THREE.Geometry();
param.lines.forEach(function(line){
geometry.vertices.push(new THREE.Vector3(
line.start.x,
line.start.y,
line.start.z
));
geometry.vertices.push(new THREE.Vector3(
line.end.x,
line.end.y,
line.end.z
));
});
var m = new THREE.LineBasicMaterial({
color: param.color,fog:true});
var line = new THREE.Line(geometry, m);
return line;
}
},{
name:"flat",
isFlat:true,
create: function(param){
var mold = ar.util.getMold(param.moldId);
var obj = ar.util.flatObject(param, mold,param.position, parseFloat(param.aboveGround));
return obj.mesh;
}
},{
name:"wallPath",
create: function(param){
var group = new THREE.Object3D();
var mold = ar.util.getMold(param.moldId);
if (param.moldId !== "wallpath-null")
{
param.lines.forEach(function(line){
group.add(ar.util.buildWall(mold, line));
});
}
//if (param.angle > 0 )
group.rotateY( 0 - ar.util.radians(param.angle));
return group;
}
},{
name:"camera",
create: function(param){
//var transparentColor = 0xffffff;
//var size = {x:64,y:64};
//var imgurl = "img/3d/CCTV-icon.png";
//
//var obj = ar.util.flatObject(imgurl, transparentColor,
// size,param.position);
//
//return obj.mesh;
var geometry = new THREE.SphereGeometry( 30, 16, 16 );
var material = new THREE.MeshBasicMaterial( {
map: THREE.ImageUtils.loadTexture('img/3d/global.jpg')});
var sphere = new THREE.Mesh( geometry, material );
sphere.position.x = param.position.x;
sphere.position.y = param.position.y;
sphere.position.z = param.position.z;
return sphere;
}
}
];
};
ar.shape3DClass = {
mesh: undefined,
tws:[],
defaultColors:[],
update:function(status){
if (status.state === this.alarmLevel) return;
this.alarmLevel = status.state;
var needRemove=null;
this.tws.forEach(function(fso){
if (fso.id === this.id)
{
fso.twarray.forEach(function(tw){
tw.stop();
});
needRemove = fso;
}
});
this.tws = _.without(this.tws, needRemove);
this.resetColor();
if (this.alarmLevel == 0) return;
this.shining(this.alarmLevel);
},
resetColor:function(){
var that = this;
if (that.mesh.material instanceof THREE.MultiMaterial)
{
var i=0;
that.mesh.material.materials.forEach(
function(m) {
m.color = {r:1,g:1,b:1};
});
}
},
shining: function(alarmLevel){
var that = this;
var color = {r:1,g:1,b:1};
switch(alarmLevel)
{
case "1":
color={r:0,g:0,b:2};
break;
case "2":
color={r:2,g:2,b:0};
break;
case "3":
color={r:2, g: 1, b:0};
break;
case "4":
color={r:2, g: 0, b:0};
break;
default:
}
if (that.mesh.material instanceof THREE.MultiMaterial)
{
var kso = {id:that.id,twarray:[]};
that.mesh.material.materials.forEach(function(m){
var tw = new TWEEN.Tween(m.color)
.to(color, 3000)
.repeat(Infinity)
.easing(TWEEN.Easing.Quartic.InOut)
.start();
kso.twarray.push(tw);
});
that.tws.push(kso);
}
}
};
ar.util = {};
ar.util.createShape = function ( shape, color, x, y, z, rx, ry, rz, s ) {
// flat shape like svg
var geometry = new THREE.ShapeGeometry( shape );
var material = new THREE.MeshBasicMaterial({
color: color,
side: THREE.DoubleSide,
overdraw: true
});
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( x, y, z );
mesh.rotation.set( rx, ry, rz );
mesh.scale.set( s, s, s );
return mesh;
};
ar.util.transformSVGPath = function (pathStr) {
const DIGIT_0 = 48, DIGIT_9 = 57, COMMA = 44, SPACE = 32, PERIOD = 46,
MINUS = 45;
var path = new THREE.Shape();
var idx = 1, len = pathStr.length, activeCmd,
x = 0, y = 0, nx = 0, ny = 0, firstX = null, firstY = null,
x1 = 0, x2 = 0, y1 = 0, y2 = 0,
rx = 0, ry = 0, xar = 0, laf = 0, sf = 0, cx, cy;
function eatNum() {
var sidx, c, isFloat = false, s;
// eat delims
while (idx < len) {
c = pathStr.charCodeAt(idx);
if (c !== COMMA && c !== SPACE)
break;
idx++;
}
if (c === MINUS)
sidx = idx++;
else
sidx = idx;
// eat number
while (idx < len) {
c = pathStr.charCodeAt(idx);
if (DIGIT_0 <= c && c <= DIGIT_9) {
idx++;
continue;
}
else if (c === PERIOD) {
idx++;
isFloat = true;
continue;
}
s = pathStr.substring(sidx, idx);
return isFloat ? parseFloat(s) : parseInt(s);
}
s = pathStr.substring(sidx);
return isFloat ? parseFloat(s) : parseInt(s);
}
function nextIsNum() {
var c;
// do permanently eat any delims...
while (idx < len) {
c = pathStr.charCodeAt(idx);
if (c !== COMMA && c !== SPACE)
break;
idx++;
}
c = pathStr.charCodeAt(idx);
return (c === MINUS || (DIGIT_0 <= c && c <= DIGIT_9));
}
var canRepeat;
activeCmd = pathStr[0];
while (idx <= len) {
canRepeat = true;
switch (activeCmd) {
// moveto commands, become lineto's if repeated
case 'M':
x = eatNum();
y = eatNum();
path.moveTo(x, y);
activeCmd = 'L';
break;
case 'm':
x += eatNum();
y += eatNum();
path.moveTo(x, y);
activeCmd = 'l';
break;
case 'Z':
case 'z':
canRepeat = false;
if (x !== firstX || y !== firstY)
path.lineTo(firstX, firstY);
break;
// - lines!
case 'L':
case 'H':
case 'V':
nx = (activeCmd === 'V') ? x : eatNum();
ny = (activeCmd === 'H') ? y : eatNum();
path.lineTo(nx, ny);
x = nx;
y = ny;
break;
case 'l':
case 'h':
case 'v':
nx = (activeCmd === 'v') ? x : (x + eatNum());
ny = (activeCmd === 'h') ? y : (y + eatNum());
path.lineTo(nx, ny);
x = nx;
y = ny;
break;
// - cubic bezier
case 'C':
x1 = eatNum(); y1 = eatNum();
case 'S':
if (activeCmd === 'S') {
x1 = 2 * x - x2; y1 = 2 * y - y2;
}
x2 = eatNum();
y2 = eatNum();
nx = eatNum();
ny = eatNum();
path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
x = nx; y = ny;
break;
case 'c':
x1 = x + eatNum();
y1 = y + eatNum();
case 's':
if (activeCmd === 's') {
x1 = 2 * x - x2;
y1 = 2 * y - y2;
}
x2 = x + eatNum();
y2 = y + eatNum();
nx = x + eatNum();
ny = y + eatNum();
path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
x = nx; y = ny;
break;
// - quadratic bezier
case 'Q':
x1 = eatNum(); y1 = eatNum();
case 'T':
if (activeCmd === 'T') {
x1 = 2 * x - x1;
y1 = 2 * y - y1;
}
nx = eatNum();
ny = eatNum();
path.quadraticCurveTo(x1, y1, nx, ny);
x = nx;
y = ny;
break;
case 'q':
x1 = x + eatNum();
y1 = y + eatNum();
case 't':
if (activeCmd === 't') {
x1 = 2 * x - x1;
y1 = 2 * y - y1;
}
nx = x + eatNum();
ny = y + eatNum();
path.quadraticCurveTo(x1, y1, nx, ny);
x = nx; y = ny;
break;
// - elliptical arc
case 'A':
rx = eatNum();
ry = eatNum();
xar = eatNum() * DEGS_TO_RADS;
laf = eatNum();
sf = eatNum();
nx = eatNum();
ny = eatNum();
if (rx !== ry) {
console.warn("Forcing elliptical arc to be a circular one :(",
rx, ry);
}
// SVG implementation notes does all the math for us! woo!
// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
// step1, using x1 as x1'
x1 = Math.cos(xar) * (x - nx) / 2 + Math.sin(xar) * (y - ny) / 2;
y1 = -Math.sin(xar) * (x - nx) / 2 + Math.cos(xar) * (y - ny) / 2;
// step 2, using x2 as cx'
var norm = Math.sqrt(
(rx*rx * ry*ry - rx*rx * y1*y1 - ry*ry * x1*x1) /
(rx*rx * y1*y1 + ry*ry * x1*x1));
if (laf === sf)
norm = -norm;
x2 = norm * rx * y1 / ry;
y2 = norm * -ry * x1 / rx;
// step 3
cx = Math.cos(xar) * x2 - Math.sin(xar) * y2 + (x + nx) / 2;
cy = Math.sin(xar) * x2 + Math.cos(xar) * y2 + (y + ny) / 2;
var u = new THREE.Vector2(1, 0),
v = new THREE.Vector2((x1 - x2) / rx,
(y1 - y2) / ry);
var startAng = Math.acos(u.dot(v) / u.length() / v.length());
if (u.x * v.y - u.y * v.x < 0)
startAng = -startAng;
// we can reuse 'v' from start angle as our 'u' for delta angle
u.x = (-x1 - x2) / rx;
u.y = (-y1 - y2) / ry;
var deltaAng = Math.acos(v.dot(u) / v.length() / u.length());
// This normalization ends up making our curves fail to triangulate...
if (v.x * u.y - v.y * u.x < 0)
deltaAng = -deltaAng;
if (!sf && deltaAng > 0)
deltaAng -= Math.PI * 2;
if (sf && deltaAng < 0)
deltaAng += Math.PI * 2;
path.absarc(cx, cy, rx, startAng, startAng + deltaAng, sf);
x = nx;
y = ny;
break;
default:
throw new Error("weird path command: " + activeCmd);
}
if (firstX === null) {
firstX = x;
firstY = y;
}
// just reissue the command
if (canRepeat && nextIsNum())
continue;
activeCmd = pathStr[idx++];
}
return path;
};
ar.util.gradientTexture = function (){
function generateMeterial() {
var size = 512;
// create canvas
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
// get context
var context = canvas.getContext( '2d' );
// draw gradient
context.rect( 0, 0, size, size );
var gradient = context.createLinearGradient( 0, 0, 0, size );
gradient.addColorStop(0, '#99ddff'); // light blue
gradient.addColorStop(1, 'transparent'); // dark blue
context.fillStyle = gradient;
context.fill();
var texture = new THREE.Texture( canvas );
texture.needsUpdate = true;
var material = new THREE.MeshBasicMaterial( {
map: texture, transparent: true } );
return material;
}
return generateMeterial();
};
ar.util.flatObject = function(param, mold, position,aboveGround){
var material = ar.util.newFace(mold.face);
var geometry = new THREE.PlaneGeometry( mold.size.width, mold.size.high, 1, 1 );
var flat = new THREE.Mesh(geometry, material);
flat.position.x = position.x;
flat.position.y = mold.size.high / 2 + aboveGround;
flat.position.z = position.z;
var shp = _.extend({}, ar.shape3DClass);
shp.mesh = flat;
shp.isFlat = true;
shp.id = _.uniqueId();
ar.shape3Ds.push(shp);
shp.config = param;
return shp;
};
ar.util.buildWall = function(mold, segment){
function updateLine(segment){
if (segment.start.x === segment.end.x){
segment.length = Math.abs(segment.end.z - segment.start.z);
segment.direct = "Z";
}
if (segment.start.z === segment.end.z){
segment.length = Math.abs(segment.end.x - segment.start.x);
segment.direct = "X";
}
return segment;
}
var line = updateLine(segment);
var sideMaterial = ar.util.newFace(mold.faces.sideFace,line.length);
var wallMaterial = sideMaterial;
var topMaterial = ar.util.newFace(mold.faces.topFace, line.length);
var xlen,ylen,zlen,xm,ym,zm,px,py,pz;
ylen = mold.size.high;
py = ylen/2;
if (line.direct === "X")
{
xlen = line.length + mold.size.width - 0.1;
zlen = mold.size.width;
zm = wallMaterial;
ym = topMaterial;
xm = sideMaterial;
if (line.start.x < line.end.x)
px = line.length/ 2 + line.start.x;
if (line.start.x > line.end.x)
px = line.start.x - line.length/2;
pz = line.start.z;
}
if (line.direct === "Z")
{
zlen = line.length + mold.size.width / 2 - 0.1;
xlen = mold.size.width;
xm = wallMaterial;
zm = sideMaterial;
ym = topMaterial;
if (line.start.z > line.end.z)
pz = line.start.z - line.length / 2;
if (line.start.z < line.end.z)
pz = line.length /2 + line.start.z;
px = line.start.x;
}
var wall = new THREE.Mesh(new THREE.CubeGeometry(xlen,ylen,zlen),
new THREE.MeshFaceMaterial(
[
xm, // +x
xm, // -x
ym, // +y
ym, // -y
zm, // +z
zm // -z
]));
wall.position.x = px;
wall.position.y = py;
wall.position.z = pz;
wall.castShadow = true;
wall.receiveShadow = true;
return wall;
};
ar.util.buildWallPart = function(param){
var mold = ar.util.getMold(param.moldId);
//var doorMaterial = ar.util.newFace(mold.faces.topFace);
var frontMaterial = ar.util.newFace(mold.faces.frontFace);
var backMaterial = ar.util.newFace(mold.faces.backFace);
var sideMaterial = ar.util.newFace(mold.faces.sideFace);
var xlen,ylen,zlen,xm1,xm2,ym1,ym2,zm1,zm2,px,py,pz;
ylen = mold.size.high;
py = mold.size.high /2 + param.position.y;
if (param.direct === "X")
{
xlen = mold.size.width;
zlen = mold.size.depth;
zm1 = frontMaterial;
zm2 = backMaterial;
ym1 = sideMaterial;
ym2 = sideMaterial;
xm1 = sideMaterial;
xm2 = sideMaterial;
px = param.position.x;
pz = param.position.z;
}
if (param.direct === "Z")
{
zlen = mold.size.width;
xlen = mold.size.depth;
xm1 = frontMaterial;
xm2 = backMaterial;
zm1 = sideMaterial;
zm2 = sideMaterial;
ym1 = sideMaterial;
ym2 = sideMaterial;
pz = param.position.z;
px = param.position.x;
}
var door = new THREE.Mesh(new THREE.CubeGeometry(xlen,ylen,zlen),
new THREE.MeshFaceMaterial(
[
xm1, // +x
xm2, // -x
ym1, // +y
ym2, // -y
zm1, // +z
zm2 // -z
]));
door.position.x = px;
door.position.y = py;
door.position.z = pz;
return door;
};
ar.util.getMold = function(id){
var res;
molds.forEach(function(m){
if (m.id === id) res = m;
});
return res;
};
ar.util.radians = function(degrees) {
return degrees * Math.PI / 180;
};
ar.util.newFace = function(cfg, faceSize){
var param = {};
if (cfg.texture) {
param.map = new THREE.TextureLoader().load( cfg.texture );
if (cfg.tileWay){
param.map.wrapS = param.map.wrapT = THREE.RepeatWrapping;
var walltileSize = cfg.textureSize;
if (cfg.tileWay == "H")
param.map.repeat.set( faceSize / walltileSize, 1);
if (cfg.tileWay == "T")
param.map.repeat.set( faceSize / walltileSize, faceSize / walltileSize);
if (cfg.tileWay == "V")
param.map.repeat.set(1, faceSize / walltileSize);
}
}
if (cfg.side) param.side = cfg.side;
if (cfg.color) param.color = new THREE.Color(cfg.color);
if (cfg.transparent) param.transparent = cfg.transparent;
var material = new THREE.MeshPhongMaterial(param);
if (cfg.opacity) {
material.opacity = cfg.opacity;
}
else{
material.opacity = 1;
}
if (material.opacity !== 1) material.depthWrite = false;
return material;
};
ar.util.maskColor = function(mesh, color){
if (!mesh) return;
try {
if (mesh.material instanceof THREE.MeshPhongMaterial)
{
mesh.material.emissive.setHex( color );
//mesh.material.color.setHex( color );
}
if (mesh.material instanceof THREE.MultiMaterial)
{
mesh.material.materials.forEach(function(m){
//m.color.setHex( color );
m.emissive.setHex( color );
});
}
}
catch(err) {
}
};
ar.util.getMaskColor = function(mesh){
if (!mesh) return;
if (mesh.material instanceof THREE.MeshPhongMaterial)
{
return mesh.material.emissive.getHex();
}
if (mesh.material instanceof THREE.MultiMaterial)
{
return mesh.material.materials[0].emissive.getHex();
}
};
ar.provider = {
collectBinding : function(){
var res = [];
ar.shape3Ds.forEach(function(shp){
if (shp.config.bindings.length > 0)
{
var pack = { id:shp.id, bs:shp.config.bindings};
res.push(pack);
}
});
return res;
},
start : function(){
if (!ar.options.shell) return;
var bindingSet = this.collectBinding();
//http ask for result by interval
this.stop = ar.options.shell.$interval(function() {
//get data and refresh shapes status
ar.options.shell.$srv.getData(bindingSet).then(function(data){
ar.shape3Ds.forEach(function(shp){
var status = _.find(data, function(item){
return item.id === shp.id;
});
if (status) shp.update(status);
});
});
}, 5000);
},
dispose :function(){
if (!ar.options.shell) return;
if (this.stop)
ar.options.shell.$interval.cancel(this.stop);
ar.options.shell.$srv = undefined;
ar.options.shell.$interval = undefined;
ar.options.shell.$location = undefined;
this.stop = undefined;
}
};
///////// create main code here /////////
ar.init(id);
ar.loadUnits();
if (config)
ar.load(config);
else
ar.load();
if (options)
ar.options = _.extend(ar.options, options);
//start 3D time line
ar.animate();
ar.provider.start();
return ar;
}
};