use fabric js canvas as a threejs 3d model texture - javascript

juste starting to learn threejs and to do so decided to build a t-shirt configurator in combination with fabric js. my goal is that the user can upload a picture to the canvas (cnvs) which will be mapped to the gltf model of a t-shirt the probleme is that the texture doesn't show .
code :
var canvas2 = new fabric.Canvas('cnvs', {
backgroundColor: 'red'
});
fabric.Image.fromURL('eo.png', function(myImg) {
//i create an extra var for to change some image properties
var img1 = myImg.set({ left: 0, top: 0 ,width:150,height:150});
canvas2.add(img1);
canvas2.renderAll();
});
var canvasTexture = new THREE.CanvasTexture(canvas2);
canvasTexture.wrapS = THREE.RepeatWrapping;
canvasTexture.wrapT = THREE.RepeatWrapping;
const gltfLoader2 = new GLTFLoader();
gltfLoader2.load('tshirt2.gltf', (gltf2) => {
model = gltf2.scene;
model.traverse(child => {
console.log(child.material);
if (child.material && child.material.name === 'Pattern2D_13095') {
// Pattern2D_13095
child.material.map = new TextureLoader().load( new THREE.MeshStandardMaterial({
map: canvasTexture,
}));
}
});
canvas2.on("after:render", function() {
model.material.map.needsUpdate = true;
});
canvas2.on('mouse:down',function(event){
if(canvas2.getActiveObject()){
alert(event.target);
}
})
scene.add(model);
model.rotation.x = 1.5;
model.position.y=310;
model.position.x=-300;
model.position.z=-100;
model.scale.set(1000,1000,1000);
});
});
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);
requestAnimationFrame(render);
}
function animate(){
requestAnimationFrame(animate);
cloudParticles.forEach(p => {
p.rotation.z -= 0.001;
});
root.rotation.z -= 0.01;
renderer.render(scene, camera);
model.material.needsUpdate = true;
}
animate();
lights/camera:
let cloudParticles = [];
let root;
let model;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1,
1000 );
camera.position.z = 2;
camera.rotation.x = 1.16;
camera.rotation.y = -0.12;
camera.rotation.z = 0;
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
scene.fog = new THREE.FogExp2(0x11111f, 0.002);
renderer.setClearColor(scene.fog.color);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild( renderer.domElement );
let directionalLight = new THREE.DirectionalLight(0xff8c19);
directionalLight.position.set(0,0,1);
scene.add(directionalLight);
let orangeLight = new THREE.PointLight(0xcc6600,50,450,1.7);
orangeLight.position.set(200,300,100);
scene.add(orangeLight);
let redLight = new THREE.PointLight(0xd8547e,50,450,1.7);
redLight.position.set(100,300,100);
scene.add(redLight);
let blueLight = new THREE.PointLight(0x3677ac,50,450,1.7);
blueLight.position.set(300,300,200);
scene.add(blueLight);
let directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(-110,-110,-120);
scene.add(directionalLight2);
HTML:
<div class="cnvscon">
<canvas id="cnvs" height="256" width="256" ></canvas></div>
<canvas id="c"></canvas>
here is an img of the result ( the mesh is black ):
result
gltfviewer

child.material.map = new TextureLoader().load( new THREE.MeshStandardMaterial({
map: canvasTexture }));
I'm afraid this code is incorrect. It should be sufficient to assign canvasTexture to the respective map property. Meaning:
child.material.map = canvasTexture;

Related

I've written code that takes geojson array and translates it into Vector3, but it isn't showing up

The plan is for it to draw borders using GeoJSON coords. Also when I write coordinates directly into the same file it works normally and I've noticed that my fbih variable doesn't get the fbih: THREE.Vector3 when hovered over. I'm using ViteJS + ThreeJS, Here's the code:
import './style.css'
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { Vector3 } from 'three';
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(20);
renderer.render(scene,camera);
const teksturazemlje = new THREE.TextureLoader().load('slike/zemlja.png')
const zemlja = new THREE.Mesh (
new THREE.SphereGeometry(16, 500, 500 ),
new THREE.MeshStandardMaterial({
map:teksturazemlje,
})
);
scene.add(zemlja)
function koordinate([lon,lat]){
var phi = (90-lat)*(Math.PI/180);
var theta = (lon+180)*(Math.PI/180);
var x = -((16) * Math.sin(phi)*Math.cos(theta));
var z = ((16) * Math.sin(phi)*Math.sin(theta));
var y = ((16) * Math.cos(phi));
return new THREE.Vector3(x,y,z)
}
const boja = new THREE.MeshBasicMaterial({
color: 0xff00cc,
side : THREE.DoubleSide,
});
var fbih = [];
fetch ('granice/bih.json')
.then (res => res.json())
.then (data => {
for (let element of data.features[0].geometry.coordinates[0][0]) {
fbih.push(koordinate(element))
}
});
console.log(fbih)
const linije = new THREE.BufferGeometry().setFromPoints(fbih)
const line = new THREE.Line(linije,boja)
scene.add(line);
const ambientlight= new THREE.AmbientLight(0xffffff);
scene.add(ambientlight)
const controls = new OrbitControls(camera, renderer.domElement);
function animate(){
requestAnimationFrame(animate);
controls.update();
renderer.render (scene, camera);
}
controls.enableDamping = true;
controls.dampingFactor = 0.04;
controls.rotateSpeed = 0.07;
controls.maxDistance = 20;
controls.minDistance = 16.5;
controls.enablePan = false;
controls.zoomSpeed = 0.30;
animate()
It displays Vector3 array in console.log but it isn't displayed through BufferGeometry. Sorry if there are grammatical errors, English isn't my first language.

three.js change same material texture multiple times

In three.js I would like to change the same object material texture multiple times.
After the page loaded the base 3D model rendered but already changed the left side of the furniture. (I made it on purpose). After 5 seconds it should change the texture again but the texture disappears. In the Network Activity tab the texture downloaded.
I would really appreciate it if somebody would give me a hint.
import * as THREE from 'three';
import {
OrbitControls
} from '../js/three/examples/jsm/controls/OrbitControls.js'
import {
GLTFLoader
} from '../js/three/examples/jsm/loaders/GLTFLoader.js'
const scene = new THREE.Scene();
const manager = new THREE.LoadingManager();
const renderer = new THREE.WebGLRenderer();
const loader = new GLTFLoader(manager);
const camera = new THREE.PerspectiveCamera(
30,
window.innerWidth / window.innerHeight,
0.1,
2000
)
camera.position.z = 3.5
camera.position.x = 0
camera.position.y = 1
const hemiLight = new THREE.HemisphereLight();
scene.add(hemiLight);
const light1 = new THREE.AmbientLight(0xFFFFFF, 0.3);
scene.add(light1);
const light2 = new THREE.DirectionalLight(0xFFFFFF, 0.8 * Math.PI);
light2.position.set(0.5, 1, 0.8);
scene.add(light2);
const light3 = new THREE.DirectionalLight(0xFFFFFF, 0.8 * Math.PI);
light3.position.set(-0.5, -1, -0.8);
scene.add(light3);
render.toneMapping = THREE.ACESFilmicToneMapping;
renderer.physicallyCorrectLights = true
renderer.shadowMap.enabled = true
renderer.outputEncoding = THREE.sRGBEncoding
renderer.setClearColor(0xcccccc);
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
const loadElement = async (input, xinput, yinput, zinput, cb) => {
loader.load(input, async function (gltf) {
const box = new THREE.Box3().setFromObject(gltf.scene);
const center = box.getCenter(new THREE.Vector3());
gltf.scene.position.x += (gltf.scene.position.x - center.x + xinput);
gltf.scene.position.y += (gltf.scene.position.y - center.y + yinput);
gltf.scene.position.z += (gltf.scene.position.z - center.z + zinput);
cb(gltf.scene)
}),
function () {}, // onProgress function
function (error) {
console.log(error)
} // onError function
}
window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight
renderer.setSize(window.innerWidth, window.innerHeight)
render()
}
function render() {
renderer.render(scene, camera)
}
function animate() {
requestAnimationFrame(animate)
controls.update()
render()
}
document.addEventListener("DOMContentLoaded", () => {
animate();
loadElement("../models/base/model.gltf", 0, -0.3, 0, (obj) => {
obj.name = "base";
scene.add(obj)
obj.traverse(child => {
if (child.material && child.material.name === 'dark_wood') {
child.material = new THREE.TextureLoader().load("../models/base/wood_color.png", (texture) => {
texture.flipY = false;
texture.encoding = THREE.sRGBEncoding;
texture.needsUpdate = true;
});
}
});
})
setTimeout(() => {
scene.getObjectByName('base').traverse(child => {
if (child.material && child.material.name === 'wood') {
child.material = new THREE.TextureLoader().load("../models/base/dark_wood_color.png", (texture) => {
texture.flipY = false;
texture.encoding = THREE.sRGBEncoding;
texture.needsUpdate = true;
});
}
});
}, 5000);
});

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.

Three.js: How to calculate the minimum bounding rectangle of an object in a camera image?

I'd like to calculate and draw the minimum bounding rectangle (MBR) of an object in the image of a camera (2D projection).
The following picture shows the MBR of the cube object of the example provided below.
I took a screenshot of the camera image and drew the MBR (red rectangle) manually by eye.
How can I calculate the MBR (size and position in the camera image) programmatically and draw it in the canvas of the camera image (in real time)?
Edit: I added a MBR to my example based on this related solution, but I drew the MBR on a 2D overlay canvas. It works fine till you move the camera (using the mouse). Then the MBR is not correct (shifted and wrong size). Does the calculation not fit to my example or is there a bug in my implementation?
Note: I do not only want to draw the MBR but also find out the 2D coordinates and size on the camera image.
function computeScreenSpaceBoundingBox(mesh, camera) {
var vertices = mesh.geometry.vertices;
var vertex = new THREE.Vector3();
var min = new THREE.Vector3(1, 1, 1);
var max = new THREE.Vector3(-1, -1, -1);
for (var i = 0; i < vertices.length; i++) {
var vertexWorldCoord = vertex.copy(vertices[i]).applyMatrix4(mesh.matrixWorld);
var vertexScreenSpace = vertexWorldCoord.project(camera);
min.min(vertexScreenSpace);
max.max(vertexScreenSpace);
}
return new THREE.Box2(min, max);
}
function normalizedToPixels(coord, renderWidthPixels, renderHeightPixels) {
var halfScreen = new THREE.Vector2(renderWidthPixels/2, renderHeightPixels/2)
return coord.clone().multiply(halfScreen);
}
const scene = new THREE.Scene();
const light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 1, 1, 0.5 ).normalize();
scene.add( light );
scene.add(new THREE.AmbientLight(0x505050));
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
const renderWidth = window.innerWidth;
const renderHeight = window.innerHeight;
const camera = new THREE.PerspectiveCamera( 75, renderWidth / renderHeight, 0.1, 1000 );
camera.position.z = 10;
const controls = new THREE.OrbitControls( camera );
controls.update();
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const clock = new THREE.Clock();
const overlayCanvas = document.getElementById('overlay');
overlayCanvas.width = renderWidth;
overlayCanvas.height = renderHeight;
const overlayCtx = overlayCanvas.getContext('2d');
overlayCtx.lineWidth = 4;
overlayCtx.strokeStyle = 'red';
const animate = function () {
const time = clock.getElapsedTime() * 0.5;
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
cube.position.x = Math.sin(time) * 5
controls.update();
renderer.render( scene, camera );
const boundingBox2D = computeScreenSpaceBoundingBox(cube, camera);
// Convert normalized screen coordinates [-1, 1] to pixel coordinates:
const {x: w, y: h} = normalizedToPixels(boundingBox2D.getSize(), renderWidth, renderHeight);
const {x, y} =
normalizedToPixels(boundingBox2D.min, renderWidth, renderHeight)
.add(new THREE.Vector2(renderWidth / 2, renderHeight / 2));
overlayCtx.clearRect(0, 0, renderWidth, renderHeight);
overlayCtx.strokeRect(x, y, w, h);
};
animate();
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
#overlay {
position: absolute;
}
<body>
<script src="https://unpkg.com/three#0.104.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.104.0/examples/js/Detector.js"></script>
<script src="https://unpkg.com/three#0.104.0/examples/js/controls/OrbitControls.js"></script>
<canvas id="overlay"></canvas>
</body>
Note: Please write a comment if my question is unclear so that I know what to describe in more detail.
Thanks to WestLangley for pointing me to the related solution of Holger L and thanks to manthrax for fixing a bug in that solution that made me miss a bug of my own. In my example, I simply miss-transformed the y-coordinate from WebGL 2D screen coordinates (origin is in the center of the canvas and y-axis points up) to regular 2D canvas coordinates (origin is in the top left corner of the canvas and y-axis points down). I did not consider that the y-axis is reversed. Below is a fixed version of the example:
const computeScreenSpaceBoundingBox = (function () {
const vertex = new THREE.Vector3();
const min = new THREE.Vector3(1, 1, 1);
const max = new THREE.Vector3(-1, -1, -1);
return function computeScreenSpaceBoundingBox(box, mesh, camera) {
box.set(min, max);
const vertices = mesh.geometry.vertices;
const length = vertices.length;
for (let i = 0; i < length; i++) {
const vertexWorldCoord =
vertex.copy(vertices[i]).applyMatrix4(mesh.matrixWorld);
const vertexScreenSpace = vertexWorldCoord.project(camera);
box.min.min(vertexScreenSpace);
box.max.max(vertexScreenSpace);
}
}
})();
const renderWidth = window.innerWidth;
const renderHeight = window.innerHeight;
const renderWidthHalf = renderWidth / 2;
const renderHeightHalf = renderHeight / 2;
const scene = new THREE.Scene();
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 1, 0.5).normalize();
scene.add(light);
scene.add(new THREE.AmbientLight(0x505050));
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshLambertMaterial({color: 0x00ff00});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
const camera = new THREE.PerspectiveCamera(75, renderWidth / renderHeight, 0.1, 1000);
camera.position.z = 10;
const controls = new THREE.OrbitControls(camera);
controls.update();
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const clock = new THREE.Clock();
const overlayCanvas = document.getElementById('overlay');
overlayCanvas.width = renderWidth;
overlayCanvas.height = renderHeight;
const overlayCtx = overlayCanvas.getContext('2d');
overlayCtx.lineWidth = 4;
overlayCtx.strokeStyle = 'red';
const boundingBox2D = new THREE.Box2();
const animate = function () {
const time = clock.getElapsedTime() * 0.5;
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
cube.position.x = Math.sin(time) * 5;
controls.update();
renderer.render(scene, camera);
computeScreenSpaceBoundingBox(boundingBox2D, cube, camera);
// Convert normalized screen coordinates [-1, 1] to pixel coordinates:
const x = (boundingBox2D.min.x + 1) * renderWidthHalf;
const y = (1 - boundingBox2D.max.y) * renderHeightHalf;
const w = (boundingBox2D.max.x - boundingBox2D.min.x) * renderWidthHalf;
const h = (boundingBox2D.max.y - boundingBox2D.min.y) * renderHeightHalf;
overlayCtx.clearRect(0, 0, renderWidth, renderHeight);
overlayCtx.strokeRect(x, y, w, h);
};
animate();
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
#overlay {
position: absolute;
}
<body>
<script src="https://unpkg.com/three#0.104.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.104.0/examples/js/Detector.js"></script>
<script src="https://unpkg.com/three#0.104.0/examples/js/controls/OrbitControls.js"></script>
<canvas id="overlay"></canvas>
</body>

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