I am having trouble knowing how the set the camera. What i have tried is using a example and just changing the OBJLoader url to my file
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - OBJLoader + MTLLoader</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;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>
</head>
<body>
<div id="info">
three.js - OBJLoader + MTLLoader
</div>
<script src="../build/three.js"></script>
<script src="js/loaders/DDSLoader.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
render();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = -25;
// scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x444444 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
//directionalLight.position.set( 0, 0, 1 ).normalize();
scene.add( directionalLight );
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load( '140018_2.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.load( '140018_2.obj', function ( object ) {
object.position.set(0, 0, 0);
console.log("loaded");
scene.add( object );
});
});
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableZoom = true;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
It somewhat works. When i load the page i dont see anything. But when i zoom out, the object 'flies in' from the top left corner of my screen. All i really need is just for the object to be centered on the screen.
How are you guys achieving this? The OBJ is not created by me and its settings (height, width etc etc) can vary.
The fact that you say "the object 'flies in' from the top left corner" suggests to me that your .OBJ is not centred, as in, when it was exported from the 3D editor, it was not centred.
It will need to be centred in the 3D authoring program and exported again.
Related
I am learning how to render glb (and gltf) files using three.js,
and I got black screen as result.
Any advice for this? Thanks!
PS: I am using three.min.js and GLTFLoader.js from here:
three.min.js -> https://github.com/mrdoob/three.js/blob/r142/build/three.min.js
GLTFLoader.js -> https://github.com/mrdoob/three.js/blob/r142/examples/js/loaders/GLTFLoader.js
PS2: Avocado glb file is here: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Avocado
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.x = 1;
scene.add( camera );
const canva = document.getElementById("canvas");
const renderer = new THREE.WebGLRenderer({antialias: true, canvas: canva });
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const loader = new THREE.GLTFLoader();
loader.load('Avocado.glb', function (gltf) {
image = gltf.scene;
image.scale.set(2, 2, 2);
image.position.y = 4;
scene.add(image);
}, undefined, function ( error ) {
console.error( error );
} );
camera.position.set(0, 0, 50);
renderer.render(scene, camera);
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
body {
margin: 0;
}
canvas {
width : 100%;
height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Avocado-renderer</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<canvas #canvas id="canvas"></canvas>
<script src = "three.min.js"></script>
<script src="GLTFLoader.js"></script>
<script type="module" src="main.js"></script>
</body>
</html>
I have this object in blender, i want to display it on three js but the result is so different and can't able to change the view, How can i change the view with mouse?
Here's my full code, i'm newbie and this is my first time using three.js and blender:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loaders - ColladaLoader2</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{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="WebGL-output">
</div>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="colladaloader.js"></script>
<script>
function init() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
var axes = new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0
scene.add(plane);
document.body.appendChild(renderer.domElement);
camera.position.set(0, 0, 4);
var loader = new THREE.ColladaLoader();
loader.load("MAC12.dae", function (result) {
scene.add(result.scene);
});
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
};
window.onload = init;
</script>
</body>
</html>
I'm learning how to integrate Three.js to Polymer's Lit-Element. My current problem is that I need refer to a div element to append Three's Renderer element. Here's how it is done usually:
box = document.getElementById("box")
box.appendChild(renderer.domElement)
Unfortunately, I am not able find how to refer from the constructor()/firstUpdate() to the div declared in the render function. How would you do that?
Here's my best result for now:
Renderer element off target
Here's the code to get this result:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<box-test></box-test>
<script type="module" src="src/components/box-test.js" crossorigin></script>
</body>
</html>
Javascript:
import { LitElement, html } from '#polymer/lit-element';
import * as THREE from 'three/build/three.module';
class BoxTest extends LitElement {
constructor() {
super();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(300, 300);
//box = document.getElementById("box");
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
var animate = function () {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
animate();
}
render() {
return html`
<style>
#box { border: 1px solid red; height: 310px; width: 310px;}
</style>
<section>
The webgl animation must be in the red box
<div id="box">
</div>
</section>
`
}
}
window.customElements.define('box-test', BoxTest);
Any suggestion will be welcomed.
In your constructor function you can keep variables to use in other functions later by set it to this
this.renderer = renderer
Then in firstUpdated function you can do
firstUpdated () {
let box = this.shadowRoot.getElementById('box')
box.appendChild(this.renderer.domElement)
}
Example Code:
<script type='module'>
import { LitElement, html } from '#polymer/lit-element'
import * as THREE from 'three/build/three.module'
class BoxTest extends LitElement {
constructor () {
super()
var scene = new THREE.Scene()
var camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
var geometry = new THREE.BoxGeometry(1, 1, 1)
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true })
var cube = new THREE.Mesh(geometry, material)
scene.add(cube)
camera.position.z = 5
;(function animate () {
requestAnimationFrame(animate)
cube.rotation.x += 0.01
cube.rotation.y += 0.01
renderer.render(scene, camera)
}())
var renderer = new THREE.WebGLRenderer()
renderer.setSize(300, 300)
this.renderer = renderer
}
firstUpdated () {
let box = this.shadowRoot.getElementById('box')
box.appendChild(this.renderer.domElement)
}
render () {
return html`
<style>
#box { border: 1px solid red; height: 310px; width: 310px;}
</style>
<section>
The webgl animation must be in the red box
<div id="box"></div>
</section>
`
}
}
window.customElements.define('box-test', BoxTest)
</script>
I am just trying to follow examples and get myself putting my own models into a scene. However, when using the FBXLoader, I'm not sure what if what I'm doing is right. I can only get one FBX to load at a time. I'm not a coder first, so sorry if my code looks sloppy:
I have an object called range_burners.fbx. It loads in fine by itself. I have a model called range_main.fbx that works just fine by itself. But both of them together, well the range_main.fbx always seems to take precedent.
<!DOCTYPE html>
<!-- saved from url=(0022)http://127.0.0.1:1024/ -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>three.js webgl - FBX loader</title>
<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: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a {
color: #046;
font-weight: bold;
}
</style>
</head>
<body>
<div id="info">
three.js - FBXLoader<br>
Character and animation from Mixamo
</div>
<script src="./index_files/three.js.download"></script>
<script src="./index_files/inflate.min.js.download"></script>
<script src="./index_files/FBXLoader.js.download"></script>
<script src="./index_files/OrbitControls.js.download"></script>
<script src="./index_files/Detector.js.download"></script>
<script src="./index_files/stats.min.js.download"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats, controls;
var camera, scene, renderer, light;
var clock = new THREE.Clock();
var mixers = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 100, 200, 300 );
controls = new THREE.OrbitControls( camera );
controls.target.set( 0, 100, 0 );
controls.update();
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = -100;
light.shadow.camera.left = -120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera ) );
// ground
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
var burners = new THREE.FBXLoader();
burners.load( '/fbx/range_burners.fbx', function ( object ) {
object.traverse( function ( child ) {
if( child.material ) {
child.material = new THREE.MeshStandardMaterial ( {
color: 0x151515,
metalness: 0.8,
roughness: 0.6
} );
}
} )
object.position.set(0, 200, 0);
scene.add ( object );
} );
// model
var range = new THREE.FBXLoader();
range.load( '/fbx/range_main.fbx', function ( object2 ) {
object2.traverse( function ( child2 ) {
if( child2.material ) {
child2.material = new THREE.MeshStandardMaterial ( {
color: 0xffffff,
metalness: 0.8,
roughness: 0.4
} );
}
} )
object2.position.set(-150, 0, 0);
scene.add ( object2 );
} );
//burners
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// stats
stats = new Stats();
container.appendChild( stats.dom );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
if ( mixers.length > 0 ) {
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() );
}
}
renderer.render( scene, camera );
stats.update();
}
</script><div><canvas width="1920" height="898" style="width: 1920px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div><div><canvas width="928" height="898" style="width: 928px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div>
</body></html>
Your code looks pretty good. It's not obvious to me why one would override the other, unless perhaps its hidden behind the other one?
Might try moving their initial positions?
Also, you probably want to do your THREE.WebGLRenderer initialization before you fire off the loaders.. i.e. put your loaders at the end of the init...
Another way to debug is to set 'wireframe:true" on your materials, so you can see of one of them is hiding inside the other...
I'm having a hard time trying to get a cylinder aligned to a particular vector. I've seen and tried a number of possible solutions, but to no avail. My understanding is that all I should need to do is to position the cylinder at the center of the vector and use LookAt() to align it. Below I've attached a simple example of this where I add a line, then am attempting to align the cylinder to this line. Would anyone be able to tell me what I'm doing wrong? TIA
Roy
<!DOCTYPE html>
<html lang="en">
<head>
<title></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;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display: block;
}
a {
color: skyblue;
}
.button {
background: #999;
color: #eee;
padding: 0.2em 0.5em;
cursor: pointer;
}
.highlight {
background: orange;
color: #fff;
}
span {
display: inline-block;
width: 60px;
float: left;
text-align: center;
}
.left-panel{
position: absolute;
top:0px;
left: 0px;
height:100%;
width:220px;
background-color:white;
}
.right-panel{
position: absolute;
top:0px;
right: 0px;
height:100%;
width:220px;
background-color:white;
}
</style>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/threejs/r76/three.min.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, raycaster, renderer, model, cylinder;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var reader;
init();
function init() {
scene = new THREE.Scene();
scene.add(new THREE.AmbientLight(0x999999));
addLine();
addCylinder();
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );
// Z is up for objects intended to be 3D printed.
camera.up.set(0, 0, 1);
camera.position.set(8, -72, 20);
camera.rotateOnAxis('X', 25);
camera.rotateOnAxis('Z', 0.0025);
camera.add(new THREE.PointLight(0xffffff, 0.8));
scene.add(camera);
var grid = new THREE.GridHelper(200, 100, 0x229922, 0x222222);//grid
grid.rotateOnAxis(new THREE.Vector3(1, 0, 0), 90 * (Math.PI / 180));
grid.receiveShadow = true;
scene.add(grid);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0x333399 );// scene background color
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(renderer.domElement);
raycaster = new THREE.Raycaster();
raycaster.linePrecision = .05;
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.target.set( 0, 1.2, 2 );
controls.update();
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
render();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function render() {
raycaster.setFromCamera(mouse, camera);
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects(scene.children);
renderer.render( scene, camera );
}
function addCylinder() {
//Mesh to align
var material = new THREE.MeshLambertMaterial({ color: 0x666666 });
cylinder = new THREE.Mesh(new THREE.CylinderGeometry(.2, .2, 7.5,8), material);
var vector = new THREE.Vector3(10, 0, 10);
cylinder.position.set(5, 0, 5);
//create a point to lookAt
var focalPoint = new THREE.Vector3(
cylinder.position.x + vector.x,
cylinder.position.y + vector.y,
cylinder.position.z + vector.z
);
//all that remains is setting the up vector (if needed) and use lookAt
//cylinder.up = new THREE.Vector3(0, 0, 1);//Z axis up
cylinder.lookAt(focalPoint);
scene.add(cylinder);
}
function addLine() {
var material = material = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 1, fog: false });
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3(0,0,0),
new THREE.Vector3(10,0,10)
);
var line = new THREE.Line(geometry, material);
line.castShadow = true;
scene.add(line);
}
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
render();
}
</script>
</body>
</html>
All you need to do is rotate the cylinder so it aligns with the z-axis instead of the y-axis.
cylinder = new THREE.Mesh( new THREE.CylinderGeometry( .2, .2, 7.5, 8 ), material );
cylinder.geometry.rotateX( Math.PI / 2 );
cylinder.geometry.translate( 0, 0, - 7.5 / 2 ); // optional
When you call object.lookAt( target ), the oject's local positive z-axis is oriented toward the target.
three.js r.82