538 lines
21 KiB
Plaintext
538 lines
21 KiB
Plaintext
<%@ language="javascript"%>
|
|
<% /*
|
|
$Revision$
|
|
$Id$
|
|
|
|
File: 3Dize.asp
|
|
Description:
|
|
Parameters: allerlei custom parameters
|
|
Context: Vanuit ge
|
|
Note: De tekening staat in een andere directory (S("fg_vlucht_path")) maar moet dezelfde bestandsnaam hebben
|
|
als de gewone FG plattegrondtekening.
|
|
*/
|
|
%>
|
|
<!--#include file="../Shared/common.inc" -->
|
|
<!--#include file="../slnkdwf/Slnk2IMG.inc" -->
|
|
<%
|
|
FCLTHeader.Requires({ plugins: ["jQuery"],
|
|
js: ["jquery-ui.js", "./js/three.js", "./js/Detector.js"],
|
|
css: []});
|
|
|
|
// Jos's PC WebGL kan maximaal 2048 in een richting aan
|
|
var hpix = getQParamInt("hpix", 2048);;
|
|
var vpix = getQParamInt("vpix", 1536);
|
|
// Permanent inzoomen op het plaatje
|
|
// scl: 2000 voor factor 2 enz.
|
|
// ox en oy geven verschuiving in pixels *na* verschaling
|
|
var scl = getQParamInt("scl", 1000);
|
|
var ox = getQParamInt("ox", 0);
|
|
var oy = getQParamInt("oy", 0);
|
|
var pContmode = getQParamInt("contmode", 0);
|
|
|
|
// 180 graden bijvoorbeeld om vanaf de andere kant te kijken
|
|
var rot = getQParamInt("rot", 0) / 180 * Math.PI;
|
|
var labelrot = getQParamInt("labelrot", getQParamInt("rot", 0));
|
|
|
|
var camZ = getQParamInt("camZ", parseInt(vpix * 1.0));
|
|
var camY = getQParamInt("camY", parseInt(- vpix / 2.0));
|
|
var camX = getQParamInt("camX", parseInt(vpix / 2.0));
|
|
|
|
// camX en camY automatisch met rot meeroteren
|
|
camY = parseInt( Math.cos(rot) * camY);
|
|
camX = parseInt( Math.sin(rot) * camX);
|
|
|
|
// het thema voor de popup borden
|
|
var bordlabel_key = getQParamInt("bordlabel_key", -1);
|
|
|
|
var wallColor = getQParamInt("wallColor", 0xc0c0c0 );
|
|
var ambientLight = getQParamInt("ambientLight", 0x999999 );
|
|
var directionalLight = getQParamInt("directionalLight", 0xd0d0d0 );
|
|
|
|
var symbolX = getQParamFloat( "symbolX", -1 ); // -1 kan in theorie ook een geldige waarde zijn. Ach...
|
|
var symbolY = getQParamFloat( "symbolY", -1 );
|
|
var symbol = getQParam("symbol", "../pictures/urhere.png");
|
|
var showSymbol = getQParamInt("showSymbol",0)==1;
|
|
|
|
// Muur hoogte/ breedte
|
|
var wallw = getQParamInt("wallw", 200);
|
|
var wallh = getQParamInt("wallh", 5 * wallw);
|
|
|
|
if (getQParamInt("hideSymbol", 0) == 1)
|
|
symbolX = -1;
|
|
|
|
offsetX = ox - parseInt(hpix/2 - hpix/2/scl/1000);
|
|
offsetY = oy - parseInt(vpix/2 + vpix/2/scl/1000);
|
|
|
|
%>
|
|
<html>
|
|
<head>
|
|
<% FCLTHeader.Generate(); %>
|
|
<title>FACILITOR perspective view</title>
|
|
</head>
|
|
|
|
<body class="floorscreen3d">
|
|
|
|
<script>
|
|
var gSLNKEvent;
|
|
var gCustomParameters; // wat er inhoudelijk getoond moet worden (verdieping, thema's etc)
|
|
var gimgurl;
|
|
|
|
var offsetX=<%=offsetX%>;
|
|
var offsetY=<%=offsetY%>;
|
|
var scale=<%=scl%>;
|
|
var vpix = <%=vpix%>;
|
|
var hpix = <%=hpix%>;
|
|
var symbolX = <%=safe.jsfloat(symbolX)%>;
|
|
var symbolY = <%=safe.jsfloat(symbolY)%>;
|
|
var symbol = "<%=safe.jsstring(symbol)%>";
|
|
|
|
function SetCustomParameters(custParams)
|
|
{
|
|
gCustomParameters = custParams;
|
|
}
|
|
|
|
function Refresh(actual)
|
|
{
|
|
document.removeEventListener( 'mousedown', onDocumentMouseDown, false ); // Even geen onclicks
|
|
|
|
init();
|
|
}
|
|
|
|
function zoom2DWG(centerX, centerY, newScale)
|
|
{
|
|
if (!gSLNKEvent)
|
|
return; // we waren zelf nog niet klaar.
|
|
var currScale=vpix / (gSLNKEvent.viewmaxY - gSLNKEvent.viewminY);
|
|
var currScale=hpix / (gSLNKEvent.viewmaxX - gSLNKEvent.viewminX);
|
|
|
|
// zie ook CWhip2DCState::SetExtents
|
|
var mulY = vpix / (gSLNKEvent.DWGmaxY - gSLNKEvent.DWGminY)
|
|
var mulX = hpix / (gSLNKEvent.DWGmaxX - gSLNKEvent.DWGminX);
|
|
|
|
if (mulY > mulX)
|
|
{
|
|
var autoMinX = gSLNKEvent.DWGminX; // als ik niets verschuif of schaal
|
|
var autoMaxY = (gSLNKEvent.DWGminY+gSLNKEvent.DWGmaxY + vpix/mulX)/2;
|
|
}
|
|
else
|
|
{
|
|
var autoMinX = (gSLNKEvent.DWGminX+gSLNKEvent.DWGmaxX - hpix/mulY)/2;
|
|
var autoMaxY = gSLNKEvent.DWGmaxY;
|
|
}
|
|
offsetX = Math.round((autoMinX - centerX) * newScale + hpix/2);
|
|
offsetY = Math.round((centerY - autoMaxY) * newScale + vpix/2);
|
|
scale = Math.round(1000.0 / currScale * newScale);
|
|
}
|
|
function noAutoResize()
|
|
{
|
|
}
|
|
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
|
|
|
|
var SCREEN_WIDTH = window.innerWidth;
|
|
var SCREEN_HEIGHT = window.innerHeight;
|
|
|
|
var container;
|
|
|
|
var camera, scene, renderer;
|
|
|
|
//init();
|
|
|
|
function allCast(elm)
|
|
{
|
|
elm.castShadow = true;
|
|
if (elm.children)
|
|
for (var i in elm.children)
|
|
allCast(elm.children[i]);
|
|
}
|
|
|
|
// http://stackoverflow.com/questions/15248872/dynamically-create-2d-text-in-three-js
|
|
var projector = new THREE.Projector();
|
|
// image XY to canvasXY to 3D
|
|
function toXYCoords (imgX, imgY)
|
|
{
|
|
var imgPos = new THREE.Vector3(imgX - hpix / 2, vpix / 2 - imgY, 10)
|
|
camera.lookAt( scene.position );
|
|
camera.rotation.z = <%= safe.jsfloat(rot) %>;
|
|
|
|
camera.updateMatrixWorld();
|
|
var vector = projector.projectVector(imgPos.clone(), camera);
|
|
vector.x = (vector.x + 1)/2 * window.innerWidth;
|
|
vector.y = -(vector.y - 1)/2 * window.innerHeight;
|
|
return vector;
|
|
}
|
|
// 3D to canvas XY to imageXY
|
|
function fromXYCoords (vector)
|
|
{ var projector = new THREE.Projector();
|
|
|
|
projector.unprojectVector( vector, camera );
|
|
var dir = vector.sub( camera.position ).normalize();
|
|
var distance = - camera.position.z / dir.z;
|
|
var pos = camera.position.clone().add( dir.multiplyScalar( distance ) );
|
|
|
|
// FcltMgr.alert("Image pos.X=" + pos.x + " pos.Y=" + pos.y);
|
|
|
|
var imgX = pos.x + hpix / 2;
|
|
var imgY = vpix / 2 - pos.y;
|
|
return { x: imgX, y: imgY };
|
|
}
|
|
|
|
function init() {
|
|
|
|
container = document.createElement( 'div' );
|
|
|
|
document.body.appendChild( container );
|
|
|
|
camera = new THREE.PerspectiveCamera( 35, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
|
|
|
|
camera.position.z = <%=camZ%>;
|
|
camera.position.y = <%=camY%>;
|
|
camera.position.x = <%=camX%>;
|
|
|
|
scene = new THREE.Scene();
|
|
|
|
// GROUND
|
|
|
|
// PAINTING
|
|
gimgurl = "../CAD/mySlnk2IMG.asp?labelPos=2" + gCustomParameters
|
|
+ "&sizeX="+hpix+"&sizeY="+vpix + "&labelrot=<%=labelrot%>"
|
|
+ "&contmode=<%=pContmode%>"
|
|
+ "&offsetX="+offsetX+"&offsetY="+offsetY+"&scale="+scale+"&paperColor=16777214";
|
|
|
|
// 'bordlabel' wordt voor de popup 'borden' gebruikt
|
|
|
|
var callbackPainting = function()
|
|
{
|
|
var image = texturePainting.image;
|
|
|
|
var ss = Math.min(image.width, image.height);
|
|
|
|
var geometry = new THREE.PlaneGeometry( ss , ss );
|
|
var mesh = new THREE.Mesh( geometry, materialPainting );
|
|
|
|
mesh.scale.x = image.width / image.height;
|
|
mesh.scale.y = 1;
|
|
|
|
scene.add( mesh );
|
|
|
|
//mesh.receiveShadow = true;
|
|
|
|
$.getJSON(gimgurl + "&AsMap=1", { }, callbackWalls );
|
|
}
|
|
function drawBord(imgX, imgY, tekst)
|
|
{
|
|
//console.log("Bord: " + tekst+ " x=" + imgX + " y=" + imgY)
|
|
var image = texturePainting.image;
|
|
var x0 = imgX;
|
|
var y0 = imgY;
|
|
|
|
tekst = tekst.replace(/\[br\]/g, "<br>");
|
|
|
|
var text2 = document.createElement('div');
|
|
text2.className = 'bord3d';
|
|
text2.style.position = 'absolute';
|
|
//text2.style.zIndex = 1; // if you still don't see the label, try uncommenting this
|
|
|
|
text2.innerHTML = tekst;
|
|
var pos = toXYCoords(x0, y0);
|
|
// Eigenlijk willen we centreren maar ik weet de breedte van het bord niet.
|
|
text2.style.top = pos.y - 20 + "px";
|
|
text2.style.left = pos.x - 40 + "px";
|
|
container.appendChild(text2);
|
|
}
|
|
|
|
function drawSymbol(imgX, imgY, symbol)
|
|
{
|
|
//console.log("Symbol: " + symbol+ "op x=" + imgX + " y=" + imgY)
|
|
var image = texturePainting.image;
|
|
var x0 = imgX;
|
|
var y0 = imgY;
|
|
|
|
var img = document.createElement('img');
|
|
img.src = symbol;
|
|
img.className = 'symbol3d';
|
|
img.style.position = 'absolute';
|
|
//img.style.zIndex = 1; // if you still don't see the label, try uncommenting this
|
|
|
|
var imgPos = new THREE.Vector3(imgX - image.width / 2, image.height / 2 - imgY, 10)
|
|
var pos = toXYCoords(imgX, imgY);
|
|
// Eigenlijk willen we centreren maar ik weet de grootte van het symbool niet.
|
|
img.style.top = pos.y + "px";
|
|
img.style.left = pos.x + "px";
|
|
container.appendChild(img);
|
|
}
|
|
|
|
function _Centroid(coords)
|
|
{
|
|
var ptx = 0;
|
|
var pty = 0;
|
|
var totArea = 0;
|
|
var i;
|
|
var arX = [], arY = [];
|
|
for (i = 0; i < coords.length / 2; i++)
|
|
{
|
|
arX[i] = coords[i*2];
|
|
arY[i] = coords[i*2+1];
|
|
}
|
|
|
|
|
|
for (i = 0; i < arX.length; i++) {
|
|
var j = (i + 1) % arX.length;
|
|
var dArea = arX[i]*arY[j] - arX[j]*arY[i];
|
|
totArea += dArea;
|
|
ptx += (arX[i]+arX[j]) * dArea;
|
|
pty += (arY[i]+arY[j]) * dArea;
|
|
}
|
|
return { X: ptx / totArea / 3, Y: pty / totArea / 3, AREA: totArea / 2 };
|
|
}
|
|
|
|
var callbackWalls = function(data)
|
|
{
|
|
window.gSLNKEvent = data;
|
|
// data.area is een heel lange string en can rect en poly's bevatten
|
|
//<area SLNKKey="R:12021" title="" shape="rect" coords="985,892,1079,983">
|
|
//<area SLNKKey="R:12023" title="" shape="poly" coords="985,738,1079,738,1079,829,985,829,985,738">
|
|
var areas = data.Map.split("<area");
|
|
|
|
// Cubes
|
|
var sc = <%= wallw %> / gSLNKEvent.scaleX; // muurdikte
|
|
|
|
var geometry = new THREE.CubeGeometry( sc, sc, sc );
|
|
|
|
var material = new THREE.MeshLambertMaterial( { color: <%=wallColor%>, shading: THREE.FlatShading, overdraw: true } );
|
|
var materialTrans = new THREE.MeshLambertMaterial( { color: <%=wallColor%>, shading: THREE.FlatShading, overdraw: true, transparent: true, opacity: 0.001 } );
|
|
|
|
function fromtos(arr, trans)
|
|
{
|
|
var i;
|
|
for (i=0; i < arr.length / 2 - 1; i++)
|
|
fromto(arr[2*i],arr[2*i+1],arr[2*i+2],arr[2*i+3], trans)
|
|
}
|
|
|
|
function fromto(x0, y0, x1, y1, trans)
|
|
{
|
|
var cube = new THREE.Mesh( geometry, trans ? materialTrans: material );
|
|
//cube.castShadow = true;
|
|
|
|
var m = new THREE.Matrix4();
|
|
var rot = Math.atan( (y1-y0) / (x1-x0) )
|
|
m.makeRotationZ( - rot );
|
|
cube.applyMatrix( m );
|
|
|
|
// Muur hoogte
|
|
cube.scale.z = <%= wallh / wallw %>; // 5 keer de dikte
|
|
cube.position.z = cube.scale.z/2 * sc;
|
|
|
|
// Muur lengte
|
|
cube.scale.x = Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)) / sc + 1;
|
|
|
|
var image = texturePainting.image;
|
|
cube.position.x = (x0 + x1 - image.width)/ 2;
|
|
cube.position.y = (image.height - y0 - y1) / 2;
|
|
|
|
scene.add( cube );
|
|
}
|
|
|
|
// Werkplekken zijn ooit uitgeschakeld om 3D op IE11 te kunnen testen
|
|
// Niemand heeft het nog gemist.
|
|
// Werkplekken
|
|
// var loader = new THREE.ColladaLoader();
|
|
|
|
// loader.load('./models/Desk.dae.txt', function (result)
|
|
// {
|
|
// var werkplekSymbol = result.scene;
|
|
// allCast(werkplekSymbol);
|
|
|
|
// FcltMgr.alert(werkplekSymbol.scale.x); // default is 0.0254 ?
|
|
// werkplekSymbol.scale.set(25.4 / gSLNKEvent.scaleX , 25.4 / gSLNKEvent.scaleX, 25.4 / gSLNKEvent.scaleX);
|
|
// werkplekSymbol.rotation.set(0, 0, Math.PI / 4);
|
|
// var mat = new THREE.MeshLambertMaterial( { map: modelTex });
|
|
|
|
// Coordinaten werkplekken
|
|
$.getJSON("get_wp_info_ajax.asp?bordlabel=<%=bordlabel_key%>" + gCustomParameters, { },
|
|
function (wpjson)
|
|
{
|
|
var image = texturePainting.image;
|
|
// FcltMgr.alert(wpjson.werkplekken.length);
|
|
|
|
for (var ar in areas)
|
|
{
|
|
var area = areas[ar];
|
|
if (area.indexOf("SLNKKey") < 0)
|
|
continue;
|
|
var key = area.substr(area.indexOf("SLNKKey=")+9, area.substr(area.indexOf("SLNKKey=")+9).indexOf("\""));
|
|
if (key.substring(0,2) == "R:") // 5.3.1 heeft dat nog niet
|
|
key = key.substr(2); // Haal de R: er af
|
|
|
|
// coords zitten er in <area> formaat in. Lelijke reverse-engineering:
|
|
var coordsstart = area.indexOf("coords=");
|
|
if (coordsstart > 0)
|
|
{
|
|
var coordsend = area.substr(coordsstart+8).indexOf("\"");
|
|
var coords = area.substr(coordsstart+8, coordsend);
|
|
if (coords.split(",").length >= 4)
|
|
{
|
|
var cc = coords.split(",");
|
|
for (var c in cc)
|
|
{
|
|
cc[c] = parseInt(cc[c], 10);
|
|
}
|
|
if (cc.length == 4) // dan is het een rect
|
|
{
|
|
cc = [ cc[0],cc[1],cc[0],cc[3],cc[2],cc[3],cc[2],cc[1],cc[0],cc[1] ];
|
|
}
|
|
var found = false;
|
|
for (var rm in wpjson.borden)
|
|
{
|
|
if (wpjson.borden[rm].key == key || /*5.3.1*/ wpjson.borden[rm].rnr == key)
|
|
{
|
|
var center = _Centroid(cc);
|
|
drawBord(center.X,center.Y, wpjson.borden[rm].tekst)
|
|
}
|
|
}
|
|
for (var rm in wpjson.muren)
|
|
{
|
|
if (wpjson.muren[rm].key == key || /*5.3.1*/ wpjson.muren[rm].rnr == key)
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
fromtos(cc, !found); // Niet gevonden doen we transparant
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0)
|
|
for (var wp in wpjson.werkplekken)
|
|
{
|
|
var wpdata = wpjson.werkplekken[wp];
|
|
var xy = toImgXY(wpdata.dwgX, wpdata.dwgY);
|
|
var newModel = werkplekSymbol.clone();
|
|
|
|
newModel.rotation.set(0, 0, Math.PI / 180 * wpdata.rot);
|
|
newModel.position.x = (xy.imgX - image.width / 2);
|
|
newModel.position.y = (image.height / 2 - xy.imgY);
|
|
scene.add(newModel);
|
|
}
|
|
|
|
<% if (showSymbol) { %>
|
|
if (symbolX != -1)
|
|
{
|
|
var xy = toImgXY(symbolX, symbolY);
|
|
drawSymbol(xy.imgX, xy.imgY, symbol);
|
|
}
|
|
<% } %>
|
|
|
|
render(); // Alles klaar, renderen!!!
|
|
});
|
|
|
|
// });
|
|
|
|
// Lights
|
|
|
|
var ambientLight = new THREE.AmbientLight( <%=ambientLight%> );
|
|
scene.add( ambientLight );
|
|
|
|
var directionalLight = new THREE.DirectionalLight( <%=directionalLight%> );
|
|
|
|
directionalLight.position.set(800,600,1000);
|
|
directionalLight.position.normalize();
|
|
|
|
scene.add( directionalLight );
|
|
|
|
};
|
|
|
|
// Hier begint de echte init() code
|
|
var png = gimgurl;
|
|
var TIMU = THREE.ImageUtils;
|
|
TIMU.crossOrigin = null; // Anders wordt voor de IMG-request geen ASP-session meegestuurd
|
|
// door Chrome en is het plaatje direct 'expired'
|
|
var texturePainting = TIMU.loadTexture( png, THREE.UVMapping, callbackPainting ),
|
|
materialPainting = new THREE.MeshBasicMaterial( { color: 0xffffff, map: texturePainting } );
|
|
|
|
renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
|
|
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
renderer.autoClear = false;
|
|
renderer.shadowMapEnabled = true;
|
|
|
|
renderer.domElement.style.position = "relative";
|
|
container.appendChild( renderer.domElement );
|
|
|
|
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
|
|
$(document).on( "mousewheel DOMMouseScroll", function(e){
|
|
e.preventDefault();
|
|
var delta = e.originalEvent.wheelDelta;
|
|
var detail = e.originalEvent.detail; // FireFox
|
|
|
|
camera.position.y *= (delta <=- 120 || detail>0)?1.1:(1/1.1) ;
|
|
camera.position.z *= (delta <=- 120 || detail>0)?1.1:(1/1.1);
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
function onDocumentMouseMove(event) {
|
|
|
|
var mouseX = ( event.clientX - SCREEN_WIDTH / 2 );
|
|
var mouseY = ( event.clientY - SCREEN_HEIGHT / 2 );
|
|
var ctrlKey = event.ctrlKey;
|
|
if (ctrlKey)
|
|
{
|
|
camera.position.x += ( mouseX * 4 - camera.position.x ) ;
|
|
camera.position.y += ( - ( mouseY - 200) * 16 - camera.position.y );
|
|
}
|
|
}
|
|
|
|
function callbackClicked(data)
|
|
{
|
|
// FcltMgr.alert(data.ContourLabel);
|
|
data.Param = "onclick";
|
|
parent.MMap_onClick(data);
|
|
}
|
|
function onDocumentMouseDown( event ) {
|
|
|
|
event.preventDefault();
|
|
|
|
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
|
|
var xy = fromXYCoords(vector)
|
|
|
|
var imgX = xy.x;
|
|
var imgY = xy.y;
|
|
|
|
// FcltMgr.alert("Image imgX=" + imgX + " imgX=" + imgY);
|
|
|
|
$.getJSON(gimgurl + "&AsFND=1&findX=" + imgX + "&findY=" + imgY, callbackClicked );
|
|
}
|
|
|
|
function render() {
|
|
|
|
camera.lookAt( scene.position );
|
|
camera.rotation.z = <%= safe.jsfloat(rot) %>;
|
|
|
|
renderer.render( scene, camera );
|
|
|
|
// Onderstaande niet te vroeg doen, anders kloppen de coordinaten bij onclick mogelijk niet goed
|
|
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
|
|
}
|
|
|
|
// Dee moet eigenlijk naar ToonIMG.js
|
|
function toImgXY(dwgX, dwgY)
|
|
{
|
|
result = null;
|
|
|
|
if (gSLNKEvent)
|
|
{
|
|
var result = {};
|
|
result.scaleX = gSLNKEvent.scaleX; // DWG Size of one screen pixel X
|
|
result.scaleY = gSLNKEvent.scaleY; // DWG Size of one screen pixel Y
|
|
result.imgX = (dwgX - gSLNKEvent.viewminX) / result.scaleX;
|
|
result.imgY = (gSLNKEvent.viewmaxY - dwgY) / result.scaleY;
|
|
}
|
|
return result;
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|