82 lines
2.3 KiB
Python
82 lines
2.3 KiB
Python
import numpy as np
|
|
|
|
PNT = list[tuple[float, float, float, # position
|
|
float, float, # texture
|
|
float, float, float, float]] # normal
|
|
|
|
def get_position(vertex_buffer: list[PNT], index):
|
|
return vertex_buffer[index][0:3]
|
|
|
|
def get_texture(vertex_buffer: list[PNT], index):
|
|
return vertex_buffer[index][3:5]
|
|
|
|
def get_normal(vertex_buffer: list[PNT], index):
|
|
return vertex_buffer[index][5:8]
|
|
|
|
def normalize(v):
|
|
return v / np.linalg.norm(v)
|
|
|
|
def generate_tangents(vertex_buffer: list[PNT],
|
|
index_buffer: list[int]):
|
|
vertex_count = len(vertex_buffer)
|
|
|
|
triangle_count = len(index_buffer) // 3
|
|
|
|
tan_s = np.zeros((vertex_count, 3,))
|
|
tan_t = np.zeros((vertex_count, 3,))
|
|
|
|
for t in range(triangle_count):
|
|
i0 = index_buffer[t * 3 + 0]
|
|
i1 = index_buffer[t * 3 + 1]
|
|
i2 = index_buffer[t * 3 + 2]
|
|
|
|
p0 = get_position(vertex_buffer, i0)
|
|
p1 = get_position(vertex_buffer, i1)
|
|
p2 = get_position(vertex_buffer, i2)
|
|
|
|
uv0 = get_texture(vertex_buffer, i0)
|
|
uv1 = get_texture(vertex_buffer, i1)
|
|
uv2 = get_texture(vertex_buffer, i2)
|
|
|
|
x1 = p1[0] - p0[0]
|
|
x2 = p2[0] - p0[0]
|
|
y1 = p1[1] - p0[1]
|
|
y2 = p2[1] - p0[1]
|
|
z1 = p1[2] - p0[2]
|
|
z2 = p2[2] - p0[2]
|
|
|
|
s1 = uv1[0] - uv0[0]
|
|
s2 = uv2[0] - uv0[0]
|
|
|
|
t1 = uv1[1] - uv0[1]
|
|
t2 = uv2[1] - uv0[1]
|
|
|
|
d = (s1 * t2 - s2 * t1)
|
|
r = 1.0 / d if d != 0 else 0
|
|
|
|
sdir = np.array([(t2 * x1 - t1 * x2) * r,
|
|
(t2 * y1 - t1 * y2) * r,
|
|
(t2 * z1 - t1 * z2) * r])
|
|
|
|
tdir = np.array([(s1 * x2 - s2 * x1) * r,
|
|
(s1 * y2 - s2 * y1) * r,
|
|
(s1 * z2 - s2 * z1) * r])
|
|
|
|
tan_s += sdir
|
|
tan_t += tdir
|
|
|
|
tangents = []
|
|
for v in range(vertex_count):
|
|
n = np.array(get_normal(vertex_buffer, v))
|
|
s = tan_s[v]
|
|
|
|
# orthagonalize
|
|
tangent = normalize(s - n * np.dot(n, s))
|
|
h = np.dot(np.cross(n, s), tan_t[v])
|
|
w = -1.0 if h < 0.0 else 1.0
|
|
tangent_w = (tangent[0], tangent[1], tangent[2], w)
|
|
#print(tangent_w)
|
|
tangents.append(tangent_w)
|
|
|
|
return tangents
|