About the control of threejs - three.js

I am practicing threejs while watching the tutorial.
However, one problem occurred.
Mouse control code is not working. Only black screen.
I checked, but it's exactly the same code as the tutorial.
But mine doesn't work.
I am the latest version of Chrome and I got the latest file from OrbitControls.js from GitHub.
I think the only difference from the tutorial is the OrbitControls.js file.
What should I do?
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
window.addEventListener('load', init);
function init() {
const width = 960;
const height = 540;
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#myCanvas')
});
renderer.setSize(width, height);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, width / height);
camera.position.set(0, 0, 1000);
const controls = new THREE.OrbitControls(camera);
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(300, 300, 300),
new THREE.MeshNormalMaterial()
);
scene.add(mesh);
tick();
function tick() {
renderer.render(scene, camera);
requestAnimationFrame(tick);
}
}
</script>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>

One common root cause for such importing issues is the usage of three.js components from different releases. You can easily verify this by importing your code like so:
<script src="https://cdn.jsdelivr.net/npm/three#0.110/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.110/examples/js/controls/OrbitControls.js"></script>
Another possible problem is the way you create OrbitControls. In recent versions of three.js, the second parameter is mandatory. Meaning the code should look like so:
const controls = new THREE.OrbitControls(camera, renderer.domElement);

Related

I'm trying to loading a gltf 3d model into the page but all i'm getting is a white page what am i doing wrong here?

This is the code i tried but so far it's not working it only shows a white page when i run it !
i've tried changing the path and running it over and over i also tried import maps and it didn't work.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Three.js Model Loader</title>
<body>
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/three#0.120.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#3.0.0/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-vis#0.4.0/dist/tfjs-vis.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.120.0/examples/js/loaders/GLTFLoader.js"></script>
<script>
// Create a scene
const scene = new THREE.Scene();
// Create a camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 25;
// Create a renderer
const renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// Attach the renderer to the container
document.getElementById("container").appendChild(renderer.domElement);
// Load the GLTF model
const loader = new THREE.GLTFLoader();
loader.load('./module/girl/scene.gltf', function(gltf) {
scene.add(gltf.scene);
render();
});
// Render the scene
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
</script>
</body>
</html>

Difficulty incorporating pointer lock controls API in three.js using es6 classes that are not modules

As the title states, I am using es6 classes, but because they are all not modules apart from the main.js file, it makes it difficult to use API's because I cannot make use of import modules.
I used the code from this link's answer: How to add in Three.js PointerLockControl? and pasted the code into a js file, calling it up in my HTML, but I get an error stating:
Uncaught ReferenceError: PointerLockControls is not defined
It is not picking up the class when I reference it. I tried to link it to the GitHub raw code, and it didn't pick it up either.
This is my index.html code (only one line referencing the GitHub raw code):
<!-- This html file is what the browser shows when we run index.js on port 5000. Therefore our display of our game-->
<!DOCTYPE html>
<html>
<head>
<title>Aftermath</title>
<!-- SCRIPTS-->
<!--Loads three.js into our game-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js"> </script>
<!--Loads orbit controls around player-->
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<!--Loads gltf files (our blender files)-->
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/GLTFLoader.js"></script>
<!--Pointer lock controls-->
<script src="https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/PointerLockControls.js"></script>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body { margin: 0; height: 100%; width: 100%; overflow: hidden}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<!--MOVEMENT-->
<script src="./important/THREEx.KeyboardState.js" ></script>
<script src="./important/FirstPersonControls.js" ></script>
<script src="./js/CharacterControls.js" ></script>
<!--========================================-->
<!--Lighting models-->
<script src="./js/sceneSubjects/lighting/GeneralLights.js" ></script>
<!--add models to scene-->
<!--Subject (model) scripts-->
<!--This is our main blender house-->
<script src="./js/sceneSubjects/House.js" ></script>
<!--Our character model file (not complete due to loading issues with fbx)-->
<script src="./js/sceneSubjects/characters/MainChar.js" ></script>
<!--Just a demo for you to see how this works-->
<script src="./js/sceneSubjects/objects/SceneSubject.js" ></script>
<!--Block to test raycasting -->
<script src="./js/sceneSubjects/characters/TestBlock.js" ></script>
<!--MANAGERS-->
<!--Load the scene manager-->
<script src="./js/EntityManager.js" ></script>
<script src="./js/SceneManager.js" ></script>
<script src = "./js/Time.js" ></script>
<!--Load our main.js function-->
<script type="module" src="./js/main2.js"></script>
</body>
</html>
This is my Scene Manager, which controls the whole scene. I just tested the initialization, which failed:
//Global Variables
var generalLights = new GeneralLights();
var house = new House();
var sceneSubject = new SceneSubject();
var testBlock = new TestBlock();
var mainChar = new MainChar(testBlock);
class SceneManager {
constructor(canvas) {
//this entire function renders a scene where you can add as many items as you want to it (e.g. we can create the house and add as
//many items as we want to the house). It renders objects from other JavaScript files
//------------------------------------------------------------------------------------------------------------------------------------------
//These are supposed to act like constants. DO NOT CHANGE
this.GAME_PAUSE = "pause";
this.GAME_RUN = "run";
//------------------------------------------------------------------------------------------------------------------------------------------
//we use (this) to make variables accessible in other classes
this.time = new Time();
this.game_state = this.GAME_RUN;
this.screenDimensions = {
width: canvas.width,
height: canvas.height
};
//the essentials for rendering a scene
this.scene = this.buildScene();
this.renderer = this.buildRender(this.screenDimensions);
this.camera = this.buildCamera(this.screenDimensions);
controls = new PointerLockControls( this.camera, document.body );
// this.scene.add(controls.getObject());
this.managers = this.createManagers();
this.loadToScene(this.managers[0].entities);
//Allow camera to orbit target (player) - OrbitPlayer Controls
//this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
//this.controls.target.set(0, 20, 0);
//this.controls.update();
}
loadToScene(entities)
{
for (let i = 0 ; i < entities.length ; i++)
{
console.log("before" +i.toString());
this.scene.add(entities[i].object);
console.log("after");
}
}
//this function creates our scene
buildScene() {
//create a new scene
const scene = new THREE.Scene();
//set the scene's background-> in this case it is our skybox
const loader = new THREE.CubeTextureLoader();
//it uses different textures per face of cube
const texture = loader.load([
'../skybox/House/posx.jpg',
'../skybox/House/negx.jpg',
'../skybox/House/posy.jpg',
'../skybox/House/negy.jpg',
'../skybox/House/posz.jpg',
'../skybox/House/negz.jpg'
]);
scene.background = texture;
//if we wanted it to be a color, it would have been this commented code:
//scene.background = new THREE.Color("#000");
return scene;
}
//this creates a renderer for us
buildRender({ width, height }) {
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true, alpha: true
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
return renderer;
}
//create a camera for the screen
buildCamera({ width, height }) {
//SETTING FIELD OF VIEW, ASPECT RATIO (which should generally be width/ height), NEAR AND FAR (anything outside near/ far is clipped)
const aspectRatio = width / height;
const fieldOfView = 60;
const nearPlane = 1;
const farPlane = 1000;
//there are 2 types of cameras: orthographic and perspective- we will use perspective (more realistic)
const camera = new THREE.PerspectiveCamera(fieldOfView, aspectRatio, nearPlane, farPlane);
//Set camera initial position to main character
let pos = mainChar.returnWorldPosition();
camera.position.set(pos.x,pos.y,pos.z);
return camera;
}
//add subjects to the scene
createManagers() {
const managers=[new EntityManager()];
//can be altered so we can add multiple entities, and depending on which position
//it is, certain ones won't be paused, and some will be
//Note that these variables are declared globally before the class definition
/*This is so that we can use any of these object's methods or values later somewhere else*/
managers[0].register(generalLights);
managers[0].register(house);
managers[0].register(mainChar);
managers[0].register(sceneSubject);
managers[0].register(testBlock);
return managers;
}
updateCameraPosition() {
//Match camera position and direction to the character's position and direction
let pos = mainChar.returnWorldPosition();
let dir = mainChar.returnObjectDirection();
//Set y to 10 to move camera closer to head-height
this.camera.position.set(pos.x,10,pos.z);
this.camera.rotation.set(dir.x,dir.y,dir.z);
}
//this updates the subject/model every frame
update() {
//won't call this loop if it's paused-> only for objects that need to be paused (managers that need to be paused)
if (this.game_state == this.GAME_RUN)
{
const runTime = this.time.getRunTime();
this.managers[0].update(runTime);
}
//update orbit controls
//this.controls.update();
this.updateCameraPosition();
this.renderer.render(this.scene, this.camera);
}
//this resizes our game when screen size changed
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
pause(){ //when pause mode is entered. The pause menu needs to be rendered.
this.game_state = this.GAME_PAUSE;
this.time.pause();
}
unpause(){
this.game_state = this.GAME_RUN;
this.time.unpause();
}
}
I changed all my es6 classes into es6 modules, and used import. I don't think there was a solution for this with cdn or raw git scripts.

Model not rendering on screen

I'm trying to load a 3D model on the screen but the screen is black, and sometimes I receive an error depending on the way I try to implement my code.
Here is my HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<title>T1 CG</title>
</head>
<body>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</body>
<script src="./lib/threejs/build/three.min.js"></script>
<script src="./lib/threejs/examples/js/loaders/GLTFLoader.js"></script>
<script src="./poke.js"></script>
</html>
Here is my javascript file:
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 geometry = new THREE.BoxGeometry(1, 1, 1);
var loader = new THREE.GLTFLoader();
loader.load('./assets/Squirtle/Squirtle.gltf', function(gltf) {
scene.add( gltf );
});
When I try to run like that, I receive the following error: THREE.Object3D.add: object not an instance of THREE.Object3D. But when I try to do something like scene.add(gltf.scene), I don't receive any error but the screen turns black and nothing happens.
Hope that somebody can help me, I'll appreciate it!
Thanks in advance.
Have you tried adding any lights to your scene? Most materials need to be illuminated in order to be visible. You can try a simple AmbientLight:
var light = new THREE.AmbientLight( 0x404040 );
scene.add( light );
Also make sure your camera is positioned a little far from the origin, otherwise the loaded .gltf and the camera will both be occupying the same spot. For instance, if the object is 2 units wide, you could place your camera 5 units away:
camera.position.z = 5;

How to use three JS in html div tag

I use domElement to append the data in window. But how can I use html div tag to append it to the window?
I got the error
Cannot read property 'appendChild' of null
where I can't append my three js code in div element.
<html>
<head>
<title>
Ajay's Beginners guide
</title>
</head>
<body>
<script src="../build/three.js"></script>
<script>
var scene, camera, renderer;
function init() {
var scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
}
renderer = new THREE.WebGLRenderer();
// renderer.setSize(WIDTH, HEIGHT);
console.log(document.body);
canvas = document.getElementById('mycanvas');
canvas.appendChild(renderer.domElement);
renderer.setClearColorHex(0x333F47, 1);
//color and opacity
var light = new THREE.PointLight(0xffffff);
light.position.set(-100, 200, 100);
scene.add(light);
camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 2000);
camera.set.position(0, 6, 0);
scene.add(camera);
var loader = new THREE.JSONLoader();
loader.load("models/treehouse_logo.js", function (geometry) {
var material = new THREE.MeshLambertMaterial({ color: ox55B663 });
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
controls = new THREE.OrbitControls(camera, render.domElement);
window.addEventListener('resize', function () {
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
// init();
function animate() {
requestAnimationFrame();
renderer.render(scene, camera);
controls.update();
}
</script>
<div id="mycanvas">
</div>
</body>
</html>
Moving from comment to answer, thanks for the suggestion #Marquizzo.
Your script exists in the body before the div "canvas" element. The browser parses the page in order (mostly). So, you can move the script below the div so that it exists to be appended to as it is currently null when your code executes.
Here's a link to a related Stack Question on waiting for page contents before hooking them in code: Pure JavaScript equivalent of jQuery's $.ready() - how to call a function when the page/DOM is ready for it

How to add object to scene?

I have code like this:
<html>
<head>
<script src="js/three.js"></script>
<script type="text/javascript">
function init()
{
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(0, window.innerWidth / window.innerHeight, 100, 100);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(1000, 1000);
document.body.appendChild(renderer.domElement);
var sphere_geometry = new THREE.SphereGeometry(150);
var material1 = new THREE.MeshPhongMaterial({ color: 0x0033ff, specular: 0x555555 });
var sphere_mesh = new THREE.Mesh(sphere_geometry, material1);
scene.add(sphere_mesh);
renderer.render(scene, camera);
}
</script>
</head>
<body onload="init()">
<canvas id="mycanvas" width="100" height="100"></canvas>
</body>
</html>
and i can't add a sphere into the scene. The only thing that i get is black square. How can I do it?
Just some fast tips:
-Place the camera to see the object, not just position but the direction where it is facing, do you have all your objects in front?
-Make the object visible, choose a good material definition, start with a boiler plate/hello world scene, once it works, modify it to get the scene as you want it to be.

Resources