I need to work on project that uses three.js. So I have tried to learn the basic and O wrote this simple code just to see something. But it doesn't work at all and when I click to view it on web browser nothing is shown.
This is my code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script src="Three.js"></script>
</head>
<body>
<script type="text/javascript">4
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(document.body.clientWidth,
document.body.clientHeight);
document.body.appendChild(renderer.domElement);
renderer.setClearColorHex(0xEEEEEE, 1.0);
renderer.clear();
// new THREE.PerspectiveCamera( FOV, viewAspectRatio, zNear, zFar );
var camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
camera.position.z = 300;
var scene = new THREE.Scene();
var cube = new THREE.Mesh(new THREE.CubeGeometry(50, 50, 50),
new THREE.MeshBasicMaterial({ color: 0x000000 }));
scene.add(cube);
renderer.render(scene, camera);
</script>
</body>
</html>
Why doesn't it work? What did I do wrong ?
Good day, could you tell us what version of Three.js your using (it shows up in the console once it loads if your not sure), and what browser your using?
A few notes, renderer.setClearColorHex is deprecated now, this should be just renderer.setClearColor.
Also you set the Camera with width / height but I dont see them defined anywhere?
Next is the camera.position.z = 300; may be too far away to see a little cube at (0, 0, 0)
Try those items and let us know if it works.
Just see this example.
http://mrdoob.github.io/three.js/examples/#webgl_geometry_cube
You are missing a main loop for cosecutive frame rendering. Also as Darryl said, what is width and height?
Related
I hope that there are some experienced people on this platform who'd be willing to help me with my three.js problem.
My current problem is this, I can't seem to properly run the three.js library on my localhost, all I get is a white screen.
My files:
My Javascript code:
import * as THREE from 'three.js-master/three.js';
import { OrbitControls } from "three.js-master/examples/OrbitControls.js";
const scene = new THREE.Scene(); //generate scene
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); //generate camera
const renderer = new THREE.WebGLRenderer(); //launch renderer using WebGl
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
const controls = new OrbitControls( camera, renderer.domElement );
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.05;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
And my HTML code:
<!DOCTYPE html>
<html>
<head>
<title>EMBÄR</title>
<link src="style.css" type="stylesheet">
</head>
<body>
<script src = "three.js" type="module"></script>
<script src="Main.js" type="module"> </script>
</body>
</html>
Now, this just gives a white screen all the time, but I've managed to use the link:
https://unpkg.com/three/build/three.module.js (instead of three.js-master/three.js) in combination with:
https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/controls/OrbitControls.js (instead of three.js-master/examples/OrbitControls.js)
to successfully run the script, but this really isn't a solution, since I had to search for days to find these links, and it surely isn't efficient if I want to include more modules besides these.
It'd be awesome if someone knew the answer, but please, don't feel pressured to do a lot of research.
Your HTML should look like so:
<!DOCTYPE html>
<html>
<head>
<title>EMBÄR</title>
<link src="style.css" type="stylesheet">
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims#1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "./three.js-master/build/three.module.js",
"three/addons/": "./three.js-master/examples/jsm/"
}
}
</script>
<script src="Main.js" type="module"> </script>
</head>
<body>
</body>
</html>
In your Main.js file, use the following imports:
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
The imports in your JS should look exactly like the ones from the official examples. The only thing that differs is the import map. In your case, you refer to your locally hosted version of the three.js repo. Keep in mind to always use the module.js version of three.js. Not the UMD build.
You find more information about the setup/installation of three.js in this guide.
I am trying to add a 3D object to the scene.
Uncaught TypeError: Class constructor ol cannot be invoked without 'new' at new GLTFLoader
Major line error let loader = new THREE.GLTFLoader();
But I can't figure out what to put in brackets? New? .., or what?
Constructor:
https://threejs.org/docs/#examples/en/loaders/GLTFLoader
Model 2(Mb): https://drive.google.com/file/d/1bPnC5coazNFIcsyvV9U29BFiFhXhriYg/view?usp=sharing
Source:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/GLTFLoader.js"></script>
<script>
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 10; // Отдаление камеры
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 0);
renderer.setSize(1280 , 720);
renderer.domElement.setAttribute("id", "Church3DObj");
document.body.insertBefore(renderer.domElement, document.body.firstChild);
const aLight = new THREE.AmbientLight(0x404040, 1.2);
scene.add(aLight);
let loader = new THREE.GLTFLoader();
let obj = null;
loader.load('/3d/Church.gltf', function(gltf) {
obj = gltf;
obj.scene.scale.set(1.3, 1.3, 1.3);
scene.add(obj.scene);
});
</script>
</body>
</html>
It is telling you that you cannot invoked GLTFLoader without 'new' at new GLTFLoader
If you look at the doc you linked in the code exemple they use
const loader = new GLTFLoader(); before doing anything with it.
You must instance GLTFLoader.
To avoid this error, we must download from GitHub файлы .js:
three.js, GLTFLoader.js, OrbitControls.js, three.module.js
<script src="scripts/three.js"></script>
<script type="module"> src="scripts/GLTFLoader.js"></script>
<script type="module"> src="scripts/OrbitControls.js"></script>// IF THERE IS A CAMERA CONTROL IN SPACE
Place them in the root of the project and open GLTFLoader.js. At the time of 05/24/2021 we find 64 lines
from './smthPath/smthPath/smthPath/three.module.js';
and remove the excess. (that is, we specify the path to the three.module.js file). In my case:
from './three.module.js';
(If there is a camera control, then we do the same with the OrbitControls.js file, line 9)
from './three.module.js';
Further it is IMPORTANT in the script, in which all the brains add type = "module", and import the files - that is, it turns out
<script type="module">
import {GLTFLoader} from "./scripts/GLTFLoader.js";
import {OrbitControls} from './scripts/OrbitControls.js';
//...
</script>
IMPORTANT
*For people who have not worked with 3D on the web, but model in Cinema4D, 3Ds Max, ZBrush ... (like me). You need not only a .gltf file but also a .bin file
How do I get them?
Go to the site [Scetchfab] (https://sketchfab.com/feed).
Load the model (set the settings for free download (then
you can delete the model)).
We are waiting for it to be processed.
4.download the required format (glFT)
Remove the model from Scetchfab *
IMPORTANT
***The final view of the html file ***
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dragon</title>
</head>
<body id="c" style="margin: 0;">
<!--3D-->
<script src="scripts/three.js"></script>
<script type="module" src="scripts/GLTFLoader.js"></script>
<script type="module" src="scripts/OrbitControls.js"></script>
<script type="module">
import {GLTFLoader} from "./scripts/GLTFLoader.js";
import {OrbitControls} from './scripts/OrbitControls.js';
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x555555);
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 5, 15);
const renderer = new THREE.WebGLRenderer({alpha: true, antialias: true});
renderer.setClearColor(0x000000, 0);
renderer.setSize(1920 , 1080);
document.body.appendChild(renderer.domElement);
const aLight = new THREE.AmbientLight(0x404040, 15);
aLight.position.set(0,10,10)
scene.add(aLight);
const pLight = new THREE.PointLight(0xFFFFFF, 15);
pLight.position.set(0,5,0)
scene.add(pLight);
const phelper = new THREE.PointLightHelper(pLight);
scene.add(phelper);
const loader = new GLTFLoader();
let obj = null;
loader.load("3d/Dragon/scene.gltf", function(gltf) {
obj = gltf.scene;
scene.add(gltf.scene);
});
const canvas = document.getElementById("c");
const controls = new OrbitControls(camera, canvas);
controls.target.set(0, 1, 0);
controls.update();
function animate(){
requestAnimationFrame(animate)
obj.rotation.y += 0.005;
renderer.render(scene, camera)
}
animate();
</script>
</body>
</html>
So I'm trying to load a GLTF file and I am receiving this error:
I don't know why it can't locate and open the file. Do I have to set up a local server?
I looked up other examples online and this one includes a DRACOLoader. Admittedly, I don't know what this is for and was wondering if I need to implement this in order for it to load.
Here is my code:
<html>
<head>
<meta charset="utf-8">
<title>Website first attempt</title>
<style>
body { margin: 0;
background: linear-gradient(to bottom, #33ccff 0%, #ffffff 20%);}
canvas { display: block; }
</style>
</head>
<body>
<!-- <script type = "module" src="build/myScript.js"></script>-->
<script type = "module">
import * as THREE from '../build/three.module.js';
import { GLTFLoader } from '../build/GLTFLoader.js';
let scene, camera, renderer, hlight;
function init () {
//scene
scene = new THREE.Scene();
//camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth/ window.innerHeight, 1, 5000);
//light
hlight = new THREE.AmbientLight (0x404040, 100);
scene.add(hlight);
//render
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setClearColor( 0x000000, 0 );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//3d
let loader = new GLTFLoader();
loader.load('assets/londonmap.gltf', function(gltf){
scene.add(gltf.scene);
})
}
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);
render();
}
function render() {
renderer.render( scene, camera );
}
init ();
animate();
</script>
</body>
</html>
DracoLoader is only necessary if the glTF asset was compressed with the same-named compression algorithm.
A HTTP 404 means that it was not possible to load the file (in your case assets/londonmap.gltf) from the given path. So you have to make sure that the asset is actually present in the respective directory.
And yes, it's highly recommended to work with a local web server. Especially to avoid any security related browser issues. The project actually provides a small guide about this topic: How to run things locally.
I might have discovered a Chrome Bug related to three.js/WebGL.
I have set up a simple project demonstrating the issue here. It simply initialises a fullscreen three.js canvas, resizes the renderer on resize events and prints window.innerWidth/Height to the console. (The code was created by one of the three.js contributors and should be the standard way of implementing auto-resizing. Related three.js issue)
Code
<!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 style="margin: 0;">
<script src="three.js"></script>
<script>
var scene, camera, renderer, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
var geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
var material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', resize );
console.log( 'width: ' + window.innerWidth, 'height: ' + window.innerHeight );
}
function resize() {
console.log( 'width: ' + window.innerWidth, 'height: ' + window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
</script>
</body>
</html>
How to reproduce the issue
>>> Link to repository
Open test.html in Chrome
Fire up Devtools
Toggle Device Toolbar
Select a device (for this example Nexus 6P)
Switch from landscape to portrait mode and observe console output
My console output:
width: 412 height: 732 # portrait mode
width: 732 height: 412 # landscape mode
width: 732 height: 1301 # portrait mode
width: 732 height: 412 # landscape mode
The first time I switch from landscape to portrait mode the values of window.innerHeight/Width aren't correct anymore. It should be 412x732 instead of 732x1301.
Excluding the line renderer.setSize(window.innerWidth, window.innerHeight) solves the problem.
Related Devices
I was able to reproduce this bug on 2 different MacBooks (2016, 2013) [Chrome v. 63.0.3239.108] and on my Android Phone (Redmi 4X, Android 7.1.2) [Chrome v. 63.0.3239.111]
It'd be nice if somebody could confirm this behaviour.
Ran into the same error today. I tried using document.documentElement.client[Width or Height] and it gave me the right dimensions. I didn't implement my solution yet, but something that could be good would be to check if the last time you checked your dimensions it looked like the dimensions from innerWidth like :
if(lastDims.height !== nowDims.width) { /*Or something similar, you get the idea*/
//The dimensions are ok assuming lastDims was ok too
}
// or
const width = Math.min(document.documentElement.clientWidth, window.innerWidth);
const height = Math.min(document.documentElement.clientHeight, window.innerHeight);
Also, I'm using fabric.js (canvas) and screenfull.js (fullscreen API), not three.js. I am using Chrome though.
(As I was writing this, I installed Firefox) I just tested my app and it works fine in Firefox, so that might be a problem in Chrome itself when handling the window.inner[stuff] after the fullscreen API has done its thing... I might be wrong but, hey, I got the right dimension in the end!
Edit: Soooo thought about it, you might already found your solution since it's 2018 now...
I swear, last edit: This is a Chrome(Chromium) bug: https://bugs.chromium.org/p/chromium/issues/detail?id=833440&can=2&start=0&num=100&q=window.innerWidth&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified&groupby=&sort=
I'm doing some prototyping, and I'm displaying some data in 3D using three.js (version 68). Desired result of whole animation would be a bunch of colored balls (that represent protons and neutrons that are colored according to some schema). Everything works good, but for reasons unknown to me rendered results are pixcelated.
Current version basically looks like that (this image is ~400px wide):
I have checked all obvious things like: passing incorrect resolution, browser scaling and so forth.
You can see this issue on this fiddle, and download the webpage here.
And also here are revelant parts of code:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script src="js/jquery.js"></script>
<script src="js/coffee-script.js"></script>
<script src="js/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/animtest/load_event.js"></script>
<style>canvas { width: 100%; height: 100% }</style>
<title></title>
</head>
<body>
<div id="animation"
style="width: 1024px; height: 768px; ">
</div>
<script>
$(function(){
ctrl = new AnimController("#animation");
ctrl.set_up_scene();
ctrl.render();
ctrl.display_frame(4);
});
</script>
</body>
</html>
Here is the coffeescript code that loads the animation:
class AnimController
...
set_up_scene: () ->
#scene = new THREE.Scene()
el = $(#element_name)
#camera = new THREE.PerspectiveCamera(45
el.width()/el.height(),
1, 20000
)
#camera.position.set(100, 100, 0)
#scene.add new THREE.AmbientLight 0x111111
#renderer = new THREE.WebGLRenderer()
el.html(#renderer.domElement)
controls = new THREE.OrbitControls(#camera, #renderer.domElement );
controls.addEventListener 'change', () =>
console.log("Change")
#render()
render: () ->
requestAnimationFrame(() => #render)
console.log "Render"
if #update_scene
material = new THREE.MeshBasicMaterial() #"color": 0xffff00,
geometry = new THREE.SphereGeometry 5, 50, 50
console.log "Update"
#update_scene = false
#scene = new THREE.Scene()
for particle in #curr_event
p = particle['position']
sphere = new THREE.Mesh( geometry, material );
sphere.position.set(p[0], p[1], p[2])
#scene.add(sphere)
#renderer.render(#scene, #camera)
It seems that you have not requested antialiasing on the renderer you are using. I don't know coffeescript but in javascript you would do:
renderer = new THREE.WebGLRenderer({ antialias: true });
Antialiasing also was a factor (see #gaitat answer) but I also forgot to set resoluion the renderer:
renderer.setSize( 1024, 768 )