How to scale a camera? - three.js

I'm trying to make a 3D scene where you can walk around the world, but my objects currently look way too small, and my camera's perspective is like from a Godzilla's. I tried to scale the camera on XYZ axis, but the view got distorted, also FOV doesn't help too.
Is there a solution to this? The only option I could think of now is to scale all of the objects instead. The problem is, there are over 100 objects, and I would have to change their parameters individually.

You can scale the scene
scene.scale.x = scene.scale.y = scene.scale.z = 10;
Or add objects to a group and scale that group:
const group = new THREE.Group();
// I guess that you're using some kind of loop for adding your objects?
group.add(objectA);
group.add(ObjectB);
// scale the group
group.scale.x = group.scale.y = group.scale.z = 10;
scene.add(group);

Related

Change facing direction of CSS3DObject

I have a 3D scene with a bunch of CSS object that I want to rotate so that they are all pointing towards a point in the space.
My CSS objects are simple rectangles that are a lot wider than they are high:
var element = document.createElement('div');
element.innerHTML = "test";
element.style.width = "75px";
element.style.height = "10px";
var object = new THREE.CSS3DObject(element);
object.position.x = x;
object.position.y = y;
object.position.z = z;
Per default, the created objects are defined as if they are "facing" the z-axis. This means that if I use the lookAt() function, the objects will rotate so that the "test" text face the point.
My problem is that I would rather rotate so that the "right edge" of the div is pointing towards the desired point. I've tried fiddling with the up-vector, but I feel like that wont work because I still want the up-vector to point up. I also tried rotating the object Math.PI/2 along the y axis first, but lookAt() seems to ignore any prior set rotation.
It seems like I need to redefine the objects local z-vector instead, so that it runs along with the global x-vector. That way the objects "looking at"-direction would be to the right in the scene, and then lookAt() would orient it properly.
Sorry for probably mangling terminology, newbie 3D programmer here.
Object.lookAt( point ) will orient the object so that the object's internal positive z-axis points in the direction of the desired point.
If you want the object's internal positive x-axis to point in the direction of the desired point, you can use this pattern:
object.lookAt( point );
object.rotateY( - Math.PI / 2 );
three.js r.84

Dynamic change a lot of textures is very low performance

I am a newbie in Three js. In my project, I need draw a ground with a lot of texture. The ground has many layers, every layer has 4 textures and textures in different layers are different size. Below picture describe the ground:
Ground is one mesh has multiple material:
this.mesh = new THREE.Mesh(geometry, new THREE.MultiMaterial(materials));
Suppose I have a car it always at center of ground, in other word, center of all layers. When it move, the ground will translate to make sure the car always at center. So everytime ground translate, I need to update texture in new position.
The picture draw 3 layers for illustration, but in my project is 6 layers. So everytime all texture change, that means need to change 6 * 4 = 24 textures, and that cause low fps in my program.
This is my function to load texture from indexed DB every time a texture change:
Ground.prototype.loadTextureFromIndexedDB = function (url, materialIndex) {
var loader = new THREE.TextureLoader();
loader.crossOrigin = '';
loader.load(url,
function (texture) {
var groundMaterial = ground.mesh.material.materials[materialIndex];
groundMaterial.map.dispose();
groundMaterial.map = texture;
groundMaterial.map.anisotropy = ground.maxAnisotropy;
groundMaterial.map.minFilter = THREE.LinearFilter;
groundMaterial.map.needsUpdate = true;
img = null;
window.URL.revokeObjectURL(url);
});
}
I have tried many solutions. One of them is make a mesh with a BufferGeometry and MultiMaterial with array of ShaderMaterial. As what I known, it is the best for performance in THREE JS, isn't it? If it is then maybe THREE JS is not powerful as I thinked. Should I change to another API for my project?
Anyone suggest me any solution to make higher performance in my program? Thanks a lot!

THREE.raycaster : Possible to use it for enemy Ai?

I've just started learning THREE and have been messing about with the three.js example of controllable MD2 characters to try and fashion it into a 3rd person shooter kind of game. I've been trying to write a simple algorithm for the enemy characters and I'm pretty sure that ray-casting would be ideal.The whole idea is that the enemies should stop rotating once they're facing the player. But Here's the problem that's giving me sleepless nights! :
Let's say, the enemy object is the origin for the ray caster ray. No matter what direction I set for the direction of that ray ( even, for example (1,0,0) - the positive x-axis), the ray's direction is always pointing towards the center of the scene!!!
Please help! haven't been able to find any Example online for this kind of use for the ray caster (apart from collision detection which I really don't need at the moment).
If all you want is for enemies to stop rotating when they are looking at the player, I would consider just checking the direction between them, as it's a lot faster than casting a ray to see if it intersects:
// Assuming `enemy` is a THREE.Mesh
var targetDir = enemy.position.clone().sub(player.position).normalize();
var currentDir = (new THREE.Vector3()).applyMatrix4(enemy.matrixWorld).sub(enemy.position).normalize();
var amountToRotate = currentDir.sub(targetDir);
var offset = amountToRotate.length();
Then rotate each axis no more than the value for that axis in amountToRotate if offset is greater than some threshold.
That said, here is how you use a Raycaster, given the variables above:
var raycaster = new THREE.Raycaster(enemy.position, targetDir);
var intersections = raycaster.intersectObject(player);
Note that if you are running any of the above code in an animation loop, it will create a lot of garbage collection churn because you are constantly creating a bunch of new objects and then immediately throwing them away. A better pattern, which is used a lot in the library itself, is to initialize objects once, copy values to them if you need to, and then use those copies for computation. For example, you could create a function to do your raycasting for you like this:
var isEnemyLookingAtPlayer = (function() {
var raycaster = new THREE.Raycaster();
var pos = new THREE.Vector3();
return function(enemy) {
raycaster.ray.origin.copy(enemy.position);
raycaster.ray.direction.copy(pos.copy(enemy.position).sub(player.position).normalize());
return !!raycaster.intersectObject(player).length;
};
})();

Dynamic text or texture on curved object

I'm a newcomer to three.js and am looking for what approaches are possible to achieve an effect like this:
For a cola can like object as in the image below (minus condensation), I want to change independent bits of text on the surface of the can based on user interaction. The variants of text are fairly arbitrary, too many for pre-baked full can textures. For instance I might want to:
change "Euro 2012" to arbitrary text
change the nutritional stats on the back of the can
show or hide one of the individual music notes
I'm sure it's possible, just looking for what concepts I need to employ. Is it difficult to have multiple textures on the same object? Or to generate arbitrary text and position it on an object and wrap it to the shape of the object?
Any pointers helpful!
You can use image created in a separate canvas as a Three.js texture. Instead of trying to mix and blend multiple textures in Three.js (possible, but tricky and limited control), I think the best solution would be to create the dynamic texture in 2D, totally out of Three.js then just apply the full texture to the can.
You can create your canvas image manually or using canvas image manipulation library of your choice (some possibilities: https://docs.google.com/spreadsheet/ccc?key=0Aqj_mVmuz3Y8dHNhUVFDYlRaaXlyX0xYSTVnalV5ZlE#gid=0 ). Or you can have your template as SVG and modify that (should be quite simple), render that to canvas, then use it as texture.
Using canvas as a texture is very simple:
var canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
var context = canvas.getContext('2d');
// drawing something here....
context.font = "Bold 20px Helvetica";
context.lineWidth = 4;
context.strokeStyle = 'rgba(255,255,255,.8)';
context.fillStyle = "rgba(0,0,0,1)";
context.strokeText("Testing", 4, 22);
context.fillText("Testing", 4, 22);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

how to display a mesh in front of my camera in Three.Js?

i want to show a mesh (like gunshot) in front of my perspective camera(with first person controls) i wrote this code in the render function of my page:
var pos = camera.position;
var rot = camera.rotation;
shot.rotation.x = rot.x;
shot.rotation.y = rot.y;
shot.rotation.z = rot.z;
shot.position.x = pos.x;
shot.position.y= pos.y;
shot.position.z = pos.z + 500;
if i just change the position of my camera its good, but if i change the camera's rotation i don't see the shot in front of that.
how can i do this?
It would seem that you need to make the "shot" a child of the camera. It's not clear from your example whether you're doing that already, but this should make the shot move around with the camera properly.

Resources