Setting the position of a text geometry? - javascript

I have looked through stack overflow and google and I have found how to CENTER a text geometry but that is not what I want to do.
I have a scene that just has a block of text that says "Buy Here!". Using the documentation in the three.js website and examples here I was able to do that after some struggling. I had some trouble finding out how to refer to that mesh since I had created the geometry inside a function, and it took hours for me to know about setting a name for it as a string so it can be accessible from different parent/child levels.
What I am NOT able to do now is to offset the text by some arbitrary number of units. I tried shifting it down by 5 units. No matter how I try to do it it isn't working. I either manage to make the text geometry disappear OR my whole scene is black.
Here is my code...
I have the basic scene setup working properly and I'll include it here but feel free to skip since I'm pretty sure this has nothing to do with the issue...
import './style.css'
import * as THREE from 'three';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three#0.117.0/examples/jsm/controls/OrbitControls.js';
import TWEEN from 'https://cdn.jsdelivr.net/npm/#tweenjs/tween.js#18.5.0/dist/tween.esm.js';
//BASIC SCENE SETUP
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
//LIGHTS (POINT AND AMBIENT)
const pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.set(5, 5, 5);
const ambientLight = new THREE.AmbientLight(0xFFFFFF);
scene.add(pointLight, ambientLight);
//RESIZE WINDOW
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}, false);
//ORBIT CONTROLS
const controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 5;
controls.maxDistance = 70;
controls.enablePan = false;
controls.enableRotate = false;
controls.enableZoom = false;
controls.target.set(0,0,-1);
camera.position.setZ(25);
window.addEventListener("click", (event) => {
onClick(event);
})
window.addEventListener("mousemove", onMouseMove);
var animate = function() {
requestAnimationFrame(animate);
controls.update();
render();
TWEEN.update();
};
function render() {
renderer.render(scene, camera);
}
animate();
and here is my code for the text object....
var loaderF = new THREE.FontLoader();
loaderF.load( 'https://threejs.org/examples/fonts/optimer_regular.typeface.json', function ( font ) {
var geometry = new THREE.TextGeometry( 'Buy Here!', {
font: font,
size: 2.3,
height: 0.1,
curveSegments: 15,
bevelEnabled: true,
bevelThickness: 0.5,
bevelSize: 0.31,
bevelSegments: 7
} );
geometry.center();
var material = new THREE.MeshLambertMaterial({color: 0x686868});
var mesh = new THREE.Mesh( geometry, material );
mesh.name = "bhText"
scene.add( mesh );
mesh.userData = { URL: "http://google.com"};
} );
Here's what I have tried.....
under "var geometry ({...});" I typed....
geometry.position.setX(-5);
but the text object disappears completely so I tried
geometry.position.setX = -5;
but there was no difference so i tried taking out
geometry.center();
but it had the same results.
So then I tried using
mesh.position.x = -5;
with AND without
geometry.center();
but again, they all just make my text object disappear.
So now I tried to set the position from outside the function by typing the following code OUTSIDE of everything that is contained in
loaderF.load ('https.....', function (font){var geometry = .....})
using the reference I learned....
scene.getObjectByName("bhText").position.x(-5);
but this makes my entire scene go blank (black). So I tried variations of like
scene.getObjectByName("bhText").position.x = -5;
scene.getObjectByName("bhText").position.setX(-5);
scene.getObjectByName("bhText").position.setX = -5;
mesh.position.setX = -5;// I was pretty sure this wasn't going to work since I wasn't
//using the mesh name specifically for when it's inside something
//I can't reach because of parent-child relations
and again trying each of those with AND without
geometry.center();
but they all made my scene go black.
I just wanna move it down a couple of units. Sheesh.
Could anyone be kind enough to tell me WHERE in my code I can set the position of the text geometry? Thank you please.

I just wanna move it down a couple of units.
In this case use mesh.position.y = - 5;. Changing the x coordinate will move the mesh to the left or right. Here is a complete live example based on your code:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set( 0, 0, 10 );
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
const pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.set(5, 5, 5);
const ambientLight = new THREE.AmbientLight(0xFFFFFF);
scene.add(pointLight, ambientLight);
const loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/optimer_regular.typeface.json', function(font) {
const geometry = new THREE.TextGeometry('Buy Here!', {
font: font,
size: 2,
height: 0.5
});
geometry.center();
const material = new THREE.MeshLambertMaterial({
color: 0x686868
});
const mesh = new THREE.Mesh(geometry, material);
mesh.position.y = - 1; // FIX
mesh.name = "bhText"
scene.add(mesh);
renderer.render(scene, camera);
});
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.130.1/build/three.min.js"></script>

Related

Three.js texture does not load

I'm trying to make a model of planet Earth, but the texture doesn't load and I don't know why this happens, I tried to change the image format and also use it as an export link and it still doesn't work.
my code:
import * as THREE from 'https://cdn.skypack.dev/three#0.134.0'
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);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(5, 50, 50),
new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load('.img/global.jpeg')
})
);
scene.add(sphere);
camera.position.z = 15;
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
My first suggestion is for you to split up your code into individual steps so you can pinpoint where the error is taking place. Additionally, TextureLoader.load() has a few callback functions that you can help you determine if loading was successful or if it failed:
const geom = new THREE.SphereGeometry(5, 50, 50);
const texLoader = new THREE.TextureLoader();
const texture = texLoader.load(
// Location
'.img/global.jpeg',
// On success
function(texture) {
console.log("Success!");
console.log(texture);
},
// Progress (ignored)
undefined,
// On error
function(err) {
console.log("Error");
console.log(err);
}
);
const mat = new THREE.MeshBasicMaterial({map: texture});
const sphere = new THREE.Mesh(geom, mat);
Then you can check your console to see what the logs are displaying.

How can I draw Letters in 3js/threeJS easily?

I have to draw letters using 3JS.
Previously I have drawed objects in Canvas with beziercurves, using a website that helped do them with the mouse.
Is there such a tool for the same job in 3JS?
I can't seem to find anything. And drawing them manually in code just seems a waste of time.
I've searched everywhere for it but nothing.
I'm using Spline Curves btw...
curve = new THREE.SplineCurve( [
new THREE.Vector2( -90, 50),
new THREE.Vector2( -150, 0),
new THREE.Vector2( -130, 50),
]);
Thanks in advance
https://threejs.org/docs/#manual/en/introduction/Creating-text
Gives different ways to draw text.
You can use TextGeometry:
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight);
camera.position.z = 10;
scene = new THREE.Scene();
var loader = new THREE.FontLoader();
loader.load('https://unpkg.com/three#0.77.0/examples/fonts/helvetiker_regular.typeface.json', function(font) {
var geometry = new THREE.TextGeometry('Hello World', {
font: font,
size: 1,
height: 1
});
geometry.center();
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r99/three.js" integrity="sha256-QlZjRhqOlDukXFfprbpsdrDQws7TtQdTGDh7F7Q3310=" crossorigin="anonymous"></script>

three.js - How to set camera position?

I'm pretty beginner in three.js and webgl programming. so I have created a box in three.js and its working fine but the problem is when I set camera position in z axis(eg: camera.position.z = 2; ) the box just disappears. could anyone explain me why is it happening and how can I properly set the position of the camera?
try uncommenting the camera.position.z = 2; in the fiddle
function init() {
var scene = new THREE.Scene();
var box = getBox(1, 1, 1);
scene.add(box);
var camera = new THREE.Camera(45, window.innerWidth/window.innerHeight, 1, 1000 );
//camera.position.z = 2;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("webgl").appendChild(renderer.domElement);
renderer.render(scene, camera);
}
function getBox(w, h, d) {
var geometry = new THREE.BoxGeometry(w, h, d);
var material = new THREE.MeshBasicMaterial({
color : 0x00ff00
});
var mesh = new THREE.Mesh(geometry, material);
return mesh;
}
init();
not sure if you're trying to create this scene with an orthographic camera or perspective camera, but you'll typically need to specify the camera by type (ie THREE.PerspectiveCamera(...)).
I also added a few extra lines to ensure the camera was configured correctly, namely, setting the "LookAt" point to (0,0,0) , as well as setting an actual position of the camera via the THREE.Vector3.set(...) method.
Here are my adjustments to your code:
function init() {
var scene = new THREE.Scene();
var box = getBox(1, 1, 1);
scene.add(box);
var camera = new THREE.PerspectiveCamera(70,
window.innerWidth/window.innerHeight, 0.1, 1000 ); // Specify camera type like this
camera.position.set(0,2.5,2.5); // Set position like this
camera.lookAt(new THREE.Vector3(0,0,0)); // Set look at coordinate like this
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("webgl").appendChild(renderer.domElement);
renderer.render(scene, camera);
}
function getBox(w, h, d) {
var geometry = new THREE.BoxGeometry(w, h, d);
var material = new THREE.MeshBasicMaterial({
color : 0x00ff00
});
var mesh = new THREE.Mesh(geometry, material);
return mesh;
}
init();
Try
camera.position.set( <X> , <Y> , <Z> );
where <X> and <Z> are 2D coordinates and <Y> is height

Limit OrbitControls to an Area of page that does not have the Render

I'm an old COBOL programmer, teaching myself a bit of Javascript and Three.js for a little personal project, and I've got struck now with this doubt for almost two days.
I've read all the questions about OrbitControls here in StackOverflow, and couldn't find anything related to what I'm trying to do. So any help would be appreciated.
I have a scene that's like the image below:
And here's what my Script Looks like right Now:
var container, renderer, scene, camera, controls;
var Main = {
Init: function () {
document.getElementById("comprimento").innerHTML = "Comprimento: " + localStorage.storLength / 100;
document.getElementById("largura").innerHTML = "Largura: " + localStorage.storWidth / 100;
document.getElementById("altura").innerHTML = "Altura: " + localStorage.storHeight / 100;
document.getElementById("quadrado").innerHTML = "Metros²: " + localStorage.storSquare;
Main.Render();
Main.Camera();
Main.Draw();
Main.Update();
// events
window.addEventListener('resize', onWindowResize, false);
},
Render: function () {
renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffe6ff);
container = document.getElementById("building");
document.body.appendChild(container);
container.appendChild(renderer.domElement);
// Inicializacao da Cena
scene = new THREE.Scene();
},
Camera: function () {
//Inicializacao da Camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
//Posicao da Camera nos eixos X,Y,Z
camera.position.set(0, 100, 800);
camera.lookAt(scene.position);
//Controle de Camera
controls = new THREE.OrbitControls(camera, renderer.domElement);
//Controle de Iluminação
var light = new THREE.PointLight(0xffffff);
light.position.set(100, 250, 250);
scene.add(light);
},
Draw: function () {
var planeGeometry = new THREE.PlaneGeometry(localStorage.storWidth, localStorage.storLength, 10, 10);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0x888888,
side: THREE.DoubleSide
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
},
Update: function () {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(Main.Update);
}
}
function onWindowResize(event) {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
Main.Init();
This works just fine for using the orbitControl, while the mouse is over the part where the rendered materials are.
What I'm trying to do is, limit the Orbit control functionality to only be usable while the mouse is over the little green div that is overlaying the render scene. I've tried messing up with the parameters of the OrbitControl, tried adding onMouseOver functions on the javascript, associated with the div in the html, but nothing seems to work.
What I'm trying to do is even possible? If so, what am I missing?
Thanks in advance.
If I got you correctly, let's suppose, that you have a little green div
<div style="position: absolute;" id="LittleGreenDiv"></div>
Then you can use it as the second parameter when you create the object of controls:
var controls = new THREE.OrbitControls(camera, document.getElementById("LittleGreenDiv"));
jsfiddle example.

Three js in a class

I tried to set all the necessary functionality into one class in order to create a simple three.js scene with a cube. I don't get any errors, but the scene stays black when I open it in the browser.
Here is my code:
class SceneInit {
constructor(fov = 45,camera,scene,controls,renderer)
{
this.camera = camera;
this.scene = scene;
this.controls = controls;
this.renderer = renderer;
this.fov = fov;
}
initScene() {
this.camera = new THREE.PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 1, 1000);
this.camera.position.z = 15;
this.controls = new THREE.TrackballControls( this.camera );
//this.controls.addEventListener('change', this.renderScene);
this.scene = new THREE.Scene();
//specify a canvas which is already created in the HTML file and tagged by an id //aliasing enabled
this.renderer = new THREE.WebGLRenderer({canvas: document.getElementById('myThreeJsCanvas') , antialias: true});
this.renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(this.renderer.domElement);
//ambient light which is for the whole scene
let ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
ambientLight.castShadow = false;
this.scene.add(ambientLight);
//spot light which is illuminating the chart directly
let spotLight = new THREE.SpotLight(0xffffff, 0.55);
spotLight.castShadow = true;
spotLight.position.set(0,40,10);
this.scene.add(spotLight);
//if window resizes
window.addEventListener('resize', this.onWindowResize, false);
}
animate(){
requestAnimationFrame( this.animate.bind(this) );
this.render();
this.controls.update();
}
render(){
this.renderer.render( this.scene, this.camera );
}
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize( window.innerWidth, window.innerHeight );
}
}
And then I try to instantiate a new object and add an object to the scene. When I try to print the children of the scene, it returns me the right objects, but as I mentioned before the scene stays black. Only the renderer window is getting drawed in the browser.
let test = new SceneInit(45);
test.initScene();
test.animate();
let geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
let material = new THREE.MeshBasicMaterial();
let mesh = new THREE.Mesh( geometry, material );
test.scene.add(mesh);
console.log(test.scene.children); //returns 3 objects (ambientLight, spotLight, mesh)
I got the answer.
The problem in the code was that the BoxGeometry was too big and the camera was inside the box. With the clipping set to 1 it wouldn't even render it.
So the solution is to set a smaller BoxGeometry. or to move the camera away!

Categories

Resources