def dispverts_of(self, face): # add format argument (lightmap uv, 2 uvs, etc) """vertex format [Position, Normal, TexCoord, LightCoord, Colour] normal is inherited from face returns rows, not tris""" verts = self.verts_of(face) if face.disp_info == -1: raise RuntimeError('face is not a displacement!') if len(verts) != 4: raise RuntimeError( 'face does not have 4 corners (probably t-junctions)') disp_info = self.DISP_INFO[face.disp_info] start = list(disp_info.start_position) start = [round(x, 1) for x in start] # approximate match round_verts = [] for vert in [v[0] for v in verts]: round_verts.append([round(x, 1) for x in vert]) if start in round_verts: # "rotate" index = round_verts.index(start) verts = verts[index:] + verts[:index] A, B, C, D = [vector.vec3(*v[0]) for v in verts] Auv, Buv, Cuv, Duv = [vector.vec2(*v[2]) for v in verts] Auv2, Buv2, Cuv2, Duv2 = [vector.vec2(*v[3]) for v in verts] # scale is wrong AD = D - A ADuv = Duv - Auv ADuv2 = Duv2 - Auv2 BC = C - B BCuv = Cuv - Buv BCuv2 = Cuv2 - Buv2 power2 = 2**disp_info.power full_power = (power2 + 1)**2 start = disp_info.disp_vert_start stop = disp_info.disp_vert_start + full_power new_verts, uvs, uv2s = [], [], [] for index, disp_vert in enumerate(self.DISP_VERTS[start:stop]): t1 = index % (power2 + 1) / power2 t2 = index // (power2 + 1) / power2 bary_vert = vector.lerp(A + (AD * t1), B + (BC * t1), t2) disp_vert = [x * disp_vert.distance for x in disp_vert.vector] new_verts.append([a + b for a, b in zip(bary_vert, disp_vert)]) uvs.append(vector.lerp(Auv + (ADuv * t1), Buv + (BCuv * t1), t2)) uv2s.append( vector.lerp(Auv2 + (ADuv2 * t1), Buv2 + (BCuv2 * t1), t2)) normal = [verts[0][1]] * full_power colour = [verts[0][4]] * full_power verts = list(zip(new_verts, normal, uvs, uv2s, colour)) return verts
def draw_lerp(self, dt): global tickrate dt *= tickrate position = vector.lerp(self.old_position, self.position, dt) glPushMatrix() glTranslate(*position) glColor(1, 0, 1) glBegin(GL_LINES) glVertex(0, 0, (self.aabb.min.z + self.aabb.max.z) / 2) glVertex(self.front.x * 48, self.front.y * 48, (self.aabb.min.z + self.aabb.max.z) / 2) glEnd() glBegin(GL_POINTS) glVertex(0, 0, 0) glEnd() self.draw_aabb(self.aabb) glPopMatrix()
def set_view_lerp(self, dt): global tickrate dt *= tickrate position = vector.lerp(self.old_position, self.position, dt) self.camera.set(vector.vec3(position) + vector.vec3(0, 0, 64))
def dispverts_of(self, face): verts = self.verts_of(face) verts = self.verts_check(face, verts) if len(verts) < 4: return [] if face['dispinfo'] == -1: return verts dispinfo = self.DISP_INFO[face['dispinfo']] start = list(dispinfo['startPosition']) #rounding errors throw compares start = [round(x, 1) for x in start] round_verts = [] for vert in verts: round_verts.append([round(x, 1) for x in vert]) if start in round_verts: index = round_verts.index(start) verts = verts[index:] + verts[:index] A = vector.vec3(*verts[0]) B = vector.vec3(*verts[1]) C = vector.vec3(*verts[2]) D = vector.vec3(*verts[3]) AD = D - A BC = C - B verts = [] power = dispinfo['power'] power2 = 2 ** power start = dispinfo['DispVertStart'] stop = dispinfo['DispVertStart'] + (power2 + 1) ** 2 for index, dispvert in enumerate(self.DISP_VERTS[start:stop]): t1 = index % (power2 + 1) / power2 t2 = index // (power2 + 1) / power2 baryvert = vector.lerp(A + (AD * t1), B + (BC * t1), t2) dispvert = [x * dispvert['dist'] for x in dispvert['vec']] verts.append([a + b for a, b in zip(baryvert, dispvert)]) #assemble tris power2A = power2 + 1 power2B = power2 + 2 power2C = power2 + 3 tri_verts = [] for line in range(power2): line_offset = power2A * line for block in range(2 ** (power - 1)): offset = line_offset + 2 * block if line % 2 == 0: tri_verts.append(verts[offset + 0]) tri_verts.append(verts[offset + power2A]) tri_verts.append(verts[offset + 1]) tri_verts.append(verts[offset + power2A]) tri_verts.append(verts[offset + power2B]) tri_verts.append(verts[offset + 1]) tri_verts.append(verts[offset + power2B]) tri_verts.append(verts[offset + power2C]) tri_verts.append(verts[offset + 1]) tri_verts.append(verts[offset + power2C]) tri_verts.append(verts[offset + 2]) tri_verts.append(verts[offset + 1]) else: tri_verts.append(verts[offset + 0]) tri_verts.append(verts[offset + power2A]) tri_verts.append(verts[offset + power2B]) tri_verts.append(verts[offset + 1]) tri_verts.append(verts[offset + 0]) tri_verts.append(verts[offset + power2B]) tri_verts.append(verts[offset + 2]) tri_verts.append(verts[offset + 1]) tri_verts.append(verts[offset + power2B]) tri_verts.append(verts[offset + power2C]) tri_verts.append(verts[offset + 2]) tri_verts.append(verts[offset + power2B]) return tri_verts
# indices > vertices > vectors A = vector.vec3(*vertices[rows[0][0]]) B = vector.vec3(*vertices[rows[0][-1]]) C = vector.vec3(*vertices[rows[-1][-1]]) D = vector.vec3(*vertices[rows[-1][0]]) AD = D - A BC = C - B vector_rows = [] # rows are nice and easy to split! # use vector.lerp for boundaries between disps of different powers for x, row in enumerate(rows): x = x / 4 # assuming power 2 vector_rows.append([]) for y, index in enumerate(row): y = y / 4 # assuming power 2 bary_point = vector.lerp(A + (AD * x), B + (BC * x), y) point = vertices[index] - bary_point vector_rows[-1].append(point) with open("../mapsrc/test_disp.vmf") as target_file: base_vmf = vmf_tool.parse_lines(target_file.readlines()) scope = vmf_tool.scope(["world", "solid", "sides", 0, "dispinfo"]) # ^ solid 0, side 0 scope.add("startposition") scope.set_in(base_vmf, f"[{A.x} {A.y} {A.z}]") scope.retreat() for i, row in enumerate(vector_rows): row_distances = [v.magnitude() for v in row] # 1 per vert row_normals = [ v / w if w != 0 else vector.vec3() for v, w in zip(row, row_distances)