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
order.
2.8.0 (Under development)
-------------------------
Fixed
^^^^^
* Improved the algorithm used by the :func:`.mesh.needsFixing` function.
2.7.0 (Wednesday 6th November 2019)
-----------------------------------
......
......@@ -758,15 +758,19 @@ def needsFixing(vertices, indices, fnormals, loBounds, hiBounds):
ivert = np.argmin(dists)
vert = vertices[ivert]
# Pick a triangle that
# this vertex is in and
# ges its face normal
itri = np.where(indices == ivert)[0][0]
n = fnormals[itri, :]
# Get all the triangles
# that this vertex is in
# and their face normals
itris = np.where(indices == ivert)[0]
norms = fnormals[itris, :]
# Make sure the angle between the
# Calculate the angle between each
# normal, and a vector from the
# vertex to the camera is positive
# If it isn't, we need to flip the
# triangle winding order.
return np.dot(n, affine.normalise(camera - vert)) < 0
# vertex to the camera. If more than
# 50% of the angles are negative
# (== more than 90 degrees == the
# 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():
verts = np.array(CUBE_VERTICES)
tris_cw = np.array(CUBE_TRIANGLES_CW)
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)
bhi = verts.max(axis=0)
mesh = fslmesh.Mesh(tris_cw, vertices=verts, fixWinding=True)
......@@ -254,6 +254,28 @@ def test_needsFixing():
assert fslmesh.needsFixing(verts, tris_cw, -fnormals, blo, bhi)
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():
......
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