textureLoader not working for a normal map - javascript

I'm trying to load a texture with three.js to use it as a normal map. It returns no error or anything else, but the texture is not loading. I end up with a black ball
import * as THREE from 'three';
/** Build the scene. */
const canvas = document.querySelector('#canvas');
const scene = new THREE.Scene();
const textureLoader = new THREE.TextureLoader();
/** Create the sphere. */
const gemoetry = new THREE.SphereBufferGeometry(.5, 64, 64);
const material = new THREE.MeshStandardMaterial({
metalness: 0.7,
roughness: 0.2,
normalMap: textureLoader.load('https://res.cloudinary.com/axiol/image/upload/v1617884764/CodePen/normalMap.png'),
color: new THREE.Color(0x292929)
});
const sphere = new THREE.Mesh(gemoetry, material);
scene.add(sphere);
/** Set the sizes based on the windows size. */
const sizes = {
width: window.innerWidth,
height: window.innerHeight
};
/** Add some light. */
const pointLight = new THREE.PointLight(0xffffff, 0.1)
pointLight.position.x = 2
pointLight.position.y = 3
pointLight.position.z = 4
scene.add(pointLight)
window.addEventListener('resize', () => {
sizes.width = window.innerWidth
sizes.height = window.innerHeight
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
});
/** Place the camera. */
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 2;
scene.add(camera);
/** Render the scene. */
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.render(scene, camera);
I don't really see what I could be missing here. Any idea ?

You render the scene with a normal map which is not yet fully loaded. Try it like so:
/** Build the scene. */
const canvas = document.querySelector('#canvas');
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
const textureLoader = new THREE.TextureLoader();
/** Create the sphere. */
const gemoetry = new THREE.SphereBufferGeometry(0.5, 64, 64);
const material = new THREE.MeshStandardMaterial({
metalness: 0.7,
roughness: 0.2,
normalMap: textureLoader.load('https://res.cloudinary.com/axiol/image/upload/v1617884764/CodePen/normalMap.png', render),
color: new THREE.Color(0xffffff)
});
const sphere = new THREE.Mesh(gemoetry, material);
scene.add(sphere);
/** Set the sizes based on the windows size. */
const sizes = {
width: window.innerWidth,
height: window.innerHeight
};
/** Add some light. */
const pointLight = new THREE.PointLight(0xffffff, 1)
pointLight.position.x = 2
pointLight.position.y = 3
pointLight.position.z = 4
scene.add(pointLight)
window.addEventListener('resize', () => {
sizes.width = window.innerWidth
sizes.height = window.innerHeight
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
});
/** Place the camera. */
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 2;
scene.add(camera);
/** Render the scene. */
const renderer = new THREE.WebGLRenderer({
canvas: canvas
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
render();
function render() {
renderer.render(scene, camera);
}
body {
margin:0
}
<script src="https://cdn.jsdelivr.net/npm/three#0.127.0/build/three.js"></script>
<canvas id="canvas"></canvas>
Notice the call of render() in the onLoad() callback of TextureLoader.load().

Related

OrbiterControls not working properly in three.js app

I'm trying to create a basic scene with an orbitercontrols that can rotate around the center, i.e. always looking at (0,0,0). I want it to behave like this https://threejs.org/examples/misc_controls_orbit.html exactly. But in my version if I click and drag to the left/right, the camera just spins in a circle always looking at (0,0,0). How can I fix this?
<!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 'https://threejs.org/build/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.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 );
// ADD LIGHT
const light = new THREE.PointLight(0xffffff, 2)
light.position.set(0, 5, 10)
scene.add(light)
// ADD ORBITER
const controls = new OrbitControls( camera, renderer.domElement );
controls.listenToKeyEvents( window );
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
//controls.screenSpacePanning = false;
//controls.minDistance = 100;
//controls.maxDistance = 500;
//controls.maxPolarAngle = Math.PI / 2;
//controls.minPolarAngle = Math.PI / 2;
//controls.maxPolarAngle = Math.PI / 2;
camera.position.set(0, -5, 5);
camera.lookAt( 0, 0, 0 );
camera.up.set( 0, 0, 1 );
//controls.target = new THREE.Vector3(0, 0, 0);
controls.update();
// ADD CUBE
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
// ADD MAP
const loader = new THREE.TextureLoader();
const height = loader.load('/data/images/height.png');
const texture = loader.load('/data/images/height.png');
const map_geometry = new THREE.PlaneBufferGeometry(10,10,64,64);
const map_material = new THREE.MeshStandardMaterial({
color:'orange',
//side: THREE.DoubleSide,
map:texture,
displacementMap: height,
displacementScale: 0.5,
//alphaMap: alpha,
//transparent:true
});
const map_plane = new THREE.Mesh(map_geometry, map_material);
//map_plane.position.set(0, 0, 0);
scene.add( map_plane );
// RENDER
function animate() {
requestAnimationFrame( animate );
//cube.rotation.x += 0.01;
//cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
The code needed several modifications. Use the code below instead and compare it with yours to find out which parts did I change.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body {
padding: 0;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://threejs.org/build/three.module.js';
import {OrbitControls} from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
// BUILDING THE SCENE
const scene = new THREE.Scene();
// ADDING CAMERA
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, -5, 5);
scene.add(camera);
// CREATING THE RENDERER
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// ADD LIGHT
const light = new THREE.PointLight(0xffffff, 2);
light.position.set(0, 5, 10);
scene.add(light);
// ADD ORBITER
const controls = new OrbitControls(camera, renderer.domElement);
controls.maxPolarAngle = Math.PI/2.2;
controls.minDistance = 5;
controls.maxDistance = 10;
controls.target.set(0, 0, 0);
// ADD CUBE
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, .5, 0);
scene.add(cube);
// ADD MAP
const loader = new THREE.TextureLoader();
const height = loader.load('/data/images/height.png');
const texture = loader.load('/data/images/height.png');
const map_geometry = new THREE.PlaneBufferGeometry(10,10,64,64);
const map_material = new THREE.MeshStandardMaterial({
color:'orange',
side: THREE.DoubleSide,
map:texture,
displacementMap: height,
displacementScale: 0.5,
});
const map_plane = new THREE.Mesh(map_geometry, map_material);
map_plane.rotation.x = Math.PI/2;
scene.add(map_plane);
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// ANIMATING THE SCENE
function animate() {
controls.update();
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
Write controls.update(); in the animate function.
controls.maxPolarAngle = Math.PI/2.2; doesn't let the camera to go under the ground.
controls.target.set(0, 0, 0); makes the control stair at the center.
I added map_plane.rotation.x = Math.PI/2; so the plane will be placed horizontally as the floor.
And side: THREE.DoubleSide, helps the floor to be visible from all angels.
I also added an onWindowResize function to the script to make the applicaion responsive. Now, it'll response to the browser's width and height when its resized.
In case of CSS, the page has default padding as well. So, adding a padding: 0; to the CSS code is not a bad idea as well.

How to make TextGeometry in THREE JS follow mouse?

This is my source code. I am trying to make the text rotate according to mouse position.
// Initialization
const scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
let body = document.getElementsByTagName("body");
let pageX = 0.5;
let pageY = 0.5;
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("board").appendChild(renderer.domElement);
// Handle resize event
window.addEventListener('resize', () => {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
camera.position.z = 20;
// Create light
let directLight = new THREE.DirectionalLight('#fff', 4);
directLight.position.set(0, 7, 5);
scene.add(directLight);
var light = new THREE.AmbientLight( 0x404040 ); // soft white light
scene.add( light );
function animate (){
requestAnimationFrame( animate );
var loader = new THREE.FontLoader();
loader.load( 'https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function ( font ) {
var geometry = new THREE.TextGeometry( 'Hello three.js!', {
font: font,
size: 3,
height: 0.5,
curveSegments: 4,
bevelEnabled: true,
bevelThickness: 0.02,
bevelSize: 0.05,
bevelSegments: 3
} );
geometry.center();
var material = new THREE.MeshPhongMaterial(
{ color: '#dbe4eb', specular: '#dbe4eb' }
);
var mesh = new THREE.Mesh( geometry, material );
mesh.rotation.x = (pageY - 0.5) * 2;
mesh.rotation.y = (pageX - 0.5) * 2;
scene.add( mesh );
} );
renderer.render(scene, camera);
}
animate();
// Get mouse coordinates inside the browser
document.body.addEventListener('mousemove', (event) => {
pageX = event.pageX / window.innerWidth;
pageY = event.pageY / window.innerHeight;
});
renderer.render(scene, camera);
</script>
This is the best I could get. The problem is that each time I move the mouse, it instantiates a new mesh and rotates it accordingly, and I only need one mesh to follow the mouse. Can anyone help?
Thanks in advance!
As you already figured out, each frame you're reloading the font and ultimately recreating the mesh each time.
To get around this you need to move the font loading and object creation inside some initialization function, so it just happens once.
The only part of code you want to keep inside the render loop is the updating of the text's rotation according to the mouse movement:
mesh.rotation.x = (pageY - 0.5) * 2;
mesh.rotation.y = (pageX - 0.5) * 2;
This will bring up another problem though. Since mesh is a local object defined inside the callback function of the font loader, it won't be accessible outside. Luckily three.js offers a property called .name which you can use to give your object a name.
e.g.
var mesh = new THREE.Mesh(geometry, material);
mesh.name = "myText";
scene.add(mesh);
Later on you can get a reference to this object using:
scene.getObjectByName("myText")
Here's an example:
var container, scene, camera, renderer, pageX, pageY;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
pageX = 0.5;
pageY = 0.5;
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("container").appendChild(renderer.domElement);
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
camera.position.z = 20;
let directLight = new THREE.DirectionalLight('#fff', 4);
directLight.position.set(0, 7, 5);
scene.add(directLight);
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
var loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function(font) {
var geometry = new THREE.TextGeometry('Hello three.js!', {
font: font,
size: 3,
height: 0.5,
curveSegments: 4,
bevelEnabled: true,
bevelThickness: 0.02,
bevelSize: 0.05,
bevelSegments: 3
});
geometry.center();
var material = new THREE.MeshPhongMaterial({
color: '#dbe4eb',
specular: '#dbe4eb'
});
var mesh = new THREE.Mesh(geometry, material);
mesh.name = "myText";
scene.add(mesh);
animate();
});
document.body.addEventListener('mousemove', (event) => {
pageX = event.pageX / window.innerWidth;
pageY = event.pageY / window.innerHeight;
});
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
scene.getObjectByName("myText").rotation.x = (pageY - 0.5) * 2;
scene.getObjectByName("myText").rotation.y = (pageX - 0.5) * 2;
renderer.render(scene, camera);
}
init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r120/three.min.js"></script>
<div id="container"></div>

How to move camera back on canvas

I am looking for a way to move the camera back with the code that I have here. Does anyone have any suggestions?
I have adjusted camera.position.set and added camera.position.x parameters.
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({
canvas
});
const fov = 45;
const aspect = 2;
const near = 0.1;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 20);
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 5, 0);
controls.update();
const scene = new THREE.Scene();
scene.background = new THREE.Color('black'); {
const planeSize = 0;
const loader = new THREE.TextureLoader();
const texture = loader.load('');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.magFilter = THREE.NearestFilter;
const repeats = planeSize / 2;
texture.repeat.set(repeats, repeats);
const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
const planeMat = new THREE.MeshPhongMaterial({
map: texture,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(planeGeo, planeMat);
mesh.rotation.x = Math.PI * -.5;
scene.add(mesh);
}
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
const halfFovY = THREE.Math.degToRad(camera.fov * .5);
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
const direction = (new THREE.Vector3())
.subVectors(camera.position, boxCenter)
.multiply(new THREE.Vector3(1, 0, 1))
.normalize();
camera.near = boxSize / 100;
camera.far = boxSize * 100;
camera.updateProjectionMatrix();
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}
const box = new THREE.Box3().setFromObject(root);
const boxSize = box.getSize(new THREE.Vector3()).length();
const boxCenter = box.getCenter(new THREE.Vector3());
frameArea(boxSize * 0.5, boxSize, boxCenter, camera);
controls.maxDistance = boxSize * 10;
controls.target.copy(boxCenter);
controls.update();
});
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render() {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
The answer to this question has been resolved.
I needed to increase the box size using this line of code:
frameArea(boxSize * 0.5, boxSize, boxCenter, camera);
The equations are based off of SOHCAHTOA. I needed to compute the distance and then move the camera that distance from the center of the box.

Can't view object in three js

Want to create objects (cubes), within a for loop, then output them in a random location on the page. Cubes do not appear unsure why.
**Info: When I console log the cube get **
-cube.js:24 Mesh {uuid: "8859E918-7D3A-47ED-BDEF-072BC60FF725", name:
"", type: "Mesh", parent: Scene, children: Array(0), …}
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth /
window.innerHeight, 0.1, 1000 )
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth,window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
var geometry = new THREE.BoxGeometry(3, 1, 1);
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
meshX = -5;
for(var i = 0; i<20;i++) { //amount of shapes
cube.position.x = (Math.random() - 0.5) * 10; //Location of shapes
cube.position.y = (Math.random() - 0.5) * 10;
cube.position.z = (Math.random() - 1.2) * 10;
scene.add(cube);
meshX+=1;
console.log(cube);
}
var render = function() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
You need a light for MeshLambertMaterial (as opposed MeshBasicMaterial which does not use lights).
Also, you need to make a new Cube instance in the loop, otherwise you are just changing the location of the initial cube.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth /
window.innerHeight, 0.1, 1000 )
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth,window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
var geometry = new THREE.BoxGeometry(3, 1, 1);
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
//var cube = new THREE.Mesh(geometry, material);
//meshX = -5;
for(var i = 0; i<20;i++) { //amount of shapes
var cube = new THREE.Mesh(geometry, material);
cube.position.x = (Math.random() - 0.5) * 10; //Location of shapes
cube.position.y = (Math.random() - 0.5) * 10;
cube.position.z = (Math.random() - 1.2) * 10;
scene.add(cube);
//meshX+=1;
//console.log(cube);
}
var render = function() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
body {
padding: 0;
margin: 0;
position: relative;
}
<script src="https://rawgithub.com/mrdoob/three.js/r104/build/three.js"></script>

three.js(version 102) How to set default position & rotation of camera with OrbitControls

I create a scene, and it is all fine without using OrbitControls.
When I use OrbitControls, I found that my camera's position and rotation has changed, and I can't modify it.
Can somebody tell me how to set a default position and rotation of the camera with OrbitControls.
Thanks!
OrbitControls require a target. Set the target such that you get the same view.
camera.position.set(1, 8, 7);
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 3, 0);
controls.update();
'use strict';
/* global THREE */
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas: canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 500;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(1, 8, 7);
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 3, 0);
controls.update();
const scene = new THREE.Scene();
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
{
const boxWidth = 1;
const boxHeight = 10;
const boxDepth = 1;
const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
const material = new THREE.MeshPhongMaterial({color: 'red'});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.y = .5;
}
{
const geometry = new THREE.PlaneBufferGeometry(10, 10);
const material = new THREE.MeshPhongMaterial({color: 'gray'});
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
plane.rotation.x = Math.PI * -0.5;
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/js/controls/OrbitControls.js"></script>
Or you could compute a target based on the current camera view. The OrbitControls orbit around the target so you'd need to choose a distance from the camera as your target
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(1, 2, 5);
camera.rotation.set(.1, .2, 0);
// get the direction of the camera
const direction = new THREE.Vector3();
camera.getWorldDirection(direction);
const controls = new THREE.OrbitControls(camera, canvas);
// point the target from the camera in the
// target direction
camera.getWorldPosition(controls.target);
controls.target.addScaledVector(direction, 5);
controls.update();
Note the 5 in addScaledVector means the target will be 5 units in front of the camera in the direction the camera was facing. Whether 5 is the right distance is up to you. In my sample scene the camera started at z = 5 so 5 units in front of the camera seemed like a reasonable place to put the target
'use strict';
/* global THREE */
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas: canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 500;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(1, 2, 5);
camera.rotation.set(.1, .2, 0);
// compute a target direction
const direction = new THREE.Vector3();
camera.getWorldDirection(direction);
const controls = new THREE.OrbitControls(camera, canvas);
// point the target from the camera in the
// target direction
camera.getWorldPosition(controls.target);
controls.target.addScaledVector(direction, 5);
controls.update();
const scene = new THREE.Scene();
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
{
const boxWidth = 1;
const boxHeight = 10;
const boxDepth = 1;
const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
const material = new THREE.MeshPhongMaterial({color: 'red'});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.y = .5;
}
{
const geometry = new THREE.PlaneBufferGeometry(10, 10);
const material = new THREE.MeshPhongMaterial({color: 'gray'});
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
plane.rotation.x = Math.PI * -0.5;
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/js/controls/OrbitControls.js"></script>

Categories

Resources