Three.js: Some material texture faces / triangles not rendering

Created on 21 Dec 2016  路  16Comments  路  Source: mrdoob/three.js

Description of the problem

I have a .obj and .mtl which load textures from .tga files. This all seems to work / look fine in 3D modeling software, but when loaded with three.js (THREE.WebGLRenderer({ antialias: true })) some of the object's children, (specifically between the knees and the calves, but not, for example, the pockets and legs), seem to have a transparent jagged gap / empty triangles. (Tried turning on antialiasing, changing the overdraw value, turning off transparency, etc.)

Demo project and files: demo.zip

Potential problem area: "Forgive my ignorance, but code starting at line 306 in OBJLoader.js seems to imply a fixed side limit/requirement for all faces. The obj file in question shows some faces with more than 4 sides. For example see line 60067 in the obj file. There are more after. It's as if a cut tool has healed cut seams with complex faces." - http://stackoverflow.com/users/3311552/radio

Screenshots and more details (including discussion): http://stackoverflow.com/questions/41154498/threejs-some-material-texture-faces-triangles-not-rendering/41257937#41257937

Three.js version
  • [x] r83
  • [ ] Dev
  • [ ] r82
  • [ ] ...
Browser
  • [x] All of them
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Internet Explorer
OS
  • [x] All of them
  • [ ] Windows
  • [ ] Linux
  • [ ] Android
  • [ ] IOS

Most helpful comment

I took a closer look.

First, turning off the bevel gets rid of the glitches:

https://threejs.org/examples/webgl_geometry_text_earcut.html#75FF00110#Earcut

That means that the glitches are probably related to the bevel functionality.

Then, after quite a bit of looking around how the triangulation of the caps could affect the bevel, I found that both the native function and PnlTri example remove duplicate start/end points:

https://github.com/mrdoob/three.js/blob/master/src/extras/ShapeUtils.js#L194
https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_text_pnltri.html#L52

It turns out that this is actually necessary not just for the triangulation but also for the bevel calculation:
https://github.com/mrdoob/three.js/blob/master/src/geometries/ExtrudeGeometry.js#L196
The getBevelVec function assumes that none of three given points are identical. Otherwise, a (0,0) translation vector is returned which causes glitches.

So, I added, similar to the PnlTri example, the removal of duplicate start/end points to the earcut example:

https://rawgit.com/andreasplesch/three.js/gh-pages/examples/webgl_geometry_text_earcut.html

And the glitches disappeared here as well. Earcut itself is actually ok with duplicate start/end points.

I can prepare a PR for the example if useful.

All 16 comments

OBJLoader only supports triangular faces and convex quads, and tessellates the quads for you.

If a quad is not convex and planar, then the tessellation may be incorrect.

Your work-around is to triangulate faces having more than 4 vertices before exporting.

I just want to add, it's important to note from the previous discussion that Second Life Obj output is unsupported (Singularity), primitive and does not have options normally associated with obj export.

There are 3d programs which allow opening a mesh, even from SL, triangulation and re-export. Three only supports triangular faces and convex quads because most rendering hardware is designed for quads and triangles. It's nice that some viewers correct the face, but a fix in OBJLoader becomes detection and correction. There are many issues that appear in vertex sets that could be corrected as well. Unless a fix can be found at the webGL level, JavaScript intervention is out of step with performant, run anywhere ability. Strict face vertex structure is good practice for the web. 3d assets should be well considered before sent to a browser. If Three was just an OBJ viewer, it might make sense.

Since more than a few obj viewers I opened the example obj file with fixed the offending polygons, I wonder if this fix is happening at the openGL level that isn't handled by webGL. I can't imagine the number of edge cases and lazy face issues that would need to be written.

The obj specification can be read here http://paulbourke.net/dataformats/obj/ It describes no vertex limit, but I believe the assumption is that the limit is set by the render.

Actually, we have code core that triangulates a set of points... https://github.com/mrdoob/three.js/blob/dev/src/extras/ShapeUtils.js#L192

@jonnenauha Maybe OBJLoader could use that to triangulate ngons at load time and say goodbye to this problem?

@radio412 you are referring to .obj files with polygon p declarations?

p  v1 v2 v3 . . .

    Polygonal geometry statement.

    Specifies a point element and its vertex. You can specify multiple
    points with this statement. Although points cannot be shaded or
    rendered, they are used by other Advanced Visualizer programs.

    v is the vertex reference number for a point element. Each point
    element requires one vertex. Positive values indicate absolute
    vertex numbers. Negative values indicate relative vertex numbers.

The face f afaik limits the number to four (?), which obj loader does support. Or is there a bug in that code? I have just seen that the code to handle the fourth element.

It does have this note there, but I've never seen lines with more than 4 elements on a line.

There is no space between numbers and the slashes. There may be more
than one series of geometric vertex/texture vertex/vertex normal
numbers on a line.

I believe @mrdoob is right that we could triangulate them with three.js utils. At the moment p lines I think are just ignored (or actually it might be a unhandled line exception).

@radio412 could you provide file(s) that we could use to test/implement the needed features?

@jonnenauha The original version of the vive controller has some f with more than 4 vertices:

https://raw.githubusercontent.com/mrdoob/three.js/732fee16c12fdb53560ec791360e7899b4c3b2af/examples/models/obj/vr_controller_vive_1_5.obj

@mrdoob For the record, there are several places where three.js tessellates quads for the user by simply creating two triangles. The loaders come to mind.

Thing is, this is only guaranteed to work if the quad is convex. A counter-example is a V-like shape, which is, of course, not convex. In that case, only one of the diagonals is correct.

The three.js approach may also be problematic if the quad is not planar, but I do not think we need to support that case.

https://github.com/mapbox/earcut is a good and fast tesselation library for arbitrary 2d (flat) polygons.

https://github.com/mapbox/earcut is a good and fast tesselation library for arbitrary 2d (flat) polygons.

Yes, we know... https://threejs.org/examples/#webgl_geometry_text_earcut

Just curious: is there a discussion somewhere why the built-in triangulation was not replaced ? Faster in some cases ?

Well, at the moment, the earcut example seems to have some glitches. Not sure where these come from.

Oh, I see the glitches in each letter, contour. The latest earcut release has the same issue: https://rawgit.com/andreasplesch/three.js/gh-pages/examples/webgl_geometry_text_earcut.html uses the latest.

Maybe an overzealous filtering issue ? Or/And a numerical precision issue ? Maybe I can use the debugger to extract a problem contour and file an issue with earcut since I did not find a related one there.

@andreasplesch that would be great 馃憣

I took a closer look.

First, turning off the bevel gets rid of the glitches:

https://threejs.org/examples/webgl_geometry_text_earcut.html#75FF00110#Earcut

That means that the glitches are probably related to the bevel functionality.

Then, after quite a bit of looking around how the triangulation of the caps could affect the bevel, I found that both the native function and PnlTri example remove duplicate start/end points:

https://github.com/mrdoob/three.js/blob/master/src/extras/ShapeUtils.js#L194
https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_text_pnltri.html#L52

It turns out that this is actually necessary not just for the triangulation but also for the bevel calculation:
https://github.com/mrdoob/three.js/blob/master/src/geometries/ExtrudeGeometry.js#L196
The getBevelVec function assumes that none of three given points are identical. Otherwise, a (0,0) translation vector is returned which causes glitches.

So, I added, similar to the PnlTri example, the removal of duplicate start/end points to the earcut example:

https://rawgit.com/andreasplesch/three.js/gh-pages/examples/webgl_geometry_text_earcut.html

And the glitches disappeared here as well. Earcut itself is actually ok with duplicate start/end points.

I can prepare a PR for the example if useful.

I can prepare a PR for the example if useful.

Yes please! ^^

10917 Fix it, only test 2 models.

After #11871, OBJLoader should be able to handle these files:

r86
screen shot 2017-08-09 at 8 41 57 pm

r87dev
screen shot 2017-08-09 at 8 41 38 pm

Interestingly. I realised MacOS doesn't handle ngons either... 馃

screen shot 2017-08-09 at 8 44 52 pm

Was this page helpful?
0 / 5 - 0 ratings