Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First Person Flight Controls #3

Open
ibuilder opened this issue Aug 15, 2014 · 1 comment
Open

First Person Flight Controls #3

ibuilder opened this issue Aug 15, 2014 · 1 comment

Comments

@ibuilder
Copy link
Member

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

@ibuilder
Copy link
Member Author

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;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant