threeJs wrong (too low) camera position - javascript

I am new to ThreeJS, what I am trying to accomplish is to load a gltf model, which is correctly shown in three-gltf-viewer, it is valid.
When I load it into threeJS, the model loads up ok but the camera is placed on the horizon line of the model, and the orbit control does not work when I try to zoom in and out or any other rotation of the scene is disabled.
I tried to tweak any possible values of camera and scene but I just can't "jump on top" of the model and see it from above. Here is the code.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 800, window.innerWidth / window.innerHeight, 500, 1500000 );
camera.position.set(1, 1, 1);
var renderer = new THREE.WebGLRenderer({ alpha: false });
renderer.setClearColor( 0xC5C5C3 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls( camera, renderer.domElement );
var ambientLight = new THREE.AmbientLight( 0xcccccc );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 1, 1 ).normalize();
scene.add( directionalLight );
// Instantiate a loader
var loader = new THREE.GLTFLoader();
loader.load('GLTF_local_coord_sys/GEOTIFF_local_coord_sys.gltf',
function(gltf) {
var object = gltf.scene;
gltf.scene.scale.set( 0.65, 0.65, 0.65 );
gltf.scene.position.x = 1;
gltf.scene.position.y = 1;
gltf.scene.position.z = 1;
scene.add( gltf.scene );
camera.lookAt(scene.position);
},
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function ( error ) {
console.log( 'An error happened' );
}
);
camera.position.z =25;
function animate() {
render();
requestAnimationFrame( animate );
}
function render() {
renderer.render( scene, camera );
}
render();
animate();
Does anyone know how to fix this?

Related

How to center and resize 3d model in browser with three.js

I would like to build a full page application which will not have any scrolling and therefore I would like to center and resize my 3d model in the middle of my web page at all time no matter what screen size you use.
I have attempted this, but I am getting different centering outputs on different screen size, my code:
<script src="js/three.js"></script>
<script src="js/OBJLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script>
var scene, camera, renderer , controls, ambientLight, pointLight, textureLoader, map, material, loader;
function init() {
scene = new THREE.Scene();
initChris();
initCamera();
initRenderer();
initControl();
render();
}
function initCamera() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 5000);
ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
pointLight = new THREE.PointLight( 0xffffff, 0.8 );
camera.position.set(0, 0, 2500);
camera.add( pointLight );
scene.add( camera );
scene.add( ambientLight );
camera.lookAt(scene.position);
}
function initRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000, 0 );
}
function initControl(){
controls = new THREE.OrbitControls( camera );
controls.enableZoom = false;
controls.minPolarAngle = Math.PI * 0.5;
controls.maxPolarAngle = Math.PI * 0.5;
controls.update();
}
function initChris() {
textureLoader = new THREE.TextureLoader();
map = textureLoader.load('img/CHRIS.jpg');
material = new THREE.MeshPhongMaterial({map: map});
loader = new THREE.OBJLoader();
loader.load( 'obj/CHRIS.obj', function ( object ) {
object.traverse( function ( node ) {
if ( node.isMesh ){
node.material = material;
}
});
object.position.y = - window.innerHeight / 2;
scene.add( object );
});
}
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() {
document.body.appendChild(renderer.domElement);
requestAnimationFrame(render);
renderer.render(scene, camera);
window.addEventListener( 'resize', onWindowResize, false );
}
init();
</script>
Any help or advise is much appreciated. Thank you

Multiple STL files on single web page using threeJS

Here I have one STL file that I am displaying with threeJS. I don't know how to render multiple STL Files in single web page.
Here's my code:
var container, camera, scene, renderer;
init();
animate();
function init() {
container = document.getElementById('pratik');
document.body.appendChild( container );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 3, 0.5, 3 );
scene.add( camera ); // required, because we are adding a light as a child of the camera
// Controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
// lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
var light = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( light );
// object
var loader = new THREE.STLLoader();
loader.load( 'files/wolf.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
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();
}
function render() {
var timer = Date.now() * 0.0005;
camera.position.x = Math.cos( timer ) * 15;
camera.position.z = Math.sin( timer ) * 15;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
<div id="pratik"></div>
Now what if I need to include another file named 'mk6.stl', How will I do it?
Does anyone knows how to do it?
I have tried SketchFan, but its not made for me.
Thank you.
You already have the code to load a single STL file and insert it into your scene. The next step to load multiple files is straightforward, you would simply reuse your STLLoader instance. Basically you could do something like:
var loader = new THREE.STLLoader();
loader.load( 'FIRSTFILE.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
loader.load( 'SECONDFILE.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
You could also use the loaders load() method in a loop if you have an array of URLs to load your STL-files from.

Three JS TextGeometry always facing user

This is my source code.
I'm trying to make the TextGeometry always look to the camera?It's possible?
Code:
var stats;
var camera, controls, scene, renderer;
init();
render();
function init() {
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0xFFFFFF );
scene.add( ambient );
var container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({antialias: 1 });
renderer.shadowMap.enabled = true;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight);
renderer.setClearColor(0x013A65);
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5000 );
camera.position.set(0,0,0);
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.enableKeys = false;
controls.enableZoom = true;
controls.minDistance = 2000;
controls.maxDistance = 3500;
controls.maxPolarAngle = Math.PI/2;
// world
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( './assets/3d/' );
mtlLoader.load( 'A.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
mtlLoader.setPath( './assets/3d/' );
objLoader.load( './assets/3d/A.obj', function ( object ) {
object.position.x = 0;
object.position.y = 0;
object.position.z = 0;
scene.add( object );
}, onError );
});
//Text
var loader = new THREE.FontLoader();
loader.load( './fonts/Open_Sans_Regular.json', function ( font ) {
var textGeometry = new THREE.TextGeometry( "Test", {font: font, size: 22, height: 3, curveSegments: 1});var textMaterial = new THREE.MeshPhongMaterial({ color: 0xFFFFFF, specular: 0xFFFFFF });var mesh1 = new THREE.Mesh( textGeometry, textMaterial );mesh1.position.x = -200;mesh1.position.y = 250;mesh1.position.z = 725;scene.add( mesh1);});
// lights
light = new THREE.DirectionalLight( 0xFFFFFF );
light.position.set( 1, 1, 1 );
scene.add( light );
window.addEventListener( 'resize', onWindowResize, true );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
stats.update();
render();
}
function render() {
renderer.render( scene, camera );
}
I already tried mesh.lookAt(camera.position) inside the render function but no sucess.
Best Regards.
I believe your question is how to make the text appear regardless of where the camera is. Instead of using text geometry you can try to put your text in a div container and make the position absolute using CSS. https://threejs.org/docs/#manual/en/introduction/Creating-text

How to enable shading in Three.js

How do you enable shading in Three.js?
Various examples have shown it should be as simple as assigning THREE.FlatShading to your material, but when I do this, my shape has no shading at all.
My JS:
CANVAS_WIDTH = 200,
CANVAS_HEIGHT = 200;
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, CANVAS_WIDTH / CANVAS_HEIGHT, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
material.shading = THREE.FlatShading;
for(var i=0; i<material.length; i++){
material[i].shading = THREE.FlatShading;
}
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// light
//scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 400, 400, 400 );
scene.add( light );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( CANVAS_WIDTH, CANVAS_HEIGHT );
container = document.getElementById( 'accelgyro_canvas' );
container.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() {
console.log('animate')
requestAnimationFrame( animate );
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render( scene, camera );
}
And this renders by cube as:
I've tried adjusting the light angles, adding/removing ambient light, changing which object I add the FlatShading to and nothing seems to help.
How do I fix this?
MeshBasicMaterial does not respond to lights. Use MeshLambertMaterial, MeshPhongMaterial, or MeshStandardMaterial.
Also, MeshLambertMaterial does not have a shading property. If you want FlatShading, you need to use MeshPhongMaterial, or MeshStandardMaterial.
three.js r.75
Are your looking for result like this.
Attaching the reference code for same
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
scene.add(new THREE.HemisphereLight(0xffffff,0xffffff,1.0))
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
for ( var i = 0; i < geometry.faces.length; i++ )
{
geometry.faces[ i ].color.setRGB( 1.0 * Math.random()+0.2 , 0, 0 );
}
var material = new THREE.MeshBasicMaterial( { color:0xff0000,vertexColors: THREE.FaceColors } );
mesh = new THREE.Mesh( geometry, material );
//mesh.drawMode =THREE.TriangleStripDrawMode;
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
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 );
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render( scene, camera );
}

Three.js Make static cube

I'm newbie in Three.js, so, I'm trying just to make STATIC cube. So, I've found a rotating cube example. Here it is:
var camera, scene, renderer;
var mesh;
init();
animate();
//renderer.render( scene, camera );
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var texture = THREE.ImageUtils.loadTexture( '16.jpg' );
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { map: texture } );
var axes = new THREE.AxisHelper( 20 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render( scene, camera );
}
ok, everything work fine. Now I want to make just STATIC cube, I've wrote
var camera, scene, renderer;
var mesh;
init();
renderer.render( scene, camera );
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var texture = THREE.ImageUtils.loadTexture( '16.jpg' );
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { map: texture } );
var axes = new THREE.AxisHelper( 20 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
The output is just a black screen, what have I done wrong?
The texture loading is asynchronous, and you are rendering the scene before it is done.
Add a callback to the Image Loader and render again:
var texture = THREE.ImageUtils.loadTexture('16.jpg', undefined, function () {
renderer.render(scene, camera);
});
Alternatively render continuosly with requestAnimationFrame:
init();
animate();
//...
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
it looks like when you got rid of animate(), you also got rid of the call to
renderer.render( scene, camera );
so you need to put that back in the code somewhere to render your scene

Categories

Resources