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