Open ibuilder opened 10 years ago
This code handles keyboard controls
viewer.php
<?php
/*
Plugin Name: 3d Model Viewer
Plugin URI: http://turneremanager.com
Description: Model viewer using three.js for CAD files
Author: Matthew M. Emma & Robert Carmosino
Version: 0.3
Author URI: http://www.turneremanager.com
Credits: va3c - http://va3c.github.io/
*/
/*-------------------------------------------------------*/
/* Enqueue scripts
/*-------------------------------------------------------*/
/*function modelscripts() {
wp_register_script('Detector', plugins_url('assets/Detector.js', __FILE__), false);
wp_register_script('Three', plugins_url('assets/three.min.js', __FILE__), false);
wp_register_script('TrackballControls', plugins_url('assets/TrackballControls.js', __FILE__), false);
wp_register_script('Stats', plugins_url('assets/stats.min.js', __FILE__), false);
wp_register_script('jama-materials', plugins_url('assets/jama-materials.js', __FILE__), false);
wp_register_script('jama-materials-data', plugins_url('assets/jama-materials-data.js', __FILE__), false);
wp_enqueue_script('Detector');
wp_enqueue_script('Three');
wp_enqueue_script('TrackballControls');
wp_enqueue_script('Stats');
wp_enqueue_script('jama-materials');
wp_enqueue_script('jama-materials-data');
}
if ( shortcode_exists( 'gallery' ) ) {
add_action( 'wp_enqueue_scripts', 'modelscripts' );
}*/
/*-------------------------------------------------------*/
/* 3d Modelv viewer
/*-------------------------------------------------------*/
/*function ModelViewer( $atts ) {
extract( shortcode_atts( array(
'url' => plugins_url('assets/rac_basic_sample_project.rvt.js', __FILE__),
'loc' => 'New York',
'width' => '800',
'height' => '600'
), $atts, 'model' ) );
*/
$width = 800;
$height = 600;
$url = 'assets/rac_basic_sample_project.rvt.js';
echo '
<!DOCTYPE html>
<html>
<head>
<title>Model Viewer</title>
<link rel="stylesheet" href="css/bootstrap.min.css" />
<link rel="stylesheet" href="css/font-awesome.min.css" />
<script src="js/jquery.1.10.2.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="assets/Detector.js"></script>
<script src="assets/three.min.js"></script>
<script src="assets/TrackballControls.js"></script>
<script src="assets/stats.min.js"></script>
<script src="assets/jama-materials.js"></script>
<script src="assets/jama-materials-data.js"></script>
<script src="js/Three.FirstPersonControls.js"></script>
</head>
<body>
<div id="threejs" style="position:relative; width:'.$width.'; height:'.$height.'; border:2px solid black">
<div class="controls" style="background:#ccc; text-align:center;
font-weight:bold; padding:10px;
position:absolute; bottom:0; width:100%; zIndex:100">
<div class="controls-left" style="float: left; width: 15%">
<i class="fa fa-undo fa-2x"></i>
<br /><strong>Rotate [Left Button]</strong>
</div>
<div class="controls-center" style="float: left; width: 15%">
<i class="fa fa-search-plus fa-2x"></i>
<br /><strong>Zoom [Mouse Wheel]</strong>
</div>
<div class="controls-right" style="float: left; width: 15%">
<i class="fa fa-arrows fa-2x"></i>
<br /><strong>Pan [Right Button]</strong>
</div>
<div class="controls-load" style="float: left; width: 25%">
<button id="control-load" type="button"
class="btn btn-primary btn-lg"
onclick="loadFile(\''.$url.'\')">Load Model
</button>
<div class="progress" id="progress" style="visibility:hidden; display:none">
<div class="progress-bar progress-bar-striped active"
id="progressbar" role="progressbar"
style="width: 0%">
<span class="sr-only">Loading</span>
</div>
</div>
</div>
<div class="controls-download" style="float: left; width: 30%">
<a id="control-download" type="button"
class="btn btn-primary btn-lg" href="'.$url.'" download>
Download Model
</a>
</div>
</div>
</div>
<script>
var renderer, stats, scene, camera, controls;
var WIDTH = '.$width.',
HEIGHT = '.$height.',
ASPECT = '.$width.' / '.$height.',
UNITSIZE = 250,
MOVESPEED = 5000,
LOOKSPEED = 0.035;
var t = THREE, scene, cam, renderer, controls, fcontrols, clock, projector, model, skin;
var runAnim = true, mouse = { x: 0, y: 0 };
var mx, mz, mlon, mlat;
var msearchz = msearchx = msearchlon = msearchlat = false;
$(document).ready(function(){
init();
animate();
});
function init() {
clock = new t.Clock();
projector = new t.Projector();
scene = new t.Scene();
var elem, geometry, material, mesh;
if(!Detector.webgl){ renderer = new t.CanvasRenderer({alpha:1, antialias:true, clearColor:0xffffff}); }
else{ renderer = new t.WebGLRenderer({alpha:1, antialias:true, clearColor:0xffffff}); }
renderer.setSize( '.$width.', '.$height.' );
renderer.shadowMapEnabled = true;
stats = new Stats();
stats.domElement.style.cssText = "position: absolute; right: 0; top: 0; zIndex: 100;";
elem = document.getElementById( "threejs" );
elem.appendChild( renderer.domElement );
elem.appendChild( stats.domElement );
camera = new t.PerspectiveCamera( 40, '.($width/$height).', 1, 100000 );
camera.position.set( 20000, 5000, 20000 );
//controls = new t.TrackballControls( camera, renderer.domElement );
fcontrols = new t.FirstPersonControls(camera);
fcontrols.movementSpeed = MOVESPEED;
fcontrols.lookSpeed = LOOKSPEED;
fcontrols.lookVertical = true;
fcontrols.noFly = false;
fcontrols.lon = 225;
//elem.appendChild(renderer.domElement);
//elem.addEventListener( "mousemove", onDocumentMouseMove, false );
light = new t.AmbientLight( 0x888888 );
scene.add( light );
light = new t.PointLight( 0xffffff, 0.5 );
scene.add( light );
light = new t.DirectionalLight( 0xffffff );
light.position.set( 10000, 10000, 10000 ).normalize();
scene.add( light );
}
function loadFile( file ) {
renderer.setSize( document.getElementById("threejs").clientWidth, document.getElementById("threejs").clientHeight );
document.getElementById("control-load").style.visibility = "hidden";
document.getElementById("control-load").style.display = "none";
document.getElementById("progress").style.removeProperty("visibility");
document.getElementById("progress").style.removeProperty("display");
var data = requestFile(file);
document.getElementById("progressbar").style.width = "25%";
data = JSON.parse(data);
document.getElementById("progressbar").style.width = "50%";
if(data.metadata===undefined){ data.metadata = { type: "Geometry" };} // 2.0
if(data.metadata.type===undefined){ data.metadata.type = "Geometry";} // 3.0
if(data.metadata.version===undefined){data.metadata.version = data.metadata.formatVersion;}
if(data.metadata.type.toLowerCase()==="geometry"){
console.log( "found geometry" );
loader = new t.JSONLoader();
contents = loader.parse( data );
geometry = contents.geometry;
if(contents.materials!==undefined){
console.log( "found geometry", contents.materials );
if(contents.materials.length>1){
material=new t.MeshFaceMaterial( contents.materials );
}else{ material=contents.materials[0]; }
}else{
material=JAMA.materials.NormalSmooth.set();
}
var mesh = new t.Mesh( geometry, material );
document.getElementById("progressbar").style.width = "75%";
scene.add( mesh );
document.getElementById("progressbar").style.width = "100%";
}else if(data.metadata.type.toLowerCase()==="object"){
loader = new t.ObjectLoader();
contents = loader.parse( data );
document.getElementById("progressbar").style.width = "75%";
if(contents instanceof t.Scene){
console.log( "found scene" );
scene.add( contents );
document.getElementById("progressbar").style.width = "100%";
}else{
console.log( "found object", contents );
scene.add( contents );
document.getElementById("progressbar").style.width = "100%";
}
}else if(data.metadata.type.toLowerCase()==="scene"){
console.log( "found deprecated");
// DEPRECATED
var loader = new t.SceneLoader();
loader.load(bundle.src, function(contents){
document.getElementById("progressbar").style.width = "75%";
scene.add( contents );
document.getElementById("progressbar").style.width = "100%";
},"");
}else{
console.log( "found a whoopsie");
document.getElementById("progressbar").style.width = "100%";
}
}
function requestFile ( fname ) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.crossOrigin = "Anonymous";
xmlhttp.open( "GET", fname, false );
xmlhttp.send( null );
return xmlhttp.responseText;
}
function animate() {
if(runAnim){ requestAnimationFrame(animate); }
//controls.update();
var delta = clock.getDelta(), speed = delta * MOVESPEED * 5;
fcontrols.update(delta);
renderer.render(scene, camera);
}
function onDocumentMouseMove(e) {
e.preventDefault();
mouse.x = (e.clientX / WIDTH) * 2 - 1;
mouse.y = - (e.clientY / HEIGHT) * 2 + 1;
}
var btnforward=false;
var btnleft=false;
var btnright=false;
var btnbackward=false;
function lookleft(){if(btnleft){myobject.mouseX=-(event.pageX-myobject.viewHalfX)} else {myobject.mouseX=false;}}
function gobackward(){if(btnbackward){myobject.moveBackward=true;}else{myobject.moveBackward=false;}}
function goforward(){if(btnforward){myobject.moveForward=true;}else{myobject.moveForward = false;}}
function lookright(){if(btnright){myobject.mouseX=event.pageX-myobject.viewHalfX}else{myobject.mouseX=false;}}
// Stop moving around when the window is unfocused (keeps my sanity!)
$(window).focus(function(){if (fcontrols) fcontrols.freeze = false;});
$(window).blur(function(){if (fcontrols) fcontrols.freeze = true;});
</script>
</body>
</html>
';
this is the javascript file Three.FirstPersonControls.js
var myobject = new Object();
THREE.FirstPersonControls = function ( object, domElement ) {
this.object = object;
this.target = new THREE.Vector3( 0, 0, 0 );
this.domElement = ( domElement !== undefined ) ? domElement : document;
this.movementSpeed = MOVESPEED;
this.lookSpeed = LOOKSPEED;
this.noFly = false;
this.lookVertical = true;
this.autoForward = false;
// this.invertVertical = false;
this.activeLook = true;
this.clickMove = false;
this.heightSpeed = false;
this.heightCoef = 1.0;
this.heightMin = -1;
this.constrainVertical = false;
this.verticalMin = 0;
this.verticalMax = Math.PI;
this.autoSpeedFactor = 0.0;
this.mouseX = 0;
this.mouseY = 0;
this.lat = 0;
this.lon = 0;
this.phi = 0;
this.theta = 0;
this.moveForward = false;
this.moveBackward = false;
this.moveLeft = false;
this.moveRight = false;
this.freeze = false;
this.mouseDragOn = false;
var mousemovement = false;
if ( this.domElement === document ) {
this.viewHalfX = window.innerWidth / 2;
this.viewHalfY = window.innerHeight / 2;
} else {
this.viewHalfX = this.domElement.offsetWidth / 2;
this.viewHalfY = this.domElement.offsetHeight / 2;
this.domElement.setAttribute( 'tabindex', -1 );
}
/*
this.onMouseMove = function ( event ) {
if ( mousemovement ) {
if ( this.domElement === document ) {
this.mouseX = event.pageX - this.viewHalfX;
this.mouseY = event.pageY - this.viewHalfY;
} else {
this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
}
}
};
this.onMouseDown = function ( event ) {
var etype = $(event.target).prop("tagName");
if(etype=="CANVAS"){
switch ( event.button ) {
case 0: mousemovement = true; break;
}
}
}
this.onMouseUp = function ( event ) {
switch ( event.button ) {
case 0: mousemovement = false; this. mouseX = false; this.mouseY = false; break;
}
}
*/
this.onKeyDown = function ( event ) {
switch( event.keyCode ) {
case 38: /*up*/ this.moveForward = true; break;
//case 87: /*W*/ this.mouseY = event.pageY - this.viewHalfY; break;
case 37: /*left*/this.mouseX = event.pageX - this.viewHalfX; break;
case 65: /*A*/ this.moveLeft = true; break;
case 40: /*down*/ this.moveBackward = true; break;
//case 83: /*S*/ this.mouseY = event.pageY + this.viewHalfY; break;
case 39: /*right*/this.mouseX = this.mouseX = event.pageX + this.viewHalfX; break;
case 68: /*D*/ this.moveRight = true; break;
case 82: /*F*/ this.moveUp = true; break;
case 70: /*R*/ this.moveDown = true; break;
case 81: /*Q*/ this.freeze = !this.freeze; break;
}
};
this.onKeyUp = function ( event ) {
switch( event.keyCode ) {
case 38: /*up*/ this.moveForward = false; break;
//case 87: /*W*/ this.mouseY = false; break;
case 37: /*left*/this.mouseX = false; break;
case 65: /*A*/ this.moveLeft = false; break;
case 40: /*down*/ this.moveBackward = false; break;
//case 83: /*S*/ this.mouseY = false; break;
case 39: /*right*/this.mouseX = false; break;
case 68: /*D*/ this.moveRight = false; break;
case 82: /*F*/ this.moveUp = false; break;
case 70: /*R*/ this.moveDown = false; break;
}
};
this.update = function( delta ) {
var actualMoveSpeed = 0;
if ( this.freeze ) { return; }
else {
if ( this.heightSpeed ) {
var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
var heightDelta = y - this.heightMin;
this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
} else {
this.autoSpeedFactor = 0.0;
}
actualMoveSpeed = delta * this.movementSpeed;
var vx = this.object.position.x;
var vy = this.object.position.y;
var vz = this.object.position.z;
//$("#listener").html(vx + "</br>" + vy + "</br>" + vz + "</br>" + this.lon + "</br>" + this.lat);
if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) {
this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
//this.object.position.y = 120;
//if(vz < -1145 || vz > 1050 || vx < -1581 || vx > 1761){
/*this.object.translateZ( actualMoveSpeed + this.autoSpeedFactor )
if(vz < -1145) {this.object.position.z = -1144.9999;}
if(vz > 1050) {this.object.position.z = 1049.9999;}
if(vx < -1581) {this.object.position.x = -1580.9999;}
if(vx > 1761) {this.object.position.x = 1760.9999;}*/
//}
}
if ( this.moveBackward || ( this.autoBackward && !this.moveBackward ) ) {
this.object.translateZ(actualMoveSpeed + this.autoSpeedFactor);
//this.object.position.y = 120;
//if(vz < -1145 || vz > 1050 || vx < -1581 || vx > 1761){
/*this.object.translateZ(- (actualMoveSpeed + this.autoSpeedFactor ) );
if(vz < -1145) {this.object.position.z = -1144.9999;}
if(vz > 1050) {this.object.position.z = 1049.9999;}
if(vx < -1581) {this.object.position.x = -1580.9999;}
if(vx > 1761) {this.object.position.x = 1760.9999;}*/
//}
}
if ( this.moveLeft || ( this.autoBackward && !this.moveBackward ) ) {
this.object.translateX( - (actualMoveSpeed + this.autoSpeedFactor ) );
//this.object.position.y = 120;
//if(vz < -1145 || vz > 1050 || vx < -1581 || vx > 1761){
/*this.object.translateX( actualMoveSpeed + this.autoSpeedFactor )
if(vz < -1145) {this.object.position.z = -1144.9999;}
if(vz > 1050) {this.object.position.z = 1049.9999;}
if(vx < -1581) {this.object.position.x = -1580.9999;}
if(vx > 1761) {this.object.position.x = 1760.9999;} */
//}
}
if ( this.moveRight ) {
this.object.translateX( actualMoveSpeed + this.autoSpeedFactor );
//this.object.position.y = 120;
/*if(vz < -1145 || vz > 1050 || vx < -1581 || vx > 1761){
this.object.translateX(-(actualMoveSpeed + this.autoSpeedFactor) );
if(vz < -1145) {this.object.position.z = -1144.9999;}
if(vz > 1050) {this.object.position.z = 1049.9999;}
if(vx < -1581) {this.object.position.x = -1580.9999;}
if(vx > 1761) {this.object.position.x = 1760.9999;}
}*/
}
if ( this.moveDown ) {
this.object.translateY(-(actualMoveSpeed+this.autoSpeedFactor));
}
if ( this.moveUp ) {
this.object.translateY((actualMoveSpeed+this.autoSpeedFactor));
}
if (msearchz) {
if (this.object.position.z > mz) {
this.object.position.z += ( -1 * ( actualMoveSpeed + this.autoSpeedFactor ) );
if( this.object.position.z < mz){
this.object.position.z = mz;
msearchz = false;
}
} else {
this.object.position.z += ( 1 * ( actualMoveSpeed + this.autoSpeedFactor ) );
if( this.object.position.z > mz) {
this.object.position.z = mz;
msearchz = false;
}
}
}
if (msearchx) {
if (this.object.position.x > mx) {
this.object.position.x += (-1 * ( actualMoveSpeed + this.autoSpeedFactor ) );
if( this.object.position.x < mx) {
this.object.position.x = mx;
msearchx = false;
}
} else {
this.object.position.x += ( 1 * ( actualMoveSpeed + this.autoSpeedFactor ) );
if( this.object.position.x > mx) {
this.object.position.x = mx;
msearchx = false;
}
}
}
if (this.lon > 360) {
this.lon = this.lon - 360;
} else if (this.lon < 0) {
this.lon = 360 + this.lon;
}
if (msearchlon) {
if (this.lon - mlon > 0) {
this.lon += ( -1.5 );
if (this.lon <= mlon) {
//alert("negative");
this.lon = mlon;
msearchlon = false;
}
} else {
this.lon += ( 1.5 );
if (this.lon >= mlon) {
//alert("positive");
this.lon = mlon;
msearchlon = false;
}
}
}
if (msearchlat) {
if (this.lat > mlat) {
this.lat += ( -0.5 );
if (this.lat < mlat) {
this.lat = mlat;
msearchlat = false;
}
} else {
this.lat += ( 0.5 );
if (this.lat > mlat) {
this.lat = mlat;
msearchlat = false;
}
}
}
if (!this.noFly) {
if ( this.moveUp ) {
this.object.translateY( actualMoveSpeed );
}
if ( this.moveDown ) {
this.object.translateY( - actualMoveSpeed );
}
}
var actualLookSpeed = delta * this.lookSpeed;
if ( !this.activeLook ) {
actualLookSpeed = 0;
}
this.lon += this.mouseX * actualLookSpeed;
if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; // * this.invertVertical?-1:1;
this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
this.phi = ( 90 - this.lat ) * Math.PI / 180;
this.theta = this.lon * Math.PI / 180;
var targetPosition = this.target,
position = this.object.position;
targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
targetPosition.y = position.y + 100 * Math.cos( this.phi );
targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
}
var verticalLookRatio = 1;
if ( this.constrainVertical ) {
verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
}
this.lon += this.mouseX * actualLookSpeed;
if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
this.phi = ( 90 - this.lat ) * Math.PI / 180;
this.theta = this.lon * Math.PI / 180;
if ( this.constrainVertical ) {
this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax );
}
var targetPosition = this.target,
position = this.object.position;
targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
targetPosition.y = position.y + 100 * Math.cos( this.phi );
targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
myobject.object.lookAt ( targetPosition );
};
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
//this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
//this.domElement.addEventListener( 'mousedown', bind( this, this.onMouseDown ), false );
//this.domElement.addEventListener( 'mouseup', bind( this, this.onMouseUp ), false );
this.domElement.addEventListener( 'keydown', bind( this, this.onKeyDown ), false );
this.domElement.addEventListener( 'keyup', bind( this, this.onKeyUp ), false );
function bind( scope, fn ) {
return function(){
fn.apply( scope, arguments );
};
};
myobject = this;
};
Add keyboard controls for flight, maybe:
http://webmaestro.fr/character-controls-three-js/
or
http://stackoverflow.com/questions/13261270/first-person-simulation-with-three-js-using-keyboard-arrows