GLTF Loader not working and doesn't load 3D model - javascript

I'm trying to upload a 3D model to my scene in three.js however I have trouble doing this.
I decided to recreate an example to practice which is shown below but I still get error and it doesn't work.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Website first attempt</title>
<script src="js/three.min.js"></script>
<script type = "module"src="js/OrbitControls.js"></script>
<script type = "module" src="js/GLTFLoader.js"></script>
<style>
body { margin: 0;}
canvas { display: block; }
</style>
</head>
<body>
<div class = "wave"></div>
<script type = "module">
var scene, camera, renderer, controls;
var hlight,directionalLight, light, light2, light3, light4;
function init () {
//scene
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xdddddd );
//camera
camera = new THREE.PerspectiveCamera(40,window.innerWidth/window.innerHeight,1,5000);
camera.rotation.y = 45/180*Math.PI;
camera.position.x = 800;
camera.position.y = 100;
camera.position.z = 1000;
//render
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
hlight = new THREE.AmbientLight (0x404040,100);
scene.add(hlight);
directionalLight = new THREE.DirectionalLight(0xffffff,100);
directionalLight.position.set(0,1,0);
directionalLight.castShadow = true;
scene.add(directionalLight);
light = new THREE.PointLight(0xc4c4c4,10);
light.position.set(0,300,500);
scene.add(light);
light2 = new THREE.PointLight(0xc4c4c4,10);
light2.position.set(500,100,0);
scene.add(light2);
light3 = new THREE.PointLight(0xc4c4c4,10);
light3.position.set(0,100,-500);
scene.add(light3);
light4 = new THREE.PointLight(0xc4c4c4,10);
light4.position.set(-500,300,500);
scene.add(light4);
var loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function(gltf){
car = gltf.scene.children[0];
car.scale.set(0.5,0.5,0.5);
scene.add(gltf.scene);
animate();
});
}
function onWindowResize () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', onWindowResize, false);
function animate () {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render( scene, camera );
}
init ();
animate();
</script>
</body>
</html>
Comes with an error:
GET http://127.0.0.1:5500/build/three.module.js net::ERR_ABORTED 404
(Not Found) index4.html:78 Uncaught TypeError: THREE.GLTFLoader is not
a constructor
at init (index4.html:78)
at index4.html:122

I think easier to stick to the example's code style and organize your imports like so:
<script type = "module">
import * as THREE from '../build/three.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
var scene, camera, renderer, controls;
Meaning three.module.js, OrbitControls and GLTFLoader are ES6 modules. In this case, you can create an instance of GLTFLoader without the THREE namespace. Same for OrbitControls.
Notice that it's no good approach to mix ES6 modules with non-ES6 modules. If you do so, you will be inevitably faced with issues which are really hard to track down. E.g. libraries like three.js get included twice.

Related

How do I get three.js to show up in browser?

whenever I try to open and see my progress with three.js on my browser locally, it will not load and throws me this error,
Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".
I'm new to three.js and been stuck for a while and haven't even really gotten started. I appreciate the help. If my first lines of the javascript file is: import * as THREE from '/Users/16103/Desktop/three'. Thank you!
Try using a demo with a cdn like this simple one taken from their samples. You can download the script from cdn locally.
var camera, scene, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 500;
scene.add(camera);
geometry = new THREE.CubeGeometry(200, 200, 200);
material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/three.js/r54/three.js"></script>
<canvas style="margin-top:-200px"></canvas>

Cannot display 3D model in threejs

I am trying to display a model which is gltf but it doesn't come up. I'm running of a http server as without so it is causing more errors now this "Error: Could not establish connection. Receiving end does not exist." comes up
<html><head>
<title>My first three.js app</title>
<style>
body {
margin: 0;
}
canvas {
display: block;
}
</style></head>[enter image description here][1]<body>
<script src="js/three.js"></script>
<script src="js/GLTFLoader.js"></script>
<script> 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);
var loader = new THREE.GLTFLoader();
loader.load("LegoEv3.glb", handle_load);
var mesh;
function handle_load(gltf) {
mesh = gltf.scene.children[0];
scene.add(mesh);
mesh.position, (z = -1000);
}
renderer.render(scene, camera);
</script>
you render only once before the model is loaded.
Try rendering again after the model is loaded and added to the scene
function handle_load(gltf) {
mesh = gltf.scene.children[0];
scene.add(mesh);
mesh.position, (z = -1000);
renderer.render(scene, camera); // You need to render after model is added
}

Firefox error during three.js execution code

I try to do a 3D animation with Three.js controls. During the execution of my code in Firefox, a have this error :
EDIT
SyntaxError: import declarations may only appear at top level of a module
And here is my code, simplified :
<!DOCTYPE html>
<head>
<title>Three.js Test</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100%;};
</style>
</head>
<body>
<script src="js/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script type="module">
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);
//keep the scene in center of the page
window.addEventListener('resize', function() {
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width,height);
//prevent distortion
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
controls = new THREE.OrbitControls(camera, renderer.domElement);
// create the shape
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0xFF0080 } );
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;
cube.rotation.z += 0.01;*/
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
I don't understand where the error came from and I don't know how to fix it.
I now run my code on a wamp server.
Thanks for your help !
import * as THREE from './jsthree.module.js';
It seems there is a typo. It should be ./js/three.module.js.
In any event, ensure to run your code on a local web server in order to avoid any security issues. More information about this topic in the following guide:
https://threejs.org/docs/index.html#manual/en/introduction/How-to-run-things-locally

Three.js ply colorless (all black)

I am trying to load my ply file using Three.js. It has worked but I almost don't see any colors. There are some glimpses here and there, but it's mostly black (the first image below). The image opens properly (with colors) in MeshLab (the second image below). I have tried vertexColors: THREE.VertexColors (as suggested in Three.js - ply files - why colorless?) and vertexColors: THREE.FaceColors but nothing seemed to help. I am a three.js newbie, so please tell me what am I doing wrong.
and my code:
<!doctype html>
<html lang="en">
<head>
<title>Icon 7</title>
<meta charset="utf-8">
</head>
<body style="margin: 0;">
<script src="js/three.min.js"></script>
<script src="js/PLYLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script>
// Set up the scene, camera, and renderer as global variables.
var scene, camera, renderer;
init();
animate();
// Sets up the scene.
function init() {
// Create the scene and set the scene size.
scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
// Create a renderer and add it to the DOM.
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
// Create a camera, zoom it out from the model a bit, and add it to the scene.
camera = new THREE.PerspectiveCamera(35, WIDTH / HEIGHT, 0.1, 100);
camera.position.set(0,0.15,3);
camera.lookAt(new THREE.Vector3(0,0,0));
scene.add(camera);
// Create an event listener that resizes the renderer with the browser window.
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
// Set the background color of the scene.
renderer.setClearColor(0xd3d3d3, 1);
// Create a light, set its position, and add it to the scene.
var light = new THREE.PointLight(0xffffff);
light.position.set(0,200,100);
scene.add(light);
// Load in the mesh and add it to the scene.
var loader = new THREE.PLYLoader();
loader.load( './models/foot.ply', function ( geometry ) {
geometry.computeVertexNormals();
geometry.center();
var material = new THREE.MeshStandardMaterial ({ shininess: 1000,vertexColors: THREE.FaceColors } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
mesh.castShadow = false;
mesh.receiveShadow = false;
scene.add( mesh );
} );
// Add OrbitControls so that we can pan around with the mouse.
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.userPanSpeed = 0.05;
}
// Renders the scene and updates the render as needed.
function animate() {
// Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimationFrame(animate);
// Render the scene.
renderer.render(scene, camera);
controls.update();
}
</script>
</body>
</html>
Edit: as I don't have separate textures, this is not a duplicate question.
Instead of using MeshStandardMaterial use MeshBasicMaterial

Basic Collada Loading in Three.js

I am attempting to load a collada file using three.js and the collada loader. I am leveraging the three.js documentation, but can't seem to get the file to render on screen. What I want to achieve is a very basic import of the collada file into a scene, no animation required. The errors I am receiving are as follows:
unhandled Surface prop: format_hint
Can not convert Transform of type lookat
The XHR output is showing 100% load of the .dae file, and I can browse to the location of the stored file in a browser and view it as XML. I currently have the mime type set to application/xml in IIS.
Here is my current code. What am I missing?:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loaders - collada loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src="scripts/three.min.js"></script>
<script src="scripts/ColladaLoader.js"></script>
<script src="scripts/jquery-2.1.4.min.js"></script>
<script src="scripts/bootstrap.min.js"></script>
<link href="css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<h1>Box Example</h1>
<p>This example loads an collada file</p>
<div id="webGL-container"></div>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xff0000);
renderer.setSize(window.innerWidth, window.innerHeight);
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
// instantiate a loader
var loader = new THREE.ColladaLoader();
loader.load(
// resource URL
'models/box.dae',
// Function when resource is loaded
function (collada) {
scene.add(collada.scene);
},
// Function called when download progresses
function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}
);
camera.lookAt(scene.position);
renderer.render(scene, camera);
$("#webGL-container").append(renderer.domElement);
</script>
</body>
</html>
Per the advice offered, here is version 2:
var scene;;
var camera;
var renderer;
var loader;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor();
renderer.setSize(window.innerWidth, window.innerHeight);
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
// instantiate a loader
loader = new THREE.ColladaLoader();
loader.load(
// resource URL
'models/box.dae',
// Function when resource is loaded
function (collada) {
scene.add(collada.scene);
},
// Function called when download progresses
function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}
);
camera.lookAt(scene.position);
$("#webGL-container").append(renderer.domElement);
};
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
init();
animate();
Update 3: I have been able to get the core .DAE file to render, but it is missing the texture (currently showing the box as all black):
var scene;
var camera;
var renderer;
var box;
// instantiate a loader
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('models//box.dae', function (collada) {
box = collada.scene;
box.traverse(function (child) {
if (child instanceof THREE.SkinnedMesh) {
var animation = new THREE.Animation(child, child.geometry.animation);
animation.play();
}
});
box.scale.x = box.scale.y = box.scale.z = .2;
box.updateMatrix();
init();
animate();
});
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xdddddd);
renderer.setSize(window.innerWidth, window.innerHeight);
scene.add(box);
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
$("#webGL-container").append(renderer.domElement);
}
You are hitting the asynchronous loading of javascript. When you call renderer.render() your scene is still empty because the model has not downloaded yet. Put the code you have in an init() function and then create an animate() function and call them as such:
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
init();
animate();
The variables scene, camera, renderer you should make global.

Categories

Resources