Threejs - Reflectivitybitmap does not work on MeshLambertMaterial - javascript

what works:
I am using threejs revision 73.
I want to render a tool with the WebGLRenderer.
The tool consists of 3 Meshes. Each mesh consists of a BufferGeometry and a MeshLambertMaterial:
var geometry = new THREE.BufferGeometry();
var material = new THREE.MeshLambertMaterial();
var mesh = new THREE.Mesh(geometry, material);
The result looks like the following:
what I want to archive:
Now I want to make the tool look more realistic by applying a Texture ("img/tablereflection.bmp", grayscale 256x256px, bmp). I am unsure what is the best approach if I want this texture to affect my reflectivity behavior.
What I do, is:
var geometry = new THREE.BufferGeometry();
var material = new THREE.MeshLambertMaterial({
map: new THREE.TextureLoader().load("img/tablereflection.bmp")
});
var mesh = new THREE.Mesh(geometry, material);
But the result looks like that:
That is not what I want to have. It should look like:
Can someone tell me please, what I might be missing?
Edits
My light function is
function initLight(scene, camera) {
var ambientLight = new THREE.AmbientLight(0x555555);
scene.add(ambientLight);
var leftLight = new THREE.PointLight(0x888888, 0.7, 0);
leftLight.position.set(-2, 5, 2);
camera.add(leftLight);
var rightLight = new THREE.PointLight(0x888888, 0.7, 0);
rightLight.position.set(2, 5, 2);
camera.add(rightLight);
}
I've already tried to use The material browser for MeshLambertMaterial and possibly was able to archieve what I wanted as you can see here using these settings , but as you can see the Type is now empty and so I am not sure what happens behind the scene. Where is the error? Im glad for any hints.

Related

Get geometry and material of 3D Model - Three.js

I am attempting to make one 3D model orbit another, but as soon as I change my mesh from a wireframe box to a 3D Model's geometry it disappears.
//this is inside a GLTFLoader.load (glftLoader.load('<model path>', (gltfScene) => {)
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial( {
color: 0xffffff,
wireframe: true
});
let pivot = new THREE.Object3D()
pivot.rotation.z = 0;
gltfScene.scene.add(pivot);
//let mesh = new THREE.Mesh(geometry, material); WORKING LINE
let mesh = new THREE.Mesh(gltfScene.scene.geometry, gltfScene.scene.material);
mesh.position.y = 2;
pivot.add(mesh);
What am I doing wrong? I get no errors, I have a feeling it may be to do with the scale of the 3D model but I'm unsure. Am I getting the geometry and material properties correctly?
let mesh = new THREE.Mesh(gltfScene.scene.geometry, gltfScene.scene.material);
I suppose this line breaks your code since gltfScene.scene (the result of GLTFLoader's onLoad() callback) is an instance of THREE.Group which has no material or geometry property.
A glTF asset can hold more than one mesh so if you really want to extract the geometries and materials from it, you have to traverse through gltfScene.scene and process all meshes.

Something like "object-fit: cover" for CylinderGeometry three.js when using THREE.VideoTexture();

I would really like to have something like this:
Where the checkered background is the texture, and the jar is a cylinder with the texture on it like so.
I really don't know too much about three.js, so I am not sure about exactly what information I have to give. I am using THREE.OrthographicCamera, if that helps! Also, I have to use THREE.VideoTexture() for this.
What I Originally Did:
var material = THREE.MeshBasicMaterial({
//material-related stuff here
map: new THREE.VideoTexture(video)
});
What I Got:
What I want(With a cylinder instead of a sphere):
What's wrong with just applying the texture to the .map material property?
var geom = new THREE.CylinderGeometry(5, 5, 20, 32);
var mat = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load( "textures/checkered.jpg" )
});
var mesh = new THREE.Mesh(geom, mat);

Creating BoxBufferGeometry from Box3

I want to create a box mesh on the three.js scene, where points of the box mesh will be the same as bounding box of some existing object on the scene.
I have tried to create box mesh from box3 in the way displayed bellow, but i dont get the right result:
var threeObject = existing object on the scene;
var boundingBox = new THREE.Box3();
boundingBox.setFromObject(threeObject);
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
boundingBox.min.x, boundingBox.min.y, boundingBox.min.z,
boundingBox.min.x, boundingBox.max.y, boundingBox.min.z,
boundingBox.min.x, boundingBox.min.y, boundingBox.max.z,
boundingBox.min.x, boundingBox.max.y, boundingBox.max.z,
boundingBox.max.x, boundingBox.min.y, boundingBox.min.z,
boundingBox.max.x, boundingBox.max.y, boundingBox.min.z,
boundingBox.max.x, boundingBox.min.y, boundingBox.max.z,
boundingBox.max.x, boundingBox.max.y, boundingBox.max.z,
] );
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var mesh = new THREE.Mesh( geometry, material );
viewer.scene.add(mesh);
How can I create mesh box from box3? Thank you very much for your help!
In Three.js there's no automatic way to turn Box3 into a regular BoxBufferGeometry but here's how it worked for me
const threeObject = existing object on the scene;
const box3 = new THREE.Box3();
// conform to the object size like it's a boundingBox
box3.setFromObject(threeObject);
// make a BoxBufferGeometry of the same size as Box3
const dimensions = new THREE.Vector3().subVectors( box3.max, box3.min );
const boxGeo = new THREE.BoxBufferGeometry(dimensions.x, dimensions.y, dimensions.z);
// move new mesh center so it's aligned with the original object
const matrix = new THREE.Matrix4().setPosition(dimensions.addVectors(box3.min, box3.max).multiplyScalar( 0.5 ));
boxGeo.applyMatrix(matrix);
// make a mesh
const mesh = new THREE.Mesh(boxGeo, new THREE.MeshBasicMaterial( { color: 0xffcc55 } ));
The vertices array in your code holds vertex data but they actually represent face/triangle definitions. Hence, rendering just this geometry data results in a few random triangles (not visualizing a box).
You can solve this problem by adding an index to your geometry which will represent the face definitions based on your vertices. To understand this topic, you have to know the difference between indexed and non-indexed geometries. I suggest you study the official documentation page of THREE.BufferGeometry. There are for each type of geometry official code examples.
three.js R107

Two canvases as textures for plane in three.js

I would like to render two canvases as textures on a plane in three.js. I created an array with two MeshBasicMaterial and did the following
texture2 = new THREE.Texture(c1);
texture3 = new THREE.Texture(c3);
var mat1 = new THREE.MeshBasicMaterial({ map: texture2 });
var mat2 = new THREE.MeshBasicMaterial({ map: texture3 });
materials.push(mat1);
materials.push(mat2);
mesh2 = new THREE.Mesh(geometry2, new THREE.MeshFaceMaterial( materials ));
scene2.add(mesh2);
renderer2 = new THREE.WebGLRenderer({canvas:c2});
renderer2.setSize(c2.width, c2.height);
document.body.appendChild(renderer2.domElement);
I created this jsfiddle example to show my actual problem. The second texture isn't rendered on canvas2, but I want to show both textures on it.
Reason
The reason why the second texture is not rendered is because it doesn't know which faces to assign the first or second material to, so by default it gives the first material to all of them.
Solution
Update Three.js to latest build (r76). You're are now running r54
Loop through all faces and assign them a materialIndex(Face3)
Use THREE.MultiMaterial instead of THREE.MeshFaceMaterial:
mesh2 = new THREE.Mesh(geometry2, new THREE.MultiMaterial( materials ));

three.js - Get all objects(meshes) in the area (3d cube)

I have a system of tubes. More precisely, I create a tubes from this code
tube_color - obviously, color of tube,
spline_points - huge number of THREE.Vector3 objects,
segments, radiusSegments are just numbers
var material = new THREE.MeshLambertMaterial( { color: tube_color, shading: THREE.SmoothShading } );
var spline = new THREE.SplineCurve3(spline_points);
var tube = new THREE.TubeGeometry(spline, segments, 10, radiusSegments, false, false);
var tubeMesh = new THREE.Mesh(tube, material);
scene.add(tubeMesh);
This code creates one particular mesh object in space. For each mesh I can have an array of Vector3's by using myMesh.geometry.vertices.
The problem is: I have the point in 3d space. Around this point I create Cube, which does intersect with tubes. For example, this cube can be created like this
var cube = new THREE.CubeGeometry(xSize,ySize,zSize, 5, 5, 5);
var material = new THREE.MeshBasicMaterial({
color: 0xff0000,
opacity: 1,
wireframe: true,
transparent: false
});
var selectionMesh = new THREE.Mesh(cube, material);
scene.add(selectionMesh);
Is it possible at least to find objects(meshes) that have intersection with by cubic area? I know that in scene object I have all meshes, and I can iterate over them, get vertices, iterate over them with a condition if there is at least one its point is in cubic area. But I believe... I hope there is a method/algorithm/magic much more simple then this...
As #WestLangley recommended the solution of this problem was to build octree.
octree=new THREE.Octree({
undeferred:false,
depthMax:Infinity,
objectsThreshold:8,
overlapPct:0.15
} );
and search it
var meshesSearch=octree.search( rayCaster.ray.origin, radiusSphere, true, rayCaster.ray.direction );
However, to have specific intersection we need to provide the recursive flag
raycaster.intersectOctreeObjects( objects, true )
I ended up with more complicated processing of my specific case however this was enough to solve the problem at that moment.

Categories

Resources