im a bit of a noob when it comes to three.js and html but ive created other js files and they would import into the html page just fine but im confused why my basic box copy pasta code isnt showing up on the page. it works fine when scripting it all in html but not when import the js file in the same folder. could yall help me understand whats going on?
index.js
/*import * as THREE from 'three'
const canvas=document.querySelector('.webgl')
const scene = new THREE.Scene();
const geo = new THREE.BoxGeometry(1,1,1)
const mats = new THREE.MeshBasicMaterial({
color:'red'
})
const boxmesh=new THREE.Mesh(geo,mats)
scene.add(boxmesh)
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,100)
camera.position.set(0,1,2)
scene.add(camera)
const renderer=new THREE.WebGL1Renderer({
canvas:canvas
})
renderer.setSize(window.innerWidth,window.innerHeight)
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2))
renderer.shadowMap.enabled=true
renderer.gammaOutput=true
renderer.render(scene, camera)*/
import * as THREE from 'three';
// init
const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
const scene = new THREE.Scene();
scene.background= new THREE.Color('black')
const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
document.body.appendChild( renderer.domElement );
// animation
function animation( time ) {
mesh.rotation.x = .1;
mesh.rotation.y = .1;
renderer.render( scene, camera );
}
animation()
index.html
<!DOCTYPE html>
<html>
<head>
<meta name="learning html" content="This is learing making websites">
<title>Learing GLTF</title>
<script src="index.js"></script>
</head>
<body>
<canvas class="webgl"></canvas>
?
</body>
</html>
When using the latest versions of three.js(e.g. r140), then it's important to define an import map in your HTML. Otherwise the import import * as THREE from 'three'; does not work. A import map is required so the bare module specifier three can be resolved in browsers. For testing, try it with:
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three#0.140/build/three.module.js"
}
}
</script>
Related
I am running a simple threejs scene from VSCode using Live Server to Chrome. This code runs fine, a spinning box appears as expected:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script type="module">
import * as THREE from './build/three.module.js';
// import {GLTFLoader} from './examples/jsm/loaders/GLTFLoader.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add(cube);
// const loader = new GLTFLoader();
// loader.load(
// // resource URL
// '../assets/tree.glb',
// // called when the resource is loaded
// function ( gltf ) {
// scene.add( gltf.scene );
// });
camera.position.z = 5;
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
However, in an attempt to add a 3d model, if I add the line (currently commented out above):
import {GLTFLoader} from './examples/jsm/loaders/GLTFLoader.js';
I then get this error:
Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".
My folder structure looks like this (essentially just three.js cloned from github with an index.html in the root).
Equally, I have the identical problem if I use CDNs like so:
<script type = "module">
import * as THREE from 'https://cdn.skypack.dev/three';
import {GLTFLoader} from 'https://cdn.skypack.dev/three/examples/jsm/loaders/GLTFLoader.js';
etc...
Thanks for the advice.
ive been trying to deploy a threejs project that im working on, on either github pages or firebase, but whenever I deploy them, the browser just shows a whitescreen, its weird because when I run the same project through localhost, everything its working perfectly.
here is my index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Waber App</title>
</head>
<body>
<canvas id="bg"></canvas>
<script type="module" src="/main.js"></script>
</body>
</html>
and here is my main.js
import "./style.css";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#bg"),
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
camera.position.setZ(30);
renderer.render(scene, camera);
const geometry = new THREE.TorusGeometry(10, 3, 16, 100);
const material = new THREE.MeshStandardMaterial({
color: 0xff6347,
});
const torus = new THREE.Mesh(geometry, material);
//scene.add(torus);
const pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(20, 20, 20);
const ambientLight = new THREE.AmbientLight();
scene.add(pointLight, ambientLight);
const lightHelper = new THREE.PointLightHelper(pointLight);
const gridHelper = new THREE.GridHelper(200, 50);
//scene.add(lightHelper, gridHelper);
const controls = new OrbitControls(camera, renderer.domElement);
function addStar() {
const geometry = new THREE.SphereGeometry(0.25, 24, 24);
const material = new THREE.MeshStandardMaterial({ color: 0xffffff });
const star = new THREE.Mesh(geometry, material);
const [x, y, z] = Array(3)
.fill()
.map(() => THREE.MathUtils.randFloatSpread(100));
star.position.set(x, y, z);
scene.add(star);
}
Array(200).fill().forEach(addStar);
const spaceTexture = new THREE.TextureLoader().load("space.jpeg");
scene.background = spaceTexture;
function animate() {
requestAnimationFrame(animate);
moon.rotation.y += 0.005;
torus.rotation.x += 0.01;
torus.rotation.y += 0.005;
torus.rotation.z += 0.01;
controls.update();
renderer.render(scene, camera);
}
const moonTexture = new THREE.TextureLoader().load("moon.jpeg")
const normalTexture = new THREE.TextureLoader().load("normal.jpeg")
const moon = new THREE.Mesh(
new THREE.SphereGeometry(3,32,32),
new THREE.MeshStandardMaterial({
map: moonTexture,
normalMap: normalTexture,
})
)
scene.add(moon)
animate();
LOCALHOST PREVIEW
FIREBASE PREVIEW
I don't know if you've found a solution for your problem yet, but I had the same problem a couple of days ago. I was able to solve it and deploy on Github Pages by putting all my javascript code into my index.html file. I added the link to my CSS file somewhere in the head of the html like you normally would:
<link rel="stylesheet" href="./style.css" />
Then I added the Threejs cdn and all my js code at the bottom of the body. So yours would have to look something like this:
<canvas id="bg"></canvas>
<script type="module">
// Find the latest version by visiting https://unpkg.com/three. The URL will
// redirect to the newest stable release.
import * as THREE from "https://unpkg.com/three/build/three.module.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const scene = new THREE.Scene();
//Followed by all the rest of your code.
</script>
</body>
</html>
This is what worked for me, anyway.
I hope you find this helpful!
Full disclosure, this is my first time answering someone's question on here. If you need anymore info, let me know, and I'll do my best to supply it.
I wanted to load a 3d object to three.js, so since I'm quite new to that, I started from the very first basic example in the documentation and everything seemed to be ok to me. But then when simply added the import line, following the documentation I couldn't see anymore the scene and I got this error from the console:
(index):1 Uncaught TypeError: Failed to resolve module specifier "three/examples/jsm/loaders/GLTFLoader.js". Relative references must start with either "/", "./", or "../"
I've just copied this line from three.js documentation so I'm not really sure about what is wrong in referencing the loader.
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
Can you help me understand what's the issue? I'm working on macOS using atom live server for the previw
Thank you!
I don't know how your project is organized so you will have to replace {path} or even the file name with the actual static path of the file.
<script type="module">
import * as THREE from '{path}/three.module.js'
import { GLTFLoader } from '{path}/GLTFLoader.js'
</script>
If you don't host threejs file just use a CDN
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three/examples/jsm/loaders/GLTFLoader.js'
EDIT
NPM and serving files with any kind of server extension is something you need to understand clearly and is not something that works out of the box. I suggest that you create a single index.html file and run it directly on the browser.
As an example I've replaced every file access with a CDN link.
First run is slow after that the model is in cache.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - glTF loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="https://ghcdn.rawgit.org/mrdoob/three.js/dev/examples/main.css">
</head>
<body>
<div id="info">
three.js - GLTFLoader<br />
Battle Damaged Sci-fi Helmet by
theblueturtle_<br />
Royal Esplanade by HDRI Haven
</div>
<script type="module">
import * as THREE from 'https://cdn.jsdelivr.net/npm/three#0.123.0/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from 'https://cdn.jsdelivr.net/npm/three/examples/jsm/loaders/RGBELoader.js';
import { RoughnessMipmapper } from 'https://cdn.jsdelivr.net/npm/three/examples/jsm/utils/RoughnessMipmapper.js';
let camera, scene, renderer;
init();
render();
function init() {
const container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
camera.position.set( - 1.8, 0.6, 2.7 );
scene = new THREE.Scene();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setPath( 'https://ghcdn.rawgit.org/mrdoob/three.js/dev/examples/textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
render();
// model
// use of RoughnessMipmapper is optional
const roughnessMipmapper = new RoughnessMipmapper( renderer );
const loader = new GLTFLoader().setPath( 'https://ghcdn.rawgit.org/mrdoob/three.js/dev/examples/models/gltf/DamagedHelmet/glTF/' );
loader.load( 'DamagedHelmet.gltf', function ( gltf ) {
gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
// TOFIX RoughnessMipmapper seems to be broken with WebGL 2.0
// roughnessMipmapper.generateMipmaps( child.material );
}
} );
scene.add( gltf.scene );
roughnessMipmapper.dispose();
render();
} );
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 2;
controls.maxDistance = 10;
controls.target.set( 0, 0, - 0.2 );
controls.update();
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
//
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
Created the following mesh in blender:
Whenever I load it into three.js I receive the following result:
I export to .obj format and triangulate all of my faces. Not sure why this is happening. Below is the threejs code I am using to render the mesh. I use the same code with other meshes and they render as expected. I'm guessing I've done something that three.js doesn't like with this mesh?
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="/js/three.js"></script>
<script type="text/javascript" src="/js/DDSLoader.js"></script>
<script type="text/javascript" src="/js/MTLLoader.js"></script>
<script type="text/javascript" src="/js/OBJLoader.js"></script>
<script type="text/javascript" src="/js/OrbitControls.js"></script>
<script type="text/javascript" src="/js/stats.js"></script>
<script type="text/javascript" src="/js/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 130;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(scene.position);
scene.add(camera);
// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
//webGLRenderer.setPixelRatio( window.devicePixelRatio );
webGLRenderer.setClearColor(new THREE.Color(0xffffff, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
var ambient = new THREE.AmbientLight( 0x444444 );
ambient.intensity = 5;
scene.add( ambient );
if('stiletto_switchblade_knife.mtl' !== ''){
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( '/assets/download/mesh/18/' );
mtlLoader.setPath( '/assets/download/mesh/18/' );
mtlLoader.load( 'stiletto_switchblade_knife.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
});
} else {
var objLoader = new THREE.OBJLoader();
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
object.material = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
}
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
var controls = new THREE.OrbitControls(camera, webGLRenderer.domElement );
render();
// simple render
function render() {
stats.update();
controls.update();
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>
EDIT
Are meshes required to be watertight in three.js? If so that could be the problem as there are a couple areas that are not in this mesh. That's the only thing I can think of at the moment that differs between this and the meshes that render properly.
Renders like that turned up with OBJ models in three.js R76. It turned out that any object containing a stray "l" (line) element blew up just like what you have shown. I found the bad objects by searching the ASCII OBJ file on "l ", got rid of the strays by selecting and hiding all of the faces, and dealing with whatever was left.
Solved. Turned out I had left a few faces drawn inside of the mesh. This was causing the unexpected behavior. Interesting debugging method. I just started stripping away vertices and rendering with threejs until I found the section that was causing the issue.
So I am trying to get a JSONLoader to work from threejs.org
Three.js is working for sure because I have no problem creating a cube. But when I try to load a js file throuh JSONLoader then nothing happens.
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="three.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( { alpha: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// instantiate a loader
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
// resource URL
'logo.js',
// Function when resource is loaded
function ( geometry, materials ) {
var material = new THREE.MultiMaterial( materials );
var object = new THREE.Mesh( geometry, material );
scene.add( object );
}
);
camera.position.z = 5;
var render = function () {
renderer.setClearColor( 0x000000, 0 );
requestAnimationFrame( render );
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
As mentioned in the title then the code is copy pasted from threejs own website and should be working.
Can someone help me figure what is going wrong?
here is a fiddle with the script of logo.js https://jsfiddle.net/380z6096/
the object has been exported from 3ds max with the 3ds Max JSExporter
I am using xampp and chrome.
Your camera is inside your geometry.
You can determine the dimensions of your geometry like so
geometry.computeBoundingSphere();
console.log( geometry.boundingSphere );
or
geometry.computeBoundingBox();
console.log( geometry.boundingBox );
Scale your geometry
object.scale.multiplyScalar( 0.01 );
Or move your camera back.
three.js r.75