OrbitControls issue when zoom in a larger webpage - javascript

I embed misc_controls_orbit example in 800x600 frame inside a larger webpage with other content.
My problem is when i scroll my mousewheel, it's do both scroll the webpage and zoom my object even when my mouse is inside or outside the frame.
What i need now is when my mouse is inside the frame, it's only zoom the object, not scroll all webpage with it, and when the mouse is outside the frame, it's will only scroll the webpage, not zoom object (like Sketchfab embeds here:http://www.klaasnienhuis.nl/2012/09/sketchfab-embeds/ )
This problem seem like only happen with OrbitControls, Trackball is not, i had search and try in many way but still no result, can anyone help me? (sr my bad english, hope you understand, plz ask if you don't)
this is original misc_controls_orbit code i'm using:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - orbit controls</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - orbit controls example
</div>
<script src="../build/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
// world
var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 );
var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } );
for ( var i = 0; i < 500; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
}
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
stats.update();
}
</script>
</body>

Use a canvas to render webgl and add an event listener
Use this html:
<canvas id="webglcanvas" width="800" height="600"></canvas>
with this javascript
function onMouseWheel(evt) {
evt.preventDefault();
/* TODO : your zoom */
}
function addMouseHandler(canvas) {
canvas.addEventListener('mousemove', onMouseMove, false);
canvas.addEventListener('mousedown', onMouseDown, false);
canvas.addEventListener('mouseup', onMouseUp, false);
canvas.addEventListener('onwheel' in document ? 'wheel' : 'mousewheel', onMouseWheel, false);
}
function createScene(canvas) {
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
});
// Set the viewport size
renderer.setSize(canvas.width, canvas.height);
}
$(document).ready(function () {
var canvas = document.getElementById("webglcanvas");
// create the scene
createScene(canvas);
// add mouse handling so we can rotate the scene
addMouseHandler(canvas);
// Run the run loop
run();
});

Related

Textures are Black in Three.JS

I have a model i'm exporting from blender 2.76b into json and then loading with three.js 71. Blender the model looks fine. In webGL the model is completely black. I'm think it has something to do with the textures but i'm not sure. The model is a fairly complex model made from maya and exported as an fbx. I've tested with simpler models and different textures and not had any problems but there's something wrong with this one.
Any suggestions would be appreciated greatly.
Link to the json: http://we.tl/GnQiOfAhOD
Here's the code.
<!DOCTYPE html>
<html lang="en">
<head>
<title>MultiLoader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #000;
margin: 0px;
overflow: hidden;
}
#info {
text-align: center;
padding: 10px;
z-index: 10;
width: 100%;
position: absolute;
}
a {
text-decoration: underline;
cursor: pointer;
}
#stats { position: absolute; top:0; left: 0 }
#stats #fps { background: transparent !important }
#stats #fps #fpsText { color: #aaa !important }
#stats #fps #fpsGraph { display: none }
</style>
</head>
<body>
<div id="info">MultiLoader Testing</div>
<script src="build/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/ColladaLoader.js"></script>
<script src="js/OBJLoader.js"></script>
<script>
WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 1,
FAR = 10000;
var container, stats;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// SCENE
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xffffff, 500, 10000 );
// CAMERA
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(60, 40, 120);
camera.lookAt(scene.position);
scene.add(camera);
//LIGHTS
var front = new THREE.DirectionalLight( 0xffffff, 5.4 );
front.position.set( 0, 140, 1500 );
front.position.multiplyScalar( 1.1 );
//front.color.setHSL( 0.6, 0.075, 1 );
scene.add( front );
var ambient = new THREE.AmbientLight(0xffffff);
scene.add( ambient );
var back = new THREE.DirectionalLight( 0xffffff, 0.5 );
back.position.set( 0, -140, -1500);
scene.add( back );
//Avatar Tests
var loader = new THREE.JSONLoader();
loader.load('models/Maya/modelExport.json', function ( geometry, materials ) {
material = new THREE.MeshFaceMaterial( materials );
avatar = new THREE.Mesh( geometry, material );
}
);
loader.onLoadComplete=function(){
avatar.scale.set(30, 30, 30);
var position = new THREE.Vector3(0,-20,0);
avatar.position.add(position);
scene.add( avatar );
}
// RENDERER
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMapEnabled = true;
container.appendChild( renderer.domElement );
// Orbit Controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
//
stats = new Stats();
container.appendChild( stats.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
There are several issues with the code and model.
For the model: The entry mapLight should have been named mapDiffuse. I know you are exporting the model so you need to find how to make this happen.
For the code:
Your ambient light is very strong. It washes out everything. Try a value of 0x222222 or remove it from the scene totally.
Your camera does not need to be added to the scene.
Remove renderer.setClearColor( fog_color ) just to see if you get the correct meshes and materials first. Then you can go the scene effects.
Your texture size is way big. It is not supported in webgl. Try a size of 1024 and then move up is you need to.
Finally your loader.onLoadComplete() is never called (and will never be). Move that part of the code in your loader.load() callback function.
After all this you will see your girl.

Three.js: Cannot change value in dat.GUI

i have an instance of dat.GUI. I added a "comboBox" to that instance to make a selection of possible values. When i run my app, the dat.GUI appears with the comboBox but there is a problem: I cannot change it's default value (my gui is frozen), here is my code:
<html>
<head>
<title>Stack Overflow</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/threex.dynamictexture.js"></script>
<script src="js/dat.gui.min.js"></script>
<script>
//Basic Three components
var scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000 );
//position camera
camera.position.z = 700;
//Set camera controls
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
//Set the renderer
var renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Set the lights
var light;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 1 );
scene.add( light );
//GUI
initGUI();
//Let's add a cube
var geometry = new THREE.BoxGeometry( 50, 50, 50 );
var material = new THREE.MeshBasicMaterial( { color: 0x5484d3 } );
var cube = new THREE.Mesh( geometry, material );
cube.position.set(0,20,50)
scene.add( cube );
function initGUI(){ //HERE IS THE MEAT, I THINK
var LevelView = function() {
this.level = 'Operacion';
// Define render logic ...
};
var gui = new dat.GUI();
var text = new LevelView();
gui.add(text, 'level', [ 'Operacion', 'Procesos', 'Participantes', 'Fuentes de Datos', 'Logica de software', 'Telecomunicaciones', 'Infraestructura'] ).onChange(function(value){
this.level = value;
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
//Render scene
function render() {
controls.update();
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
¿What i am doing wrong? I need to be able to change values with my GUI.
Solution: If you use a mouse-controlled camera with three.js, you have to comment the following line in the MouseListener of the mouseDown action:
event.preventDefault();
Place div containing dat.gui element bellow Three.js div
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
and then dat.gui
<div id="gui"></div>

TextGeometry not displaying, Could anyone tell me why?

I have the following Three.js code:
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script>
//Basic Three components
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Let´s add a cube
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
//Let´s add a text
var material2 = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
var textGeom = new THREE.TextGeometry( 'Sitescope', {
font: 'optimer',
weight: 'normal'
});
var textMesh = new THREE.Mesh( textGeom, material2 );
scene.add( textMesh );
//Render scene
function render() {
requestAnimationFrame( render );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
render();
</script>
</body>
When i run my code, My cube renders well but my text does not appear anywhere.
The only output that i get in the javascript console is:
THREE.WebGLRenderer 69.
Could anyone tell me why my text does not appear? (I am a beginner in Three.js) Thanks!
When using a THREE.MeshPhongMaterial() you need a light in the scene. Otherwise the model will come out black. If your scene background is also black you will never know if the model was drawn or not. Take a look at this fiddle. I am using THREE.MeshNormalMaterial(). Replace it with PhongMaterial to see what I am talking about. You can see the text is being drawn with black color just because it is over the green cube.

How to change the background by buttons on three.js?

I am new in three.js and using the following code I want to know how to change the background by clicking a button. So I think there is something different than using "switch" and "break". Here is something with .loadTexture am I right?
<html lang="en">
<head>
<title>gyroscopic</title>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, initial-scale=1">
<style>
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="three.min.js"></script>
<script src="DeviceOrientationControls.js"></script>
<script>
(function() {
"use strict"
window.addEventListener('load', function() {
var container, camera, scene, renderer, controls, geometry, mesh;
var animate = function(){
window.requestAnimationFrame( animate );
controls.update();
renderer.render(scene, camera);
};
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 1100);
controls = new THREE.DeviceOrientationControls( camera );
scene = new THREE.Scene();
var geometry = new THREE.SphereGeometry( 500, 316, 18 );
geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
var material = new THREE.MeshBasicMaterial( {
map: THREE.ImageUtils.loadTexture( 'pic.jpg' )
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var geometry = new THREE.BoxGeometry( 100, 100, 100, 4, 4, 4 );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = 0;
container.appendChild(renderer.domElement);
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false);
animate();
}, false);
})();
</script>
</body>
</html>
You should be able to change the texture using .loadTexture on a button click listener.
So you would probably add something like this to your HTML:
<button id="change-background">Change Background</button>
Then in Javascript:
var backgroundButton = document.getElementById('change-background');
backgroundButton.addEventListener('click', function(){
material.map = THREE.ImageUtils.loadTexture('//new image path//');
});
You'll obviously need to replace the //new image path// with whatever URL you have for the new image.
The only question would be whether this updates the material on the mesh as well. I'm sure it does, but have no way of testing it at present.

How can I load client .STL file into three.js scene instead of loading from server?

I have a 'choose file' button I want to use for loading a client side file instead of loading from the server path in loader.load() on line 86. I'm guessing I need to use File API but haven't figured out how after looking at this solution.
Existing web page that loads file from server path in line 86:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:#fea47c;
}
div {
position:relative;
left:200px;
top:0px;
background-color: #eeeeee;
border:1px solid black;
width:550px;
height:550px;
}
canvas {
width:550px;
height:550px;
}
input#file
{
position:relative;left:425px;
}
</style>
</head>
<body>
<input type="file" name="file" id="file"></input><br><br>
<script src="https://raw.github.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://raw.github.com/mrdoob/three.js/master/examples/js/loaders/STLLoader.js"></script>
<script src="https://raw.github.com/mrdoob/three.js/master/examples/js/controls/TrackballControls.js"></script>
<script>
var container, camera, scene, renderer, controls;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var width = container.clientWidth;
var height = container.clientHeight;
camera = new THREE.PerspectiveCamera(
35, // field of view in degrees?
width / height, // canvas based aspect ratio; use when canvas is smaller than page
.1 , // distance to nearest side of rendered space
10000 // distance to farthest side of rendered space
);
camera.position.set( 0, 0, 10);
scene = new THREE.Scene();
controls = new THREE.TrackballControls( camera , container);
controls.addEventListener( 'change', render );
// object
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var material = new THREE.MeshLambertMaterial( { ambient: 0xff5533, color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
loader.load( 'path to .stl file on server usually goes here' );
// lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position = camera.position;
scene.add( directionalLight );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width , height );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function addLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
}
function onWindowResize() {
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
Is the script on a server? In general web browsers are made to not permit file:// references except when the page itself is a file:// reference (and even then you might need to set some security/debug flags, varying according to the browser). So if you are running a webgl script in a page that's accessed via http:// you may be out of luck unless you piggyback through a file service like dropbox.

Categories

Resources