Why some triangles on the mesh appear to be transparent from certain angle with three.js? - three.js

first of all I am a newbie with three.js. I am making a 3D puzzle and need to create several objects that are made up from triangles. The problem is that from a certain angle those triangles appear to be transparent:
example 1, example 2. Material for mesh is created like this:
var materials = [
new THREE.MeshLambertMaterial( { opacity:0.6, color: 0x44ff44, transparent:false } ),
new THREE.MeshBasicMaterial( { color: 0x44ff44, wireframe: true } )
];
Is there any common cause for this "bug"? Or I should look into my code more because there is something wrong with it?

Every face (triangle) has a side that will be visible and the second one that will not be visible. To reverse the visibility you may change material's property side - THREE.BackSide - will display backward side instead of usual one. THREE.DoubleSide - will display both. BUT! The true issue is winding order. The visible side of triangle determined by a winding direction in which you have added vertices to your faces. Which means invisible triangles has backward direction from the one you need. In example (very primitive actually):
...
object.vertices.push(new THREE.Vector3(1,1,1)); // vertex index 0
object.vertices.push(new THREE.Vector3(2,2,2)); // vertex index 1
object.vertices.push(new THREE.Vector3(3,3,3)); // vertex index 2
object.faces.push( new THREE.Face3(0,1,2) );
...
to reverse visible side of triangle you need to change the following line to:
object.faces.push( new THREE.Face3(2,1,0) );
So you just need to find broken triangles and reverse vertices order.

Related

Rotate around World Axis

I tried to rotate an object arount the Worlds-Y-Axis, with
myObject.rotateOnWorldAxis(new THREE.Vector3(0,1,0),THREE.Math.degToRad(1));
but the result was, that the object is only rotated in object space.
To be sure that I used the correct method I looked into the documentation and found that there are three methods to rotate an object:
.RotateY(rad) // rotate in Local Space
.rotateOnAxis(axis,rad) // rotation in Object Space
.rotateOnWorldAxis(axis,rad) // rotation in World Space
It seems that I used the correct method.
Is this a bug or an understanding problem on my side?
Here is a JSFiddle which illustrates my problem (the blue cube should rotate around the world axis).
Here is a second Fiddle where thy cyan cube is a child of another object.
It looks to me like your real question isn't regarding world space or object space rotations, cause those are working as expected in your examples.
You probably meant, how to change the point of rotation of an object. If that is the case, you have two options, you can either translate all your geometry vertices in respect to a pivot point of rotation. That way, your pivot will be centered at (0,0,0) and your vertices will rotate in respect to that.
mesh.geometry.translate( x, y, z );
Or you can make your object a child of a different Object3D (pivot), position your original mesh similarly to what was described above and rotate your pivot mesh.
var cube = new THREE.Mesh( geometry, material );
var pivot = new THREE.Object3D();
cube.position.set( 0, 12, 30 ); // offset from center
pivot.add( cube );
scene.add( pivot );
//...
pivot.rotation.y += Math.PI/2;
JSFiddle

three.js EdgesHelper showing certain diagonal lines on Collada model

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

THREE.js: Looking for an alternative to MeshFaceMaterial

According to various posts at the three.js github, MeshFaceMaterial will be deprecated eventually.
I currently use this for my terrain. Granted it's not the best way to do it. Actually its pretty crappy. For one I cannot use BufferGeometry which is not good considering I generally have 2 layers of 128x128 (segmented) planes for terrain. Very high memory usage.
I've adapted all my code to allow for the terrain to be BufferGeometry except two things don't work. MeshFaceMaterial and BufferGeometry.merge(). The merge doesn't work on indexed geometry which to me is weird considering THREE creates this geometry, yet it can merge non-indexed geometry from blender. It cannot merge geometry it creates itself but can merge geometry from external sources... Oh well that's another post there, back to MeshFaceMaterial.
I currently use a 128x128 "MaterialMap". Each pixel represents a materialIndex for each face of the plane. This has two serious drawbacks. Squared up sections of terrain (no curves) and harsh distinctions on the borders of textures.
My question is: How can I generate this terrain with multiple textures without using MeshFaceMaterial. The highest res texture I have is 2048x2048 and zone size can easily be 10000x10000 making repeat necessary (right?).
Ultimately my goal is to use BufferGeometry and get rid of MeshFaceMaterial.
MaterialMap example:
Terrain Example (terribly cropped sorry {work pc}):
You helped me out a while back via email with advice on culling meshes so I would like to return the favor (with my humble strategy) :)
If you want to use THREE.PlaneBufferGeometry (which, as you know, is where all geometry in THREE.js is soon headed), then my advice would be to layer different PlaneBufferGeometries right on top of each other. For instance in the above example picture, you could have
var stoneFloorGeometry = new THREE.PlaneBufferGeometry(arenaWidth, arenaHeight, 1, 1);
var stoneFloorMaterial = new THREE.MeshBasicMaterial({
depthWrite: false, // This is always underneath every other object
map: stoneFloorTexture
});
var stoneFloor = new THREE.Mesh(stoneFloorGeometry, stoneFloorMaterial);
stoneFloor.rotation.x = Math.PI / -2; // rotate to be flat in the X-Z plane
stoneFloor.position.set(0, 0, 0);
scene.add(stoneFloor);
// now add the grass plane right on top of that with its own texture and shape
var grassGeometry = new THREE.PlaneBufferGeometry(lawnWidth, lawnHeight, 1, 1);
var grassMaterial = new THREE.MeshBasicMaterial({
depthWrite: false, // this is rendered right on top of the stone floor
map: grassTexture
});
var grass = new THREE.Mesh(grassGeometry, grassMaterial);
grass.rotation.x = Math.PI / -2;
grass.position.set(0, 0, 0);
scene.add(grass);
// finally add the stone path walkway on top of the grass, leading to the castle
var walkwayGeometry = new THREE.PlaneBufferGeometry(walkwayWidth, walkwayHeight, 1, 1);
var walkwayMaterial = new THREE.MeshBasicMaterial({
depthWrite: false, // this is rendered right on top of the grass
map: stoneFloorTexture // uses same texture as large stoneFloor before
});
var walkway = new THREE.Mesh(walkwayGeometry, walkwayMaterial);
walkway.rotation.x = Math.PI / -2;
walkway.position.set(0, 0, 0);
scene.add(walkway);
As long as you layer the level from bottom to top and disable depthWrite, all the various textures will correctly show up on top of each other, and none will Z-fight. So, stoneFloor is added to the scene first, followed by grass, followed by walkway.
And since depthTest is still active, your moving game characters will render on top of all these various textures. Initially, it also looked like it worked with just disabling 'depthTest', but the textures ended up rendering over ('above') the characters/models which is incorrect.
Eventually when THREE.js moves ShapeGeometry over to BufferGeometry, it would be nice to define an arbitrary polygonal shape (like an octagon or something) and then texture map that and lay down shapes on top of each other for the game level in a similar manner, thus avoiding the 'square' problem you mentioned.
As for this current solution, on the modern CPU/GPU I don't think you will see much performance cost in creating 3 PlaneBufferGeometries instead of 1 large one with multiple faces/indexes. This way you have the advantages of using THREE's BufferGeometry while still having everything 'looking' like it is all texture-mapped to one large plane.
Hope this helps!
-Erich (erichlof on GitHub)

How to list me vertex normals to the specified tops?

I do animation at which the part of tops moves. Thus lighting starts working incorrectly. For correct lighting it is necessary to change face.vertexNormals. At first I thought that it is enough
geometry.computeVertexNormals();
But it appeared, it does not absolutely that.
How to list me topmost vertex normals to the specified tops?
OR
How to list me the faces containing specified tops?
example here
Here example. But I need not only to see them, and to list and change in the program.
if (d<50) { var dist = 15 * Math.cos( d/20 - t );
geometry.vertices[i].z = dist; }
How to list me vertex normals for these tops?
Your plane is upside-down, which causes your vertex normals to point downward.
Set plane.rotation.x = -Math.PI/2;.
To see the normals, add
vnh = new THREE.VertexNormalsHelper( plane, 20, 0xff0000, 2 );
scene.add( vnh );
to your init() function, and in your animation loop call:
vnh.update();
three.js r.68

How to create a coin from two images of the coin using three.js CylinderGeometry.?

Hi thanks in advance for any help. I have two images of a coin say a head and tail of some coin. I want to create 3D coin from it using three.js. I tried a lot but could not get to the actual shape of a coin. My code is following.
mesh = new THREE.Mesh(
new THREE.CylinderGeometry(20, 20, 0, 20, 1, false),
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture('coin1.png'),
overdraw: true } ) );
scene.add(mesh);
Please help how can i add second image so that it is shown like a real 3D coin.
Regards
I am not expert on three.js, but I assume it is the same like in others engines.
You have to create one texture containing top, edge and bottom of the coin. Then you have to map the texture on triangles of your cilinder. So you have to create your own cylinder and mappings. You can find details in Texturing a Cylinder in Three.js question.

Resources