Skip to content
Snippets Groups Projects
Commit df39f3ed authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

Merge branch 'bf/mesh-winding-order' into 'master'

Bf/mesh winding order

See merge request fsl/fslpy!181
parents 1e9da99c cda7029c
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,18 @@ This document contains the ``fslpy`` release history in reverse chronological ...@@ -2,6 +2,18 @@ This document contains the ``fslpy`` release history in reverse chronological
order. order.
2.8.0 (Under development)
-------------------------
Fixed
^^^^^
* Improved the algorithm used by the :func:`.mesh.needsFixing` function.
2.7.0 (Wednesday 6th November 2019) 2.7.0 (Wednesday 6th November 2019)
----------------------------------- -----------------------------------
......
...@@ -758,15 +758,19 @@ def needsFixing(vertices, indices, fnormals, loBounds, hiBounds): ...@@ -758,15 +758,19 @@ def needsFixing(vertices, indices, fnormals, loBounds, hiBounds):
ivert = np.argmin(dists) ivert = np.argmin(dists)
vert = vertices[ivert] vert = vertices[ivert]
# Pick a triangle that # Get all the triangles
# this vertex is in and # that this vertex is in
# ges its face normal # and their face normals
itri = np.where(indices == ivert)[0][0] itris = np.where(indices == ivert)[0]
n = fnormals[itri, :] norms = fnormals[itris, :]
# Make sure the angle between the # Calculate the angle between each
# normal, and a vector from the # normal, and a vector from the
# vertex to the camera is positive # vertex to the camera. If more than
# If it isn't, we need to flip the # 50% of the angles are negative
# triangle winding order. # (== more than 90 degrees == the
return np.dot(n, affine.normalise(camera - vert)) < 0 # face is facing away from the
# camera), assume that we need to
# flip the triangle winding order.
angles = np.dot(norms, affine.normalise(camera - vert))
return ((angles >= 0).sum() / len(itris)) < 0.5
...@@ -245,7 +245,7 @@ def test_needsFixing(): ...@@ -245,7 +245,7 @@ def test_needsFixing():
verts = np.array(CUBE_VERTICES) verts = np.array(CUBE_VERTICES)
tris_cw = np.array(CUBE_TRIANGLES_CW) tris_cw = np.array(CUBE_TRIANGLES_CW)
tris_ccw = np.array(CUBE_TRIANGLES_CCW) tris_ccw = np.array(CUBE_TRIANGLES_CCW)
fnormals = np.array(CUBE_CCW_VERTEX_NORMALS) fnormals = np.array(CUBE_CCW_FACE_NORMALS)
blo = verts.min(axis=0) blo = verts.min(axis=0)
bhi = verts.max(axis=0) bhi = verts.max(axis=0)
mesh = fslmesh.Mesh(tris_cw, vertices=verts, fixWinding=True) mesh = fslmesh.Mesh(tris_cw, vertices=verts, fixWinding=True)
...@@ -254,6 +254,28 @@ def test_needsFixing(): ...@@ -254,6 +254,28 @@ def test_needsFixing():
assert fslmesh.needsFixing(verts, tris_cw, -fnormals, blo, bhi) assert fslmesh.needsFixing(verts, tris_cw, -fnormals, blo, bhi)
assert np.all(np.isclose(mesh.indices, tris_ccw)) assert np.all(np.isclose(mesh.indices, tris_ccw))
# regression: needsFixing used to use the first triangle
# of the nearest vertex to the camera. But this will fail
# if that triangle is facing away from the camera.
verts = np.array([
[ -1, -1, -1], # vertex 0 will be nearest the camera
[ 0.5, -0.5, 0],
[ 1, -1, 0],
[ 1, 1, 1],
[ 0, -1, 1]])
tris = np.array([
[0, 4, 1], # first triangle will be facing away from the camera
[0, 1, 2],
[1, 3, 2],
[0, 2, 4],
[2, 3, 4],
[1, 4, 3]])
mesh = fslmesh.Mesh(tris, vertices=verts, fixWinding=True)
fnormals = fslmesh.calcFaceNormals(verts, tris)
blo = verts.min(axis=0)
bhi = verts.max(axis=0)
assert not fslmesh.needsFixing(verts, tris, fnormals, blo, bhi)
def test_trimesh_no_trimesh(): def test_trimesh_no_trimesh():
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment