I am trying to create a simple 3d game with three.js. I am trying to create coloured cubes, but all the cubes just stay the same color.
When I create a cube I do:
var geometry = new THREE.BoxGeometry(width, height, length);
var material = new THREE.MeshNormalMaterial({color: hexColor});
var cube = new THREE.Mesh(geometry, material);
(which is inside a function)
Then I use the function twice,
hexColor being 0x0000ff(blue) and 0xff0000(red).
The cubes do generate, but all the faces of the cubes are different colours.
I have also tried
cube.material.color.setHex();
But it gives out Uncaught TypeError: Cannot read property 'setHex' of undefined
Help please!!
your issue is that THREE.MeshNormalMaterial() doesn't have a color property. Try using THREE.MeshBasicMaterial({ color: yourHexColor }); instead.
If you do that, your cube.material.color.setHex(yourHexColor); call should work just fine.
You can find all of the necessary information on the Three.js docs page and, if you're interested, take a look at the dedicated examples page.
Related
i have a short question:
I know how to calculate the boxes of my (imported) 3dobjects f.e.
var box = new THREE.Box3().setFromObject(obj);
With this i can compute boxes for my objects and i can merge them together if i want.
The problem is, now i have these 2 objects https://imgur.com/gallery/NbPwcmB
The solution seems quite simple: i need to compute the left and right spherebox and put them together, but both of these 2 objects are imported with stlloader. I'm not sure how stlloader exactly works, (it seems for me like its all 1 huge mesh) so i'm not even sure if this is possible.
so my questions:
1. how can i compute a box with the shape of a sphere of my sphere object.
2. Is this even possible for my stl object? (I will try when i get the answer for question 1)
Edit: Question 1 should somehow be working with .computeBoundingSphere..
is there a way to make this visible?
how can i compute a box with the shape of a sphere of my sphere object.
Well, in three.js you have the choice between two bounding volumes. THREE.Box3 represents an axis-aligned bounding box (AABB) whereas THREE.Sphere represents a bounding sphere. If you need a box with the shape of a sphere, use THREE.Sphere.
Is this even possible for my stl object?
The method setFromObject() does only exist for THREE.Box3. However, you can compute the bounding sphere via THREE.BufferGeometry.computeBoundingSphere(). This sphere is defined in local space, however. You can use THREE.Sphere.applyMatrix4() to transform it into world space by passing in the world matrix of the 3D object.
is there a way to make this visible?
There is no helper class for bounding spheres. But you can easily create a helper mesh based on THREE.SphereBufferGeometry. Something like:
const geometry = new THREE.SphereBufferGeometry( boundingSphere.radius );
const material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
const mesh = new THREE.Mesh( geometry, material );
mesh.position.copy( boundingSphere.center );
scene.add( mesh );
three.js R109
I would like to build a parallax effect from a 2D image using a depth map, similar to this, or this but using three.js.
Question is, where should I start with? Using just a PlaneGeometry with a MeshStandardMaterial renders my 2D image without parallax occlusion. Once I add my depth map as displacementMap property I can see some sort of displacement, but it is very low-res. (Maybe, since displacement maps are not meant to be used for this?)
My first attempt
import * as THREE from "three";
import image from "./Resources/Images/image.jpg";
import depth from "./Resources/Images/depth.jpg";
[...]
const geometry = new THREE.PlaneGeometry(200, 200, 10, 10);
const material = new THREE.MeshStandardMaterial();
const spriteMap = new THREE.TextureLoader().load(image);
const depthMap = new THREE.TextureLoader().load(depth);
material.map = spriteMap;
material.displacementMap = depthMap;
material.displacementScale = 20;
const plane = new THREE.Mesh(geometry, material);
Or should I use a Sprite object, which face always points to the camera? But how to apply the depth map to it then?
I've set up a codesandbox with what I've got so far. It also contains event listener for mouse movement and rotates the camera on movement as it is work in progress.
Update 1
So I figured out, that I seem to need a custom ShaderMaterial for this. After looking at pixijs's implementation I've found out, that it is based on a custom shader.
Since I have access to the source, all I need to do is rewrite it to be compatible with threejs. But the big question is: HOW
Would be awesome if someone could point me into the right direction, thanks!
Introduction:
I render an isometric map with Three.JS (v95, WebGL Renderer). The map includes many different graphic tilesets. I get the specific tile via a TextureAtlasLoader and it’s position from a JSON. It looks like this:
The problem is that it performs really slow the more tiles I render (I need to render about 120’000 tiles on one map). I can barely move the camera then. I know there are several better approaches than adding every single tile as sprite to the scene. But I’m stuck somehow.
Current extract from the code to create the tiles (it’s in a loop):
var ts_tile = Map.Imagesets[ims].Map.getTexture((bg_left / tw), (bg_top / th));
var material = new THREE.SpriteMaterial({ map: ts_tile, color: 0xffffff, fog: false });
var sprite = new THREE.Sprite(material);
sprite.position.set(pos_left, -top, 0);
sprite.scale.set(tw, th, 1);
scene.add(sprite)
I also tried to render it as a Mesh, which also works, but the performance is the same (of course):
var material = new THREE.MeshBasicMaterial({ map: ts_tile, color: 0xffffff, transparent: true, depthWrite: false });
var geo = new THREE.PlaneGeometry(1, 1, 1);
var sprite = new THREE.Mesh(new THREE.BufferGeometry().fromGeometry(geo), material);
possible solutions in the web:
I know that I can’t add so many sprites or meshes to a scene and I have tried different things and looked at examples, where it works flawless, but I can’t adapt their approaches to my code. Every tile on my map has a different texture and has it’s own position.
There is an example in the official three.js docs: They work with PointsMaterial and Points. In the end they only add 5 Points to the scene, which includes about 10000 “vertices / Images”. docs: https://threejs.org/examples/#webgl_points_sprites
Another approach can be found here on github: https://github.com/YaleDHLab/pix-plot
They create 5 meshes, every mesh includes around 4096 “tiles”, which they build up with Faces, Vertices, etc.
Final question:
My question is, how can I render my map more performant? I’m simply overchallenged by changing my code into one of the possible solutions.
I think Sergiu Paraschiv is on the right track. Try to split your rendering into chunks. This strategy and others are outlined here: Tilemap Performance. Depending on how dynamic your terrain is, these chunks could be bigger or smaller. This way you only have to re-render chunks that have changed. Assuming your terrain doesn't change, you can render the whole terrain to a texture and then you only have to render a single texture per frame, rather than a huge array of them. Take a look at this tutorial on rendering to a texture, it should give you an idea on where to start with rendering your chunks.
I am trying to create a simple 3D shapes of 3 buildings, assuming I start with the outlines (where I have the X and Y for each line start/end) and then extrude them.
Google did not help me, so I kindly ask you to take a look if you can.
I am attaching the lines as an image (just for info).
How can I then make a little dat.GUI switch to turn the shapes on/off (I am not sure how to connect the geometry with the gui).
Thank you!
A THREE.Mesh is a subclass of THREE.Object3d which defines the property visible, if you don't want to render a mesh just set the property visible to false through an instance of dat.gui
var cube = new THREE.Mesh(geometry, material)
scene.add(cube)
var dat = new dat.GUI()
dat.add(cube, 'visible')
demo
I have two object in threejs. And I would like them to share the value of scale vector
mesh1 = new THREE.Mesh(geometry, material);
mesh1.scale.x = 0.47;
mesh2 = new THREE.Mesh(geometry, material);
mesh2.scale=mesh1.scale; // This does not work
The last line has no effect. The documentation does not state that the scale property is readonly. I've taken a look at the source and found that that property is not defined as writable. Is there a bug in documentation or is this the way threejs works and there is no point in documenting it :-) ?
Is it possible to share scale (and other vector) between different meshes? Is the only way to do it by copying the values
mesh2.scale.copy(mesh1.scale); // Copy the vector over
UPDATE: This seemed to work in old versions of threejs - such as the one used in the following example. Was this functionality disabled on purpose?
Object3D's position, rotation, quaternion and scale properties are immutable.
See the source code file Object3D.js.
For example, you can no longer use the following pattern:
object.scale = vector;
Instead, you must use either
object.scale.set( x, y, z );
or
object.scale.copy( vector );
Similarly for the other properties mentioned.
three.js r.72