Three JS white screen when loading JSON object - javascript

I downloaded threejs and now try to create a 3D environment where you can move freely in some kind of "ego perspective". I used the pointlock-control example as submission and now I'm on to add my own stuff starting with a car created in Blender and exported as JSON but every time I try to load it I get just a white screen. I hope you guys can help me.
Code:
<style>
html, body {
width: 100%;
height: 100%;
}
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
font-family: arial;
}
#blocker {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
#instructions {
width: 100%;
height: 100%;
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
box-orient: horizontal;
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
color: #ffffff;
text-align: center;
cursor: pointer;
}
</style>
</head>
<body>
<script src="../build/three.min.js"></script>
<script src="js/controls/PointerLockControls.js"></script>
<div id="blocker">
<div id="instructions">
<span style="font-size:40px">Click to move</span>
<br />
(WASD or Arrow Keys = Move, SPACE = Jump, MOUSE = Look around)
</div>
</div>
<script>
var camera, scene, renderer;
var geometry, material, mesh;
var loader;
var auto;
var loadModel;
var controls,time = Date.now();
var objects = [];
var ray;
var blocker = document.getElementById( 'blocker' );
var instructions = document.getElementById( 'instructions' );
// http://www.html5rocks.com/en/tutorials/pointerlock/intro/
var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
if ( havePointerLock ) {
var element = document.body;
var pointerlockchange = function ( event ) {
if ( document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element ) {
controls.enabled = true;
blocker.style.display = 'none';
} else {
controls.enabled = false;
blocker.style.display = '-webkit-box';
blocker.style.display = '-moz-box';
blocker.style.display = 'box';
instructions.style.display = '';
}
}
var pointerlockerror = function ( event ) {
instructions.style.display = '';
}
// Hook pointer lock state change events
document.addEventListener( 'pointerlockchange', pointerlockchange, false );
document.addEventListener( 'mozpointerlockchange', pointerlockchange, false );
document.addEventListener( 'webkitpointerlockchange', pointerlockchange, false );
document.addEventListener( 'pointerlockerror', pointerlockerror, false );
document.addEventListener( 'mozpointerlockerror', pointerlockerror, false );
document.addEventListener( 'webkitpointerlockerror', pointerlockerror, false );
instructions.addEventListener( 'click', function ( event ) {
instructions.style.display = 'none';
// Ask the browser to lock the pointer
element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
if ( /Firefox/i.test( navigator.userAgent ) ) {
var fullscreenchange = function ( event ) {
if ( document.fullscreenElement === element || document.mozFullscreenElement === element || document.mozFullScreenElement === element ) {
document.removeEventListener( 'fullscreenchange', fullscreenchange );
document.removeEventListener( 'mozfullscreenchange', fullscreenchange );
element.requestPointerLock();
}
}
document.addEventListener( 'fullscreenchange', fullscreenchange, false );
document.addEventListener( 'mozfullscreenchange', fullscreenchange, false );
element.requestFullscreen = element.requestFullscreen || element.mozRequestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen;
element.requestFullscreen();
} else {
element.requestPointerLock();
}
}, false );
} else {
instructions.innerHTML = 'Your browser doesn\'t seem to support Pointer Lock API';
}
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xffffff, 0, 750 );
var light = new THREE.DirectionalLight( 0xffffff, 1.5 );
light.position.set( 1, 1, 1 );
scene.add( light );
var light = new THREE.DirectionalLight( 0xffffff, 0.75 );
light.position.set( -1, - 0.5, -1 );
scene.add( light );
controls = new THREE.PointerLockControls( camera );
scene.add( controls.getObject() );
ray = new THREE.Raycaster();
ray.ray.direction.set( 0, -1, 0 );
// floor
geometry = new THREE.PlaneGeometry( 2000, 2000, 100, 100 );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
var vertex = geometry.vertices[ i ];
vertex.x += Math.random() * 20 - 10;
vertex.y += Math.random() * 2;
vertex.z += Math.random() * 20 - 10;
}
for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) {
var face = geometry.faces[ i ];
face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
face.vertexColors[ 3 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
}
material = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// objects
loader = new THREE.JSONLoader( );
loadModel = function(geometry)
{
auto = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { envMap: THREE.ImageUtils.loadTexture( 'textures/metal.jpg', new THREE.SphericalReflectionMapping() ), overdraw: true, shading: THREE.SmoothShading } ) );
mesh.scale.set(1, 1, 1);
mesh.position.set(0, 150, 0);
//mesh.rotation.set(Math.PI/2, Mat.PI/2, Math.PI/2);
//mesh.matrix.setRotationFromEuler(mesh.rotation);
scene.add( auto );
};
loader.load('blender.js/auto.js', loadModel );
setInterval(render, 50);
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.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 );
controls.isOnObject( false );
ray.ray.origin.copy( controls.getObject().position );
ray.ray.origin.y -= 10;
var intersections = ray.intersectObjects( objects );
if ( intersections.length > 0 ) {
var distance = intersections[ 0 ].distance;
if ( distance > 0 && distance < 10 ) {
controls.isOnObject( true );
}
}
controls.update( Date.now() - time );
renderer.render( scene, camera );
time = Date.now();
}
</script>
</body>

var intersections = ray.intersectObjects( objects ); but you aren't adding your mesh to objects.

Your camera does not have position nor target.

Background color of body and text "color" in instructions is same #ffffff in style.
Please change one of them, and then try :)
It may be giving out put but you may not see it,
Update:
You are adding scene here scene.add(mesh2); I think we should follow the working code(below) and redraw the scene(using loop or timer, every "0.05 second"), don't add new scene, use simple example like round to move then proceed with complex car, that may confuse sometimes..
Working Code:
loader = new THREE.JSONLoader();
loadModel = function (geometry) {
mesh2 = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
envMap : THREE.ImageUtils.loadTexture('textures/metal.refl.jpg', new THREE.SphericalReflectionMapping()),
overdraw : true,
shading : THREE.SmoothShading
}));
mesh2.scale.set(1, 1, 1);
mesh2.position.set(0, 0, 0);
//mesh.rotation.set(Math.PI/2, Mat.PI/2, Math.PI/2);
//mesh.matrix.setRotationFromEuler(mesh.rotation);
scene.add( mesh2 );
};
Comment if not solved using this

Related

How to drag and rotate multiple objects using Three.js

In order to find the best relative position for each object, if I want to move, rotate multiple objects like 10 objects by clicking and dragging objects using Three.js, are there any other efficient ways to do that? I found the real example ((https://codepen.io/OpherV/pen/YXwwNR). However, it seems good for just 1 or 2 objects. Could you please advise any examples or solutions using Three.js?
Thanks a lot.
/**
* Provides requestAnimationFrame in a cross browser way.
* #author paulirish / http://paulirish.com/
*/
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = (function() {
return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000 / 60);
};
})();
}
var container, stats;
var camera, scene, renderer;
var cube, plane;
var targetRotationX = 0.5;
var targetRotationOnMouseDownX = 0;
var targetRotationY = 0.2;
var targetRotationOnMouseDownY = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var mouseY = 0;
var mouseYOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var slowingFactor = 0.25;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 150;
camera.position.z = 500;
scene.add( camera );
var materials = [];
for ( var i = 0; i < 6; i ++ ) {
materials.push( new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) );
}
cube = new THREE.Mesh( new THREE.BoxGeometry( 200, 200, 200 ) , new THREE.MeshFaceMaterial(materials) );
cube.position.y = 150;
cube.overdraw = true;
scene.add( cube );
plane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200 ), new THREE.MeshBasicMaterial( { color: 0xe0e0e0 } ) );
plane.rotation.x = - 90 * ( Math.PI / 180 );
plane.overdraw = true;
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDownX = targetRotationX;
mouseYOnMouseDown = event.clientY - windowHalfY;
targetRotationOnMouseDownY = targetRotationY;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotationX = ( mouseX - mouseXOnMouseDown ) * 0.00025;
mouseY = event.clientY - windowHalfY;
targetRotationY = ( mouseY - mouseYOnMouseDown ) * 0.00025;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
rotateAroundWorldAxis(cube, new THREE.Vector3(0, 1, 0), targetRotationX);
rotateAroundWorldAxis(cube, new THREE.Vector3(1, 0, 0), targetRotationY);
targetRotationY = targetRotationY * (1 - slowingFactor);
targetRotationX = targetRotationX * (1 - slowingFactor);
renderer.render( scene, camera );
}
function rotateAroundObjectAxis(object, axis, radians) {
var rotationMatrix = new THREE.Matrix4();
rotationMatrix.makeRotationAxis(axis.normalize(), radians);
object.matrix.multiply(rotationMatrix);
object.rotation.setFromRotationMatrix( object.matrix );
}
function rotateAroundWorldAxis( object, axis, radians ) {
var rotationMatrix = new THREE.Matrix4();
rotationMatrix.makeRotationAxis( axis.normalize(), radians );
rotationMatrix.multiply( object.matrix ); // pre-multiply
object.matrix = rotationMatrix;
object.rotation.setFromRotationMatrix( object.matrix );
}
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
.caption{
padding: 1rem;
color: white;
background: black;
font-size: 2rem;
text-align:center;
}
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - Object drag rotation in Three.js</title>
<link rel="stylesheet" href="./style.css">
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/loaders/OBJLoader.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/stats.js/r11/Stats.min.js'></script>
</head>
<body>
<!-- partial:index.partial.html -->
<div class="caption">Drag to rotate</div>
<!-- partial -->
</body>
<script src="./script.js"></script>
</html>

Mousemove event with three.js and gsap

I am trying to do a mousemove event where the mesh would scale when the mouse hovers over it and then it goes back to its original size when the mouse no longer hovers above it. So I've been looking at other examples and they don,t use gsap. The closest one I've seen is tween.js so maybe my syntax is wrong but I don't know how to rectify it.
Here is my function
function onMouseMove(event) {
//finding position of mouse
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera(mouse,camera);
// meshes included in mousemove
objects.push( mesh);
objects.push( mesh2 );
//including objects into intersects
var intersects = raycaster.intersectObjects(objects, true);
//if statement for intersection
if ( intersects.length > 0 ) {
if ( intersects[ 0 ].object != INTERSECTED )
{
if ( INTERSECTED )
//gsap animation
INTERSECTED.gsap.to(intersects[0].object.scale, {duration: .7, x: 1.2, y:1.2});
INTERSECTED = intersects[ 0 ].object;
}
} else {// there are no intersections
// restore previous intersection object to its original size
if ( INTERSECTED )
gsap.to(intersects[0].object.scale, {duration: .7, x: 1, y:1});
INTERSECTED = null;
}
}
With this I get an error:
Cannot read property 'object' of undefined
at onMouseMove
But when I previously did a for loop with undefined object, the code works, but I just need it to scale down again
Here is my for loop:
for(var i = 0; i < intersects.length; i++) {
gsap.to(intersects[i].object.scale, {duration: .7, x: 1.2, y:1.2});
};
EDIT:
created a fiddle, using the for loop but commented out the if statement:
let camera, scene, renderer, cube, cube1;
let raycaster;
let mouse = new THREE.Vector2(), INTERSECTED;
const objects = [];
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.z = 20;
scene = new THREE.Scene();
const geometry = new THREE.BoxBufferGeometry(3,3,3);
const material = new THREE. MeshBasicMaterial({ color: 0x00ff00 });
cube = new THREE.Mesh(geometry, material);
cube.position.y = 5;
scene.add(cube);
const geometry1 = new THREE.BoxBufferGeometry(3,3,3);
const material1 = new THREE. MeshBasicMaterial({ color: 0x00ff00 });
cube1 = new THREE.Mesh(geometry1, material1);
scene.add(cube1);
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener('mousemove',onMouseMove, false);
}
// animation
function onMouseMove (event) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera(mouse,camera);
//included in mousemove
objects.push( cube );
objects.push( cube1 );
var intersects = raycaster.intersectObjects(objects, true);
//working for loop
for(var i = 0; i < intersects.length; i++) {
gsap.to(intersects[i].object.scale, {duration: .7, x: 1.2, y:1.2});
}
//not working if statement
/*
if ( intersects.length > 0 ) {
if ( intersects[ 0 ].object != INTERSECTED )
{
if ( INTERSECTED )
INTERSECTED.gsap.to(intersects[0].object.scale, {duration: .7, x: 1.2, y:1.2});
INTERSECTED = intersects[ 0 ].object;
}
} else {// there are no intersections
// restore previous intersection object (if it exists) to its original size
if ( INTERSECTED )
gsap.to(intersects[0].object.scale, {duration: .7, x: 1.2, y:1.2});
INTERSECTED = null;
}
*/
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.114/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap#3.2.4/dist/gsap.js"></script>
Try it with this updated code:
let camera, scene, renderer, cube, cube1;
let raycaster;
let mouse = new THREE.Vector2(), INTERSECTED = null;
const objects = [];
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.z = 20;
scene = new THREE.Scene();
const geometry = new THREE.BoxBufferGeometry( 3, 3, 3 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cube = new THREE.Mesh( geometry, material );
cube.position.y = 5;
scene.add( cube );
const geometry1 = new THREE.BoxBufferGeometry( 3, 3, 3 );
const material1 = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cube1 = new THREE.Mesh( geometry1, material1 );
scene.add( cube1 );
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'mousemove', onMouseMove, false );
}
function onMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
//included in mousemove
objects.push( cube );
objects.push( cube1 );
var intersects = raycaster.intersectObjects( objects, true );
if ( intersects.length > 0 ) {
var object = intersects[ 0 ].object;
if ( object !== INTERSECTED ) {
INTERSECTED = object;
gsap.to( INTERSECTED.scale, { duration: .7, x: 1.2, y: 1.2 } );
}
} else {
if ( INTERSECTED !== null ) {
gsap.to( INTERSECTED.scale, { duration: .7, x: 1, y: 1 } );
INTERSECTED = null;
}
}
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.114/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap#3.2.4/dist/gsap.js"></script>

How to render multiple videos on a sphere using three.js

Three.js is new to me, so I am a bit stuck on this.
I read the answer to this question: Using multiuple textures on a sphere [Three.js]
The answer suggests the user to use a cube to load the textures on, instead of sphere.That being done, the cube can be expanded to a sphere.
var geometry = new THREE.BoxGeometry( 1, 1, 1, 8, 8, 8 );
for ( var i in geometry.vertices ) {
var vertex = geometry.vertices[ i ];
vertex.normalize().multiplyScalar(radius);
}
var materialArray = [];
var faceMaterial = new THREE.MeshLambertMaterial({
color: sphereColor,
transparent: true,
opacity: 0.4
});
for (var i = 0; i < 6; i++) {
materialArray.push(faceMaterial);
}
var material = new THREE.MeshFaceMaterial(materialArray);
var sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
Will the same thing work for videos? If I wish to play six videos on a sphere, should I load the 'video' texture onto the six faces of the cube and then expand it to a sphere.
EDIT:
I have the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - equirectangular video panorama</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 {
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
font-weight: bold;
text-align:center;
}
a {
color: #ffffff;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="three.js"></script>
<script>
var camera, scene, renderer;
var texture_placeholder,
isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0,
distance = 500;
init();
animate();
function init() {
var container, mesh;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
//var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
//geometry.scale( - 1, 1, 1 );
var geometry = new THREE.BoxBufferGeometry( 1,1,1,32,32,32 );
geometry.scale( - 1, 1, 1 );
for ( var i in geometry.vertices ) {
var vertex = geometry.vertices[ i ];
vertex.normalize().multiplyScalar(distance);
}
//var video = document.createElement( 'video' );
//video.width = 640;
//video.height = 360;
//video.autoplay = true;
//video.loop = true;
//video.src = "pano.webm";
var path = "vids/";
var format = '.mp4';
var urls = [
path + 'Row1Col1' + format, path + 'Row1Col2' + format,
path + 'Row1Col3' + format, path + 'Row2Col1' + format,
path + 'Row2Col2' + format, path + 'Row2Col3' + format
];
var reflectionCube = new THREE.CubeTextureLoader().load( urls );
reflectionCube.minFilter = THREE.LinearFilter;
reflectionCube.format = THREE.RGBFormat;
//var texture = new THREE.VideoTexture( video );
//texture.minFilter = THREE.LinearFilter;
//texture.format = THREE.RGBFormat;
//var material = new THREE.MeshBasicMaterial( { map : texture } );
//mesh = new THREE.Mesh( geometry, material );
//scene.add( mesh );
var materialArray = [];
var faceMaterial = new THREE.MeshLambertMaterial({
color: 0xffff00,
transparent: true,
opacity: 0.4
});
for (var i = 0; i < 6; i++) {
materialArray.push(faceMaterial);
}
var material = new THREE.MeshFaceMaterial(materialArray);
var sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
//End of what I have added
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
document.addEventListener( 'MozMousePixelScroll', onDocumentMouseWheel, false);
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
isUserInteracting = true;
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
}
function onDocumentMouseMove( event ) {
if ( isUserInteracting === true ) {
lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
}
}
function onDocumentMouseUp( event ) {
isUserInteracting = false;
}
function onDocumentMouseWheel( event ) {
// WebKit
if ( event.wheelDeltaY ) {
distance -= event.wheelDeltaY * 0.05;
// Opera / Explorer 9
} else if ( event.wheelDelta ) {
distance -= event.wheelDelta * 0.05;
// Firefox
} else if ( event.detail ) {
distance += event.detail * 1.0;
}
}
function animate() {
requestAnimationFrame( animate );
update();
}
function update() {
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.position.x = distance * Math.sin( phi ) * Math.cos( theta );
camera.position.y = distance * Math.cos( phi );
camera.position.z = distance * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( camera.target );
/*
// distortion
camera.position.copy( camera.target ).negate();
*/
renderer.render( scene, camera );
}
</script>
</body>
However, it does not work. After I host it on the web there's just a black screen. Can you tell me where am I going wrong?
Based on some of my recent findings working with 360 videos in threejs (I am also new to threejs), you could be seeing the black screen due to the overall resolution being too high. If each video is at 4k resolution, then you are trying to display a 24k res video. I start encountering issues where I get black screen after 5.7k, even on higher end equipment and 100+ mbps network speeds.

Three.js issue creating meshes outside of loader's load() function

I had difficulty exporting more than one texture using Blender's Three.js add-on, so had planned to work around it be separating the parts into separate meshes, but then came across the unexpected problem of the code not working when I created the meshes outside of the load() function. I've supplied an example below using a single model with a single mesh. The following works fine:
<!DOCTYPE html>
<html lang="en">
<head>
<title>working</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: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="js/build/three.min.js"></script>
<script src="js/loaders/ColladaLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var camera, scene, renderer, objects;
var scaleAdj = 100;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 0, 500, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
var loader = new THREE.JSONLoader();
loader.load( 'cube.json', function ( geometry, materials )
{
var faceMaterial = new THREE.MultiMaterial( materials );
for ( var i = 0; i < 250; i ++ )
{
var x = ( ( i % 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
mesh = new THREE.Mesh( geometry, faceMaterial );
var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
mesh.scale.set( s, s, s );
mesh.position.set( x, scaleAdj, z );
mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
}
} );
scene.add( new THREE.AmbientLight( 0xffffff ) );
// ground
var textureLoader = new THREE.TextureLoader();
var groundTexture = textureLoader.load( "texture.jpg" );
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set( 40, 40 );
groundTexture.anisotropy = 16;
var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
// Renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
But this doesn't (I've annotated which sections contain the differences):
<!DOCTYPE html>
<html lang="en">
<head>
<title>not working</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: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="js/build/three.min.js"></script>
<script src="js/loaders/ColladaLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
//--------------- difference number 1
var obj_geometry;
var obj_material;
//-----------------------------------
var container;
var camera, scene, renderer, objects;
var scaleAdj = 100;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 0, 500, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
//-------------------difference number 2--------------------
var loader = new THREE.JSONLoader();
loader.load( 'cube.json', function ( geometry, material )
{
obj_geometry = geometry;
obj_material = material;
});
var faceMaterial = new THREE.MultiMaterial( obj_material);
for ( var i = 0; i < 250; i ++ )
{
var x = ( ( i % 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
mesh = new THREE.Mesh( obj_geometry, faceMaterial);
var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
mesh.scale.set( s, s, s );
mesh.position.set( x, 0, z );
mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
}
//--------------------------------------
scene.add( new THREE.AmbientLight( 0xffffff ) );
// ground
var textureLoader = new THREE.TextureLoader();
var groundTexture = textureLoader.load( "texture.jpg" );
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set( 40, 40 );
groundTexture.anisotropy = 16;
var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
// Renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
Here is a copy of the contents of the cube.json file:
{
"uvs":[[0,0,1,0,1,1,0,1]],
"faces":[43,0,1,2,3,0,0,1,2,3,0,1,2,3,43,4,7,6,5,0,0,1,2,3,4,5,6,7,43,0,4,5,1,0,0,1,2,3,0,4,7,1,43,1,5,6,2,0,0,1,2,3,1,7,6,2,43,2,6,7,3,0,0,1,2,3,2,6,5,3,43,4,0,3,7,0,0,1,2,3,4,0,3,5],
"normals":[0.577349,-0.577349,-0.577349,0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,-0.577349,0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,0.577349,0.577349,0.577349,0.577349],
"metadata":{
"generator":"io_three",
"type":"Geometry",
"normals":8,
"vertices":8,
"uvs":1,
"version":3,
"materials":1,
"faces":6
},
"vertices":[1,-1,-1,1,-1,1,-1,-1,1,-1,-1,-1,1,1,-1,0.999999,1,1,-1,1,1,-1,1,-1],
"materials":[{
"DbgName":"Material",
"colorSpecular":[0.5,0.5,0.5],
"DbgIndex":0,
"mapDiffuseWrap":["RepeatWrapping","RepeatWrapping"],
"mapDiffuse":"texture.jpg",
"shading":"phong",
"depthTest":true,
"opacity":1,
"transparent":false,
"colorDiffuse":[0.64,0.64,0.64],
"mapDiffuseAnisotropy":1,
"blending":"NormalBlending",
"depthWrite":true,
"visible":true,
"specularCoef":50,
"mapDiffuseRepeat":[1,1],
"colorEmissive":[0,0,0],
"wireframe":false,
"DbgColor":15658734
}],
"name":"CubeGeometry"
}
And here is an attached texture which could be used.
It might just be a trivial problem for some of the posters on here, and if so, thanks in advance for just letting me know what it is. If not, then the answer could be useful to a lot more people, and thanks for any help you can give on it.
You cant do this, asynchronously:
var obj_geometry; // === undefined
var myMesh = new THREE.Mesh( obj_geometry ); //because undefined, same as calling new THREE.Mesh();
obj_geometry = geometry;//does nothing, mesh has no idea about this happening
obj_material = material;
When you construct a mesh, you've given it undefined for geometry, so i think it just calls new Geometry() inside the constructor. This mesh has been created with a unique isntance of empty Geometry and has nothing to do with your obj_geometry.
The solution here is to do:
var obj_geometry = new THREE.Geometry();
var myMesh = new THREE.Mesh( obj_geometry ); //holds a reference to an empty "proxy"
then onLoad
loader.load( 'url' , function( geom ) {
obj_geometry.merge(geom); //"FILL PREVIOUSLY CREATED GEOMETRY WITH DATA"
obj_geometry.vertsNeedUpdate = true; // there's a few flags like this you need to turn on
}
OR
var myMesh = new THREE.Mesh();
loader.load( 'url', function( geom ) {
myMesh.geometry = geom; //"PUT THE JUST CREATED GEOMETRY IN THE RIGHT PLACE"
//myOtherMesh.geometry = geom; //if you have more places where this needs to end up
//myThirdMesh.geometry = geom; //gets very cumbersome
}
Both are pretty cumbersome and not very intuitive :( i really dislike this part of three.js.
Thanks to help from pailhead, pointing out the asynchronous issue I made the following modification to the code and found that it worked. Surprisingly the count that I added doesn't seem to raise above 0, but I am assuming that it was because it was quite a close run thing.
<!DOCTYPE html>
<html lang="en">
<head>
<title>asynchronous working</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: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="build/three.min.js"></script>
<script>
//--------------- difference number 1
var obj_geometry;
var obj_material;
var loaded = false;
//-----------------------------------
var container;
var camera, scene, renderer, objects;
var scaleAdj = 100;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
//-----an info display
info = document.createElement( 'div' );
info.id = "info";
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
container.appendChild(info);
//-----------------
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 0, 500, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
//-------------------difference number 2--------------------
var loader = new THREE.JSONLoader();
loader.load( 'cube.json', function ( geometry, material )
{
obj_geometry = geometry;
obj_material = material;
loaded = true;
});
var notLoadedCount = 0;
var processor = setInterval(function()
{
if(!loaded)
{
notLoadedCount++;
}
else
{
var faceMaterial = new THREE.MultiMaterial( obj_material);
for ( var i = 0; i < 250; i ++ )
{
var x = ( ( i % 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
mesh = new THREE.Mesh( obj_geometry, faceMaterial);
var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
mesh.scale.set( s, s, s );
mesh.position.set( x, 0, z );
mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
info.innerHTML= '*not loaded count = ' + notLoadedCount;
}
clearInterval(processor);
}
}, 100);
//--------------------------------------
scene.add( new THREE.AmbientLight( 0xffffff ) );
// ground
var textureLoader = new THREE.TextureLoader();
var groundTexture = textureLoader.load( "texture.jpg" );
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set( 40, 40 );
groundTexture.anisotropy = 16;
var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
// Renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
Thanks for the help with this, hopefully it helps others too. If there are any problems with this resolution that anybody notices, please let me know. Thanks.

Clickable Three JS Convex Objects (once clicked reveals image)

I adjusted an example from the three js website.
I'm looking for making the small floating objects have a click event.
The click event would trigger an image or video revealed on the larger convex shape in the center
Concept + Images
http://kevinwitkowski.tumblr.com/post/109592122645/workshop-update
Working Sample
Here is my current code.
var container;
var camera, scene, renderer;
var mesh;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
// array of functions for the rendering loop
var onRenderFcts= [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xd6e3e8, 0.0030 );
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.z = 0;
controls = new THREE.OrbitControls(camera)
var light, object, materials;
light = new THREE.DirectionalLight( 0xe8dbd6 );
light.position.set( -50, -80, -10 );
scene.add( light );
light = new THREE.DirectionalLight( 0xd6dae8 );
light.position.set( 20, 120, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0xd6e8e4 );
light.position.set( 0, 1, 30 );
scene.add( light );
var map = THREE.ImageUtils.loadTexture( 'textures/1.jpeg' );
map.wrapS = map.wrapT =
THREE.RepeatWrapping;
map.anisotropy = 16;
var materials = [
new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } )
//new THREE.MeshBasicMaterial( { color: 0x00000, shading: THREE.FlatShading, wireframe: true, transparent: false, opacity: 0.5} )
];
// random convex 1
points = [];
for ( var i = 0; i < 30; i ++ ) {
points.push( randomPointInSphere( 50 ) );
}
object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials );
object.position.set( 0, 0, 0);
scene.add( object );
// random convex 2
points = [];
for ( var i = 0; i < 30; i ++ ) {
points.push( randomPointInSphere( 15 ) );
}
object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials );
object.position.set( 15, 50, -60 );
scene.add( object );
// random convex 3
points = [];
for ( var i = 0; i < 30; i ++ ) {
points.push( randomPointInSphere( 15 ) );
}
object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials );
object.position.set( 30, 10, 80 );
scene.add( object );
// random convex 4
points = [];
for ( var i = 0; i < 30; i ++ ) {
points.push( randomPointInSphere( 8 ) );
}
object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials );
object.position.set( -80, -50, 20 );
scene.add( object );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0xf5f5f5 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, true );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
//
function randomPointInSphere( radius ) {
return new THREE.Vector3(
( Math.random() - 0.5 ) * 1 * radius,
( Math.random() - 0.5 ) * 2 * radius,
( Math.random() - 0.5 ) * 2 * radius
);
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var timer = Date.now() * 0.00005;
camera.position.x = Math.cos( timer ) * 300;
camera.position.z = Math.sin( timer ) * 300;
camera.lookAt( scene.position );
for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
var object = scene.children[ i ];
object.rotation.x = timer * 1;
object.rotation.y = timer * 3;
}
// handle window resize
window.addEventListener('resize', function(){
renderer.setSize( window.innerWidth, window.innerHeight )
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
}, true)
renderer.render( scene, camera );
}
var lastTimeMsec= null
requestAnimationFrame(function animate(nowMsec){
// keep looping
requestAnimationFrame( animate );
// measure time
lastTimeMsec = lastTimeMsec || nowMsec-1000/60
var deltaMsec = Math.min(200, nowMsec - lastTimeMsec)
lastTimeMsec = nowMsec
// call each update function
onRenderFcts.forEach(function(onRenderFct){
onRenderFct(deltaMsec/1000, nowMsec/1000)
})
})
The normal way of doing this is using a THREE.Raycaster and THREE.Projector to cast a ray from the camera through space, then finding if an object intersects with this ray.
See this example: http://soledadpenades.com/articles/three-js-tutorials/object-picking/
Thankfully, others have implemented libraries such as ObjectControls: https://github.com/cabbibo/ObjectControls
This allows you to directly attach hover or select events to meshes and it will just work.
CreateMultiMaterialObject method creates an object3D, so when you click, it is necessary to specify the second parameter (recursion) = true:
var intersects = raycaster.intersectObjects( objects, true );
if ( intersects.length > 0 ) {
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}

Categories

Resources