Modified meshes lighting doesn't look right - three.js

I'm adding planes next to each over, and modify vertices a bit. After that the lighting doesn't look right between the connection points. Why does this happen?

It's a bit complicated but here goes:
Each vertex has a normal.. the normal is computed as the weighted average of all the neighboring vertex normals.
The neighbors on the edge of the first patch aren't lining up with the second patch, and don't know what the neighboring patches vertex normals are, 1 face in from the edge.
So one solution is to create patches that overlap by 2 cells, so that each patch has a ring of shared faces around it, then recompute their normals, then remove the outer ring of faces, (since those will have incorrect normals).
So if your patch is 16x16 faces.. make patches of 18x18, and make their edges overlap.. modify the vertices of each patch using the same noise function based on the world space x/z of the vertices (simplex or perlin noise is good), and then recompute face/vertex normals, then do the outer ring removal from the face list.
It's complicated but works.

Related

UV-mapping a BufferGeometrys indices in Three.js

I'm having trouble UV mapping each side of a cube. The cube was made as a BufferGeometry where each side is a rotated copy of one side (sort of a working template) and rotated accordingly by applying a quarternion. UVs are copied as well. I'll skip any vertex coordinate I've seen before and rely on indices.
This leaves me with a total of 8 vertices and 12 faces. But I think I'm running short on vertices when I have to set all of my UVs. As obvious on the screenshot I've "correctly" mapped each side of the cube. But the top and bottom is lacking. I don't know how to set the vertex UV top and bottom faces.
Can I in some way apply several UVs on the same vertex depending on which face it is used in or have I completely lost the plot?
I could solve the problem by applying 6 PlaneBufferGeometry but that would leave me with 4*6=24 vertices. That is a whole lot more than 8.
I haven't been able to figure this one out. Either I've complete misunderstood how it works or what I'm trying to accomplish is impossible given my constraints.
With BufferGeometry, vertices can only be reused if all the attributes for that vertex match. Since each corner of the cube has 3 perpendicular normals, there must be 3 copies of that vertex.
If you have uvs, it is the same issue -- vertices must be duplicated if the uvs are different.
Study BoxBufferGeometry, which is implemented as "indexed-BufferGeometry".
three.js r.90

How to merge adjacent coplanar faces on a mesh

I am looking for a method / algorithm that will allow me to merge several adjacent coplanar faces on a 3d mesh into a single face. I am hoping that this will optimize my mesh generation program, because right now it generates many 'little' triangles. When I look at the final 3d object on the screen, I can see that they all are oriented in the same direction and they could be replaced with one bigger triangle that encompasses the whole lot! I hope that is clear what I am trying to do. Thanks for your help.
I would suggest you project the faces in a single plane and than apply an algorithm for polygon uninon a plane. After that "unproject" and that's it. Always try to reduce dimensions when possible.
Your task is a special case of mesh simplification (or decimation), where the algorithm is only allowed to reduce some mesh elements without introducing any error in object's shape. And probably the most famous algorithm here is Surface Simplification Using Quadric Error Metrics.
It searches for edges in the mesh that can be contracted in a single vertex (which position is automatically selected for each edge) so that it minimizes quadratic error associated with that contraction (in your case the error is zero).
Let us consider a simple example of cube's face subdivided in 8 triangles:
Left: magenta edge is selected for contraction, remaining vertex will be located in the bottom point of the edge.
Center: after the first contraction, next magenta edge is selected, after contraction it will become a vertex in cube's corner.
Right: the final result of simplification (after contractions on other cube's faces as well), where no more coplanar triangles can be merged (at least in larger triangles).
The illustration above was prepared in MeshInspector application.

Most efficient algorithm to calculate vertex normals from set of triangles for Gouraud shading

We are given a set of triangles. Each triangle is a triplet of points. Each point is a triplet of real numbers. We can calculate surface normal for each triangle. For Gouraud shading however, we need vertex normals. Therefore we have to visit each vertex and look at the triangles that share that vertex, average their surface normals and we get vertex normal.
What is the most efficient algorithm and data structure to achieve this?
A naive approach is this (pseudo python code):
MAP = dict()
for T in triangles:
for V in T.vertices:
key = hash(V)
if MAP.has(key):
MAP[key].append(T)
else:
MAP[key] = []
MAP[key].append(T)
VNORMALS = dict()
for key in MAP.keys():
VNORMALS[key] = avg([T.surface_normal for T in MAP[key]])
Is there a more efficient approach?
Visit each triangle, calculate the normal for each triangle, ADD those to the vertex normal for each corner vertex.
Then at the end, normalise the normals for each vertex.
Then at least you only have to traverse the triangles once and you only store one normal/vertex.
Each vertex belongs to one or more faces (usually triangles, sometimes quads -- I'll use triangles in this answer).
A triangle that is not attached to any other triangles cannot be 'smoothed'. It is flat. Only when a face has neighbours can you reason about smoothing them together.
For a vertex where multiple faces meet, calculate the normals for each of these faces. The cross product of two vectors returns a perpendicular (normal) vector, which is what we want.
A --- B
\ /
C
v1 = B - A
v2 = C - A
normal = v1 cross v2
Be careful to calculate these vectors consistently across all faces, otherwise your normal may be in a negative direction to that you require.
So at a vertex where multiple faces meet, sum the normals of the faces, normalise the resulting vector, and apply it to the vertex.
Sometimes you have a mesh where some parts of it are to be smoothed, and others not. An easy to picture example is a cylinder made of triangles. The round surface of the cylinder would smooth well, but if you consider triangles from the flat ends at the vertices around the sharp ridge, it will look strange. To avoid this, you can introduce a rule that ignore normals from faces which deviate too far from the normal of the face you're calculating for.
EDIT there's a really good video showing technique for calculating Gourad shading, though it doesn't discuss an actual algorithm.
You might like to take a look at the source of of Three.js. Specifically, the computeVertexNormals function. It does not support maintaining sharp edges. The efficiency of your algorithm depends to a large extent upon the way in which you are modelling your primitives.

OBJ format and Flat vs Smooth Shading

I'm using OpenGL ES 1.1 and working on converting an OBJ export from Blender into some binary files containing vertex data. I actually already have a working tool, but I'm working on changing some things and came across a question.
Even with Smooth shading, it seems that with correct normals (perpendicular to the face plane) it achieves a flat appearance for faces. With Smooth shading enabled and the proper normals (simply via edges marked as sharp in Blender and an edge-split modifier applied), I can get the affect of smooth parts and sharp edges.
Where I'm going with this brings 2 questions.
Are the "s 1" or "s off" lines where smooth or flat shading is denoted in the OBJ file completely unnecessary from a smooth shading and use of normals standpoint?
When actually set to Flat shading in OpenGL, are normals completely ignored (or just assumed to all be perpendicular to the faces)?
For a vertex to look smooth, its normal has to be the average of the adjacent face normals (or something the like), but not perpendicular to the face plane (except if you meaned the average plane of all its adjacent faces).
GL_FLAT means, the color of a face is not interpolated over the triangle, but taken from a single triangle corner (don't know which, first or last). This color comes either from vertex colors or vertex lighting, so in fact you get per-face normals, but this is not neccessarily the faces direction, but the normal of a corner vertex.
If you got per vertex normals in the OBJ file you do not need the s parts. But you can use these to compute vertex normals. The s parts are the smoothing groups and are to be interpreted as 32bit bitfields. So there are actually 32 different smoothing groups and every face can be part of more than one. So all faces after an "s 5" line are part of smoothing groups 1 and 3 (first and third bits set). When two neighbouring faces are part of the same smoothing group, the edge between them is smooth (vertices share normals). This way you can reconstruct the neccessary per-vertex normals.
Changing the mode between gl_flat and gl_smooth doesn't seem to affect my rendering when I'm using per vertex normals. Your problem from what I can tell is that each face only has one normal. For smooth shading, each face should have three normals, one for each vertex, and they should all be different. For example, the normals of a cylinder, if projected inside of the cylinder, should all intersect at the axis of the cylinder. If your model has smooth normals, then an OBJ export should export per vertex normals. It sounds like you are probably assigning per face normals. As far as rendering in OpenGL-ES, the smoothing groups aren't used, only normals.

Vertex normals for a cube

A cube has 8 unique vertices. Is it true that each of these 8 vertex normals (unit vectors) is making 135 degree angle to each of the edges which shares that vertex? And the vertex normal pointing outward/out of the cube? Your answer should be technically correct. Or it depends on how the cube is defined (drawn) like using triangle strips or indices that define 2 triangles for each side of the cube? The purpose of the vertex normal is smooth shading and lighting in OpenGL ES application.
If the cube is defined by 8 unique vertices, then the normals will likely be making a 135 degree angle to each edge, as you mentioned.
However, a cube is often defined using 24 vertices for exactly this reason. This allows you to have vertex normals that are perpendicular to each face, by "duplicating" vertices at each corner. Defining a cube this way is, effectively, just defining 6 individual faces, each pointing outwards appropriately.
There is no point in smoothing the cube with 8 vertices in order to make it look like a sphere. You'll get an extremely ugly sphere this way. The only reasonable way to draw the cube is using 24 unique vertices.
The center-oriented normals of the eight corner vertices of a cube will actually form an angle of 125 degrees, 16 minutes with each connected edge.
There's a good discussion of this topic elsewhere on SO.
The 135 degree can be explained visually by the normal vector of each vertices point outwards and must share the same angle with each edge the vertex is part of. Since the inner angle is 90 degree 270 degrees are outward of this corner. Therefore 270 degree /2 = 135 degree.
The normal vectors of each vertex are used to calculate the normal vector of the triangle. For your 3d model being a collection of flat triangles, having only a single normal to calculate the lighting from it would result in flat shading (thou being physically correct if the object really would be that edgy). Using the vertex normals to interpolate the 'normals' for each point of the triangle gives a smooth lighting reassembling a smooth surface.
The problem with this approach is using only a single normal per vertex results in the cube to have a shading like a sphere while still being a cube.
That is basically the reason why one want to define a cube with 24 (= 6x4) vertices rather than 6. This way one can have a cube with all faces (and therefore each two of its triangles) to have correct (flat) normals.
Having 24 vertices and therefore 24 normals provide the possibility to define only forward facing normals for each triangle/face so that the normals point always in a 90 degree angle away from the triangle/face and therefore provide a flat shading throughout every triangle/face which is more correct for a cube as its surfaces are really flat.
Usually one does not want to shade a steep angle like 90 (270) degree in a smooth continuous way. The normal interpolation is only used to mimic 'organic'/'smooth' surfaces. Since these organic / smooth surfaces are the norm (think about the tea pot or a 3d-figure) the decision was made to store the vertex normals with the position and UV coordinates as it is the norm in most of the 'continuous' 3d surfaces. Normally you add more triangles to represent a smooth topology in a model. Having vertex normals is, therefore, a trade-off to minimize the amount of information for the average model.
A cube model with its all flat triangles is, therefore, the worst case. This is why each of the cube's corner needs three vertex normals, one for each face it is a vertex of.
PS: Today those 'smooth' surfaces are further defined by using normal maps baked from a higher resolution model. Using normal maps, each point in the face gets its own normal vector (or the normal vector of each point can be interpolated from the normal vector samples provided by the mapped normal map).

Resources