Attach text above 3D Object - three.js

I'm wondering if it is possible to attach a text above a 3D Object?
If so, how would I do it?
So far I'm doing the following below to load a mesh with its material and lastly adding it to a THREE.Object3D(); and adding it to the scene. Works great without any problems.
Next step is I want to show a nice text above its this object that is always fixed and can be seen from every angle.
loader.load('assets/' + enemyUrl, function (geometry, materials) {
material = new THREE.MeshFaceMaterial( materials );
model = new THREE.SkinnedMesh( geometry, material );
var mats = model.material.materials;
for (var i = 0,length = mats.length; i < length; i++) {
var m = mats[i];
m.skinning = true;
}
ensureLoop(geometry.animations[0]);
function ensureLoop( tmp ) {
for ( var i = 0; i < tmp.hierarchy.length; i ++ ) {
var bone = tmp.hierarchy[ i ];
var first = bone.keys[ 0 ];
var last = bone.keys[ bone.keys.length - 1 ];
last.pos = first.pos;
last.rot = first.rot;
last.scl = first.scl;
}
}
model.scale.set(2.5,2.5,2.5);
// TODO: Randomize where to put it in the world
yawObject.position.y = spawnPosition.y;
yawObject.position.x = spawnPosition.x;
yawObject.position.z = spawnPosition.z;
yawObject.add(model);
scene.add(yawObject);
});
Something like this:
This is what my game looks like now:

sure its possible. you can create a canvas with text on it, which you use as a texture on a plane that always looks at the camera, you could also do it with a single particle, but im not quite sure how it would work since particle materials have a size parameter. something like:
var name = 'Rovdjuret';
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
ctx.font="20px Georgia";
ctx.fillText(name,10,50);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true; //just to make sure it's all up to date.
var label = new THREE.Mesh(new THREE.PlaneGeometry, new THREE.MeshBasicMaterial({map:texture}));
and inside the render/animation loop you make all the labels look at the camera:
label.lookAt(camera.position);

Related

THREE.js planeGeometry clipped inside the walls

I want to make a 3D building using Three.js. For example, I made 6 walls and a floor by checkerboard texture. I used clippingPlanes for wall1 and wall4:
floor1.material.clippingPlanes = [plane1,plane4];
I made my planes(plane1 and plane4) by my walls(wall1 and wall4). For example, my wall4 planeGeometry and plane4 code is here:
var wallGeometry4 = new THREE.PlaneGeometry(40, Floor_Height, 1, 1);
var wall4 = createMesh(wallGeometry4, "brick_diffuse.jpg", THREE.DoubleSide, 1024, 1024);
unit1.add(wall4);
wall4.position.x = -10;
wall4.position.y = 0;
wall4.position.z = -20;
wall4.rotation.y = 1.5 * Math.PI;
wall4.add(new THREE.EdgesHelper(wall4, 0x000000));
var plane4 = new THREE.Plane();
var normal4 = new THREE.Vector3();
var point4 = new THREE.Vector3();
normal4.set(0, 0, -1).applyQuaternion(wall4.quaternion);
point4.copy(wall4.position);
plane4.setFromNormalAndCoplanarPoint(normal4, point4);
But I see an empty area between wall5 and wall6, because plane4(that used for clipping the floor) isn't the same size of wall4. I think Plane4 is whole of the scene. How to change size of my plane to clip correctly? Or Is there any way to make floor bounded in walls?
One way to achieve this as suggested is to use ShapeGeometry.
When you are creating your walls you can save the x and z co-ordinate of their starting and ending points in an array to form a loop of points of Vector2. Then you can create a new custom shape from these points using shapeGeometry.
points = [{x:0,y:0},{x:0,y:10},{x:10,y:10},{x:10,y:0},{x:0,y:0}]
function getShapeFromPoints(points){
const shape = new THREE.Shape();
shape.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i++) {
shape.lineTo(points[i].x, points[i].y);
}
return shape;
}
function createPlaneFromPoints(points) {
const planeMaterial = getPlaneMaterial();
const shape = getShapeFromPoints(points);
const geometry = new THREE.ShapeBufferGeometry(shape);
geometry.rotateX(degreeToRadians(-90));
const mesh = new THREE.Mesh(geometry, planeMaterial);
return mesh;
}
Hope that helps you!

Animating Three.js vertices

I'm trying to animate individual vertices from a collada model.
The vertices ARE animating fine once but then they don't animate anymore.
1: Load my collada
// name obj
var orgVerts = false;
var desVerts = false;
var material = new THREE.MeshBasicMaterial({ color:0x1e5679, wireframe:true });
var loader = new THREE.ColladaLoader();
var nameModel = false;
loader.options.convertUpAxis = true;
loader.load( '3d/name.dae', function ( collada ) {
nameModel = collada.scene.children[0].children[0];
nameModel.material = material;
nameModel.geometry.dynamic = true;
nameModel.position.set(0,0,0);//x,z,y- if you think in blender dimensions ;)
nameModel.scale.x = .0035;
nameModel.scale.y = .0035;
nameModel.scale.z = .0035;
scene.add(nameModel);
orgVerts = nameModel.geometry.vertices; // make a backup of all verts
genVerts(); // create a new array of random verts
});
2: in my render function
var render = function () {
requestAnimationFrame(render);
// do stuff
if(nameModel){
if(window.globalCurrentSlide != 0){
for(var r=0; r < nameModel.geometry.vertices.length; r++){
var vert = desVerts[r]; // loop through all the destination verts
nameModel.geometry.vertices[r].x = nameModel.geometry.vertices[r].x - (nameModel.geometry.vertices[r].x - vert.x)/20;
nameModel.geometry.vertices[r].y = nameModel.geometry.vertices[r].y - (nameModel.geometry.vertices[r].y - vert.y)/20;
nameModel.geometry.vertices[r].z = nameModel.geometry.vertices[r].z - (nameModel.geometry.vertices[r].z - vert.z)/20;
}
}else{
for(var t=0; t < nameModel.geometry.vertices.length; t++){
var vert2 = orgVerts[t]; // loop through all the original verts
nameModel.geometry.vertices[t].x = nameModel.geometry.vertices[t].x - (nameModel.geometry.vertices[t].x - vert2.x)/20;
nameModel.geometry.vertices[t].y = nameModel.geometry.vertices[t].y - (nameModel.geometry.vertices[t].y - vert2.y)/20;
nameModel.geometry.vertices[t].z = nameModel.geometry.vertices[t].z - (nameModel.geometry.vertices[t].z - vert2.z)/20;
}
}
nameModel.geometry.verticesNeedUpdate = true;
nameModel.rotation.y += .005;
}
renderer.render( scene, camera );
}
window.globalCurrentSlide is set to 0 to start with and everything is fine. if I change window.globalCurrentSlide to 1, all the vertices animate correctly... BUT when I change window.globalCurrentSlide back to 0 the vertices don't animate back to their original positions. I've debugged heaps and can 100% say that BOTH desVerts and orgVerts don't change and they are correct. Any ideas? It's driving me nuts.
PS: I know the code could be condensed, I'm just playing ATM
The answer was that my orgVerts was just a reference NOT a clone. use:
var geometry = nameModel.geometry.clone();
orgVerts = geometry.vertices;

threejs moving one object moves the second too

I'm new at three.js and i need to load a particle object
it seems to work if add particles on vertices
if i load my Json once and inside the load() i build 2 different THREE.Points when i mov the first the second also move if i use 2 different load calls and inside each i build a THREE.Points object each object can be move separately
this i the function that i call inside animate
function animateParticles( particleSystem, particleSystemOriginal, deltaTime ) {
var vertsOriginal = particleSystemOriginal.geometry.vertices;
var verts = particleSystem.geometry.vertices;
for(var i = 0; i < verts.length; i++) {
var vertOriginal = vertsOriginal[i]; // original position
var vert = verts[i]; // cloud position
var vertOriginalY = vertOriginal.y;
var vertY = vert.y;
if (i==1) console.log("vertOriginalY " + vertOriginalY + " vertY " + vertY);
vert.y = vertY - (10 * deltaTime); // move
}
particleSystemOriginal.geometry.verticesNeedUpdate = true;
particleSystem.geometry.verticesNeedUpdate = true;
}
it seems strange that i need to load twice the same object to move one of them
in my function i'just testing and moving dove the cloud but what i would like is to shake particles, so i need to know particles original position and set particles new position
EDIT 1
i load my model like this
var loader = new THREE.JSONLoader();
loader.load('../3d-models/creati/mymodel-001.json', function(geometry, materials) {
var material = new THREE.MeshNormalMaterial();
var particleModelOriginal = new THREE.Mesh( geometry, material );
var particleModel = particleModelOriginal.clone();
/* build particle THREE.Points */
particleSystemOriginal = new THREE.Points(particlesOriginal, particleMaterial);
particleSystem = new THREE.Points(particles, particleMaterial);
//particleSystem = particleSystemOriginal.clone();
});
If I understand the question correctly, you probably need to use the .clone() object on mesh/geometry that you are loading if you want to create multiple objects. Otherwise they are referencing the same object, and will both be modified if one of them are modified

Collision Detection - Character not falling of platform correct

I am making a platform game with movement in x and y axis. Im using the collision detction from https://stemkoski.github.io/Three.js/Collision-Detection.html, works great and all. Just that Im having a small problem that I do not understand how to solve. Did the reasearch and found nothing that helped me with the problem (probably because I dont get how it works).
To the problem: When Im moving my character left and right I want the character fall down where the ledge is, works on the left side. But on the right side the character starts to fall before where the ledge is picture.
This is how my code looks like now:
function animate() {
requestAnimationFrame( animate );
var originPoint = user.position.clone();
for (var i = 0; i < user.geometry.vertices.length; i++) {
var localVertex = user.geometry.vertices[i].clone();
var globalVertex = localVertex.applyMatrix4(user.matrixWorld);
var directionVector = globalVertex.sub(user.position);
var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
var collisionResult = ray.intersectObjects(objectArray);
if (collisionResult.length > 0 && collisionResult[0].distance < directionVector.length()){
inAir = false;
}
else inAir = true;
};
var userGeometry = new THREE.PlaneGeometry( 50, 100, 10 );
var userMaterial = new THREE.MeshBasicMaterial( {
color: "red"
} );
var user = new THREE.Mesh( userGeometry, userMaterial );
scene.add(user);

geometry.materials[0][0].shading: Three JS property 0 is undefined

I would like to add some shading to my 3D model in Three JS.
I'm using this code:
var loader = new THREE.JSONLoader();
loader.load("peer.js", createScene);
function createScene( geometry ) {
geometry.materials[0][0].shading = THREE.FlatShading;
geometry.materials[0][0].morphTargets = true;
var material = new THREE.MeshFaceMaterial();
//var material = new THREE.MeshLambertMaterial({color: 0|(0xffffff*Math.random())})
var cube = new THREE.Mesh( geometry, material );
cube.scale.set(50, 50, 50);
cube.position.z = -50;
m.model.matrixAutoUpdate = false;
m.model.add(cube);
scene.add(m.model);
}
And I'm getting the error message 'Cannot read propery 0 of undefined'.
It has something to do wit this line: geometry.materials[0][0].shading = THREE.FlatShading;
And I think the [0][0] has to be changed in something else, only I don't know what because I don't know what [0][0] is standing for. Does someone know how to fix this problem?

Resources