In three.js if I use the wireframe helper or individually add a line representing the edge at the intersection of two faces the line is visible from one side of the intersection but not visible from the other side.
I would expect the wireframe line to be visible from both sides. Any idea how to make it?
var wireframe = new THREE.LineSegments(new THREE.WireframeGeometry(geometry));
wireframe.material.depthTest = false;
wireframe.material.opacity = 0.25;
wireframe.material.transparent = true;
Related
I want to check whether a point is inside a mesh or not. To do so, I use a raycaster, set it to the point's origin and if the ray intersects the mesh only once, it must be inside. Unfortunately, the intersectObject always returns no intersection, even in cases I know that the point is located inside the mesh.
The point's origin is given in world coordinates and the mesh's matrixWorld is up to date too. Also, I set the mesh.material.side to THREE.DoubleSide, so that the intersection from inside should be detected. I tried setting the recursive attribute to true as well, but as expected, this didn't have any effect (since the mesh is a box geometry). The mesh is coming from the Autodesk Forge viewer interface.
Here is my code:
mesh.material.side = THREE.DoubleSide;
const raycaster = new THREE.Raycaster();
let vertex = new THREE.Vector3();
vertex.fromArray(positions, positionIndex);
vertex.applyMatrix4(matrixWorld);
const rayDirection = new THREE.Vector3(1, 1, 1).normalize();
raycaster.set(vertex, rayDirection);
const intersects = raycaster.intersectObject(mesh);
if (intersects.length % 2 === 1) {
isPointInside = true;
}
The vertex looks like this (and it obviosly lies inside of the bounding box):
The mesh is a box shaped room with the following bounding box:
The mesh looks like this:
The geometry of the mesh holds the vertices in the vb. After applying the world matrix, the mesh vertices are correct in world space. Here is a part of the vb list:
Why does the raycaster not return any intersection? Is the matrixWorld of the mesh taken into account when computing the intersections?
Thanks for any kind of help!
Note that Forge Viewer is based on three.js version R71, and it had to modify/reimplement some parts of the library to handle large and complex models (especially architecture and infrastructure designs), so THREE.Mesh objects might have a slightly different structure. In that case I'd suggest to raycast using Forge Viewer's own mechanisms, e.g., using viewer.impl.rayIntersect(ray, ignoreTransparent, dbIds, modelIds, intersections);.
In my program, I am trying to make bounding box around a point cloud. I have calculated the opposite vertices for this purpose.
Here, documentation for BoxGeomtery is available. But I am not able to understand the constructor. Constructor takes width,height, depth as inputs. But what about location of the box. Where in the scene would this box be created?I want bounding box to be defined by two vertices I have.
Edit:
var geometry = new THREE.Box3(mn,mx);
var material = new THREE.MeshBasicMaterial({color: 0xfffff, wireframe: true});
var bBox = new THREE.Mesh(geometry, material);
scene.add(bBox);
mn,mx are vertices of the box.
Above code gives error as:
Uncaught TypeError: object.geometry.addEventListener is not a function
BoxGeomtery is a geometry generator. What you are looking for is Box3, three.js's AABB implementation. You can use Box3.setFromObject to generate a bounding box for a 3D object.
const aabb = new THREE.Box3().setFromObject( points );
You can then use Box3.getCenter to retrieve the center of the box.
I've managed to set the colour of a mesh face using:
geometry.faces[i].color.setHex('0xff00ff');
Is there a function to set the transparency to true and opacity to say 0.5?
I'm sure there is one, just have no idea of the syntax.
Actually, you cannot achieve that by changing your geometry. Because transparency controlled by materials.
But there's way to do this.
First, each face has materialIndex (Face manual).
Next, Each mesh, drawn within three.js scene has material. And there's special material of type THREE.MeshFaceMaterial (MeshFaceMaterial manual), which takes array of materials as argument.
When faces are drawn, three.js renderer takes face's materialIndex and uses corresponding material from this material array or, if mesh contains single material type.
So you could do something like:
var opacMaterial = new THREE.MeshLambertMaterial({
transparent:true,
opacity:0.7
});
var solidMaterial = new THREE.MeshLambertMaterial({
transparent:false,
color:new THREE.Color(1,0,0)
});
var mesh = new THREE.Mesh(
geometry,
new THREE.MultiMaterial([solidMaterial, opacMaterial])
);
By default, if your geometry have materialIndex == 0 for each faces, you will see solidMaterial drawn.
If you want to make it transparent do something like this;
geometry.faces[i].materialIndex = 1;
Don't forget to update geometry in mesh: (How to update geometry in mesh question.)
Also, aware, if you have materialIndex in your faces greater than length of material array, you will get awkward error inside of deep of THREE.js
I'm using EdgesHelper on a simple model that I exported from SketchUp. It is showing some diagonal lines like this:
How do I prevent those lines from appearing, so that the edges looks like what it appears in SketchUp? I tried setting the thresholdAngle but it doesn't help.
Update:
Working demo: http://jsfiddle.net/alan0xd7/6vLm5xsa/
This is the look I am trying to achieve:
You are rendering both the model and the edges helper in a scene without lights. Remove the model and you can see the helper clearly. All edges are rendered properly.
The reason for the extra edges is because you have two edges concurrent in your model -- a short edge and a long edge. You need to change your geometry. This is not a problem with three.js
If you want to show the edges, but have hidden edges truly hidden, you need to make use of the webgl feature polygonOffset. You can use a pattern similar to the following:
var mesh = dae.children[0].children[0];
mesh.scale.set( 20, 20, 20 );
// replace the material
mesh.material = new THREE.MeshBasicMaterial( {
color: 0x000000,
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
} );
scene.add( mesh )
var helper = new THREE.EdgesHelper( mesh, 0xffffff );
helper.material.linewidth = 2;
scene.add( helper );
updated fiddle: http://jsfiddle.net/6vLm5xsa/15/
three.js r.71
I'm creating text labels that appear on a 3D cube using the following pattern:
canvas = createTextCanvas(text, color, font, size);
texture = new THREE.Texture(canvas);
geom = new THREE.PlaneBufferGeometry(canvas.width, canvas.height, segW, segH);
material = new THREE.MeshBasicMaterial({map: texture, transparent: true});
mesh = new THREE.Mesh(geom, material);
mesh.position.x = x;
mesh.position.y = y;
mesh.position.z = z;
texture.needsUpdate = true;
The labels and their positions get set within a for loop for each edge of the cube. This results in labels appearing similar to this:
But then when I rotate the cube (using OrbitControls), you'll see that the label no longer appears vertically like above:
So using the Cost label as an example, I would want the text to remain vertically oriented whenever the cube is rotated. Basically, I'm trying to mimic the behavior of axis labeling in VTK.
So I believe the solution here is to set the up vector of the label to a vector that's always orthogonal to the plane. But I'm not sure how to implement this. Any suggestions or examples would be greatly appreciated.
If it helps, I'm constructing the cube using a BoxGeometry and MeshNormalMaterial.
Do you mean the label keeps moving with the cube or not?
If not, there is a example: http://stemkoski.github.io/Three.js/Sprite-Text-Labels.html. The label keeps facing to you but may not vertical.
Else ,you may need a canvas texture,the label is a object just like the cube and you can set its position to keep it vertical.But it doesn't look good sometime.the example:http://stemkoski.github.io/Three.js/Texture-From-Canvas.html.
I think you just want the label always facing to you when you change your sight.