Volume redering using Texture3D requires geometry.translate - three.js

I have a question regarding texture3D.
I am new to the 3D world. I was looking at volume rendering and came across this example https://github.com/mrdoob/three.js/blob/master/examples/webgl2_materials_texture3d.html
My question is about these three lines.
// line 119 - 122
// THREE.Mesh
const geometry = new THREE.BoxGeometry( volume.xLength, volume.yLength, volume.zLength );
geometry.translate( volume.xLength / 2 - 0.5, volume.yLength / 2 - 0.5, volume.zLength / 2 - 0.5 );
const mesh = new THREE.Mesh( geometry, material );
Why we need geometry.translate?
Suppose I change this example to use THREE.MeshBasicMaterial without the volume rendering just a static color, then I don't need any translation.
Can someone please explain why the geometry.translate?

When you create a box of width 1, the left is at -0.5, and the right is at +0.5. This translation was necessary to change its range from [-0.5, 0.5] => [0.0, 1.0]. This way it's easier to sample the 3D texture with the position coordinates, since texture-sampling always requires coordinates between 0 - 1.

Related

three.js make a cutting plane visible

In this demo:
https://threejs.org/examples/?q=clipping#webgl_clipping_advanced
if you enable the "visualize" option, you can see the 3d pyramid "cutting" the inside object.
Here:
https://threejs.org/examples/?q=clipping#webgl_clipping
there is a simple 2d plane cutting the object, but there is no such option to "see" the plane. I just started learning threejs and I am not too familiar with any 3d engine (other than fully understanding the math behind it), so I tried some basic stuff, e.g.:
localPlane.visible = true
But of course it didn't work. Any 'simple' way to make the second demo display the cutting plane?
Thank you
Here's some code to add the plane in the position you want:
const planeGeometry = new THREE.PlaneGeometry( 1.5, 1.5 );
const planeMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
const plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.position.copy(localPlane.normal);
plane.position.multiplyScalar(-localPlane.constant);
plane.quaternion.setFromUnitVectors(new THREE.Vector3(0, 0, 1), localPlane.normal);
plane.material.opacity = 0.5;
plane.material.transparent = true;
scene.add( plane );
And here's what that looks like...
However, depending on what you are implementing, you may find it easier to create a Plane Mesh in the position you want, and then derive the clipping plane THREE.Plane from that.
If you want to be able to move the clipping plane around, the reasoning involved in moving a Plane Mesh Object3D is probably more straightforward than reasoning about moving a THREE.Plane.
(update)
Another alternative approach I've come across: you could simply use the built in THREE.PlaneHelper, which can be used to visualize any THREE.Plane.
https://threejs.org/docs/#api/en/helpers/PlaneHelper
The sample code offered on that page is this:
const plane = new THREE.Plane( new THREE.Vector3( 1, 1, 0.2 ), 3 );
const helper = new THREE.PlaneHelper( plane, 1, 0xffff00 );
scene.add( helper );

Is there ANY way to have the three.js camera lookat being rendered off-center?

Is there a way to setup the Three.js renderer in such a way that the lookat point of the camera is not in the center of the rendered image?
To clarify: image a scene with just one 1x1x1m cube at ( 0, 0, 0 ). The camera is located at ( 0, 0, 10 ) and the lookat point is at the origin, coinciding with the center of the cube. If I render this scene as is, I might end up with something like this:
normal render
However I'd like to be able to render this scene in such a way that the lookat point is in the upper left corner, giving me something like this:
desired render
If the normal image is 800x600, then the result I envision would be as if I rendered a 1600x1200 image with the lookat in the center and then cropped that normal image so that only the lower right part remains.
Of course, I can change the lookat to make the cube go to the upper left corner, but then I view the cube under an angle, giving me an undesired result like this:
test.moobels.com/temp/cube_angle.jpg
I could also actually render the full 1600x1200 image and hide 3/4 of the image, but one would hope there is a more elegant solution. Does anybody know it?
If you want your perspective camera to have an off-center view, the pattern you need to use is:
camera = new THREE.PerspectiveCamera( for, aspect, near, far );
camera.setViewOffset( fullWidth, fullHeight, viewX, viewY, viewWidth, viewHeight );
See the docs: https://threejs.org/docs/#api/cameras/PerspectiveCamera
You can find examples of this usage in this example and this example.
three.js r.73
Here's a simple solution:
Assuming your cube is 4 x 4 x 4, at position 0, 0, 0:
var geometry = new THREE.BoxGeometry( 4, 4, 4 );
var material = new THREE.MeshBasicMaterial( { color: 0x777777 } );
var cube = new THREE.Mesh( geometry, material );
cube.position.set( 0, 0, 0 );
Get cube's position:
var Vx = cube.position.x,
Vy = cube.position.y,
Vz = cube.position.z;
Then deduct by 2 from x position, then add 2 to y and z position, and use the values to create a new Vector3:
var newVx = Vx - 2,
newVy = Vy + 2;
newVz = Vz + 2;
var xyz = new THREE.Vector3(newVx, newVy, newVz)
Then camera lookAt:
camera.lookAt(xyz);
Using console log, it would show that the camera is now looking at -2, 2, 2, which is the upper-left of your cube.
console.log(xyz);

Positioning Objects at the same Elevation

I have an issue with the position of cubes in my application. When I set them all with the same size they are rendered properly on the same Y position as I defined:
Example:
geometry = new THREE.BoxGeometry(50, 50, 50);
material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(100, 0, 400); // I always set y as 0 because I want the cubes to be on the same level like buildings in a city
And I do the same for the next cubes, only changing the X and Z positions.
However, when I create cubes with different sizes, which is my objective, as follows,
geometry = new THREE.BoxGeometry(50, 100, 50);
they appear on a different level in the final visualization on the browser, as shows the image:
https://cloud.githubusercontent.com/assets/3678443/8651664/35574c18-2972-11e5-8c75-2612733ea595.png
Any ideas on how to solve this problem? What am I doing wrong?
BoxGeometry is centered on the origin. There are two solutions to translating the box so it sits on the XZ-plane.
Option 1. Translate the geometry so the bottom face of the box passes through the origin. You do that by translating the geometry up by half its height.
geometry = new THREE.BoxGeometry( 50, 50, 50 );
geometry.translate( 0, 50 / 2, 0 );
mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 100, 0, 400 );
Option 2. Translate the mesh by setting its position.
geometry = new THREE.BoxGeometry( 50, 50, 50 );
mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 100, 50 / 2, 400 );
The first option is likely preferable for your use case.
three.js r.92
The Position of the Objects is correct, they are placed where their centerĀ“s are. So your cube with 100 height in geometry extends 50 to the top and 50 to the bottom, its centroid is right in its "middle" at 0.
You could set the y positions of your Cubes to y + cube.geometry.parameters.height / 2 so every cube is aligned at one level (variable y).

Three.js How to create a simple 3d Point

I want to create some simple 3D points.
Is there any way to create this geometry without tricks?
- I don't need a pointcloud ( or do I need ? )
- I don't want a sprite ( I don't want to load any image).
Maybe I'm some clumsy but I don't see the way.
Any idea & advise ? Thanks.
You maybe want to use a simple sphere geometry with a small radius for your project.
var pointGeometry = new THREE.SphereGeometry( 2, 16, 16 ), // adjust the first value for the 'point' radius
pointMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00} ), // adjust the color of your 'point'
point3D = new THREE.Mesh( pointGeometry, pointMaterial );
scene.add( point3D );
Important side notice: the radius of the sphere and the size it takes on your screen depends on the distance from the camera and the camera.['far'] value, you set while initiating.

Non-radial texture mapping over a ring geometry in WebGL using Three.js

I am trying to simulate image deformation effects using textures over 2D geomtries using the ThreeJS library. I want to apply a texture image over a hollow circle (basically, a ring built by the THREE.RingGeometry function) and obtain the results shown at this image:
Following I show the results I am obtaining in my scene both for the solid ring and its wireframed version:
The problem is that, as you see, the texture is been applied in a radial way, from the center of the ring to the outside. However, what I really need is to apply the texture image on a concentric circle way, as shown in the first image of this question.
The idea is to produce a deformed version of the original texture over a ring shape. I would like to know how this effect can be programmatically achieved through Three.js in such a way that the destination shape can be any arbitrary 2D geometry .
Following, there is the relevant code I am using to draw my scene:
var texture = THREE.ImageUtils.loadTexture('./images/texture.png');
var wireRing = new THREE.Mesh(new THREE.RingGeometry(10, 20, 50, 5, 0, Math.PI * 2), new THREE.MeshBasicMaterial({map: texture, wireframe: true}));
wireRing.position.set(-25, 50, 0);
scene.add(wireRing);
var ring = new THREE.Mesh(new THREE.RingGeometry(10, 20, 50, 5, 0, Math.PI * 2), new THREE.MeshBasicMaterial({map: texture}));
ring.position.set(25, 50, 0);
scene.add(ring);
You just need to change the UV mapping in RingGeometry like so:
uvs.push( new THREE.Vector2( o / thetaSegments, i / phiSegments ) );
Also, if you want to rotate the texture around the ring, you instantiate the RingGeometry by varying the thetaStart parameter:
var geometry = new THREE.RingGeometry( 10, 20, 50, 5, thetaStart, Math.PI * 2 );
three.js r.67

Resources