1
0
mirror of synced 2025-02-17 19:19:19 +01:00

Fix bug in matrix inversion code relating to upper triangles causing some matrixes to fail to invert and hiding some textures.

This commit is contained in:
Jennifer Taylor 2021-07-31 01:15:52 +00:00
parent 6e76c25e95
commit 96a99f6f74

View File

@ -319,6 +319,14 @@ class Matrix:
) )
def inverse(self) -> "Matrix": def inverse(self) -> "Matrix":
try:
return self.__inverse_impl()
except ZeroDivisionError:
pass
raise ZeroDivisionError(f"Matrix({self}) cannot be inverted!")
def __inverse_impl(self) -> "Matrix":
# Use gauss-jordan eliminiation to invert the matrix. # Use gauss-jordan eliminiation to invert the matrix.
size = 4 size = 4
m = [ m = [
@ -329,36 +337,44 @@ class Matrix:
] ]
inverse: List[List[float]] = [[1 if row == col else 0 for col in range(size)] for row in range(size)] inverse: List[List[float]] = [[1 if row == col else 0 for col in range(size)] for row in range(size)]
# First, get upper triangle of the matrix.
for col in range(size): for col in range(size):
# First, get upper triangle of the matrix.
if col < size - 1: if col < size - 1:
numbers = [m[row][col] for row in range(col, size)] numbers = [m[row][col] for row in range(col, size)]
if all(n == 0 for n in numbers): if all(n == 0 for n in numbers):
print("HOO!")
raise ZeroDivisionError(f"Matrix({self}) cannot be inverted!") raise ZeroDivisionError(f"Matrix({self}) cannot be inverted!")
# Reorder the matrix until all nonzero numbers are at the top. # Reorder the matrix until all nonzero numbers are at the top.
for row in range(col, size - 1): nonzeros_m = []
# First, make sure all non-zero values are at the top. nonzeros_inverse = []
zeros_m = []
zeros_inverse = []
for row in range(size):
nrow = row - col nrow = row - col
if nrow < 0:
# This is above the current part of the triangle, just
# include it as-is without reordering.
nonzeros_m.append(m[row])
nonzeros_inverse.append(inverse[row])
continue
if numbers[nrow] == 0: if numbers[nrow] == 0:
# Put this at the end. # Put this at the end.
numbers = [ zeros_m.append(m[row])
*numbers[:nrow], zeros_inverse.append(inverse[row])
*numbers[(nrow + 1):], else:
numbers[nrow], nonzeros_m.append(m[row])
] nonzeros_inverse.append(inverse[row])
m = [
*m[:row], m = [
*m[(row + 1):], *nonzeros_m,
m[row], *zeros_m,
] ]
inverse = [ inverse = [
*inverse[:row], *nonzeros_inverse,
*inverse[(row + 1):], *zeros_inverse,
inverse[row], ]
]
row += 1
# Now, figure out what multiplier we need to make every # Now, figure out what multiplier we need to make every
# other entry zero. # other entry zero.