def __init__(self, shape, pts, texcoords, faces, normals=None, smooth=True): """Generate a vertex buffer to hold data and indices. If no normals are provided then these are generated. Arguments: *shape* Shape object that this Buffer is a child of *pts* array of vertices tuples i.e. [(x0,y0,z0), (x1,y1,z1),...] *texcoords* array of texture (uv) coordinates tuples i.e. [(u0,v0), (u1,v1),...] *faces* array of indices (of pts array) defining triangles i.e. [(a0,b0,c0), (a1,b1,c1),...] Keyword arguments: *normals* array of vector component tuples defining normals at each vertex i.e. [(x0,y0,z0), (x1,y1,z1),...] *smooth* if calculating normals then average normals for all faces meeting at this vertex, otherwise just use first (for speed). """ super(Buffer, self).__init__() # Uniform variables all in one array! self.unib = (c_float * 9)(0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 0.0) """ pass to shader array of vec3 uniform variables: ===== ============================ ==== == vec3 description python ----- ---------------------------- ------- index from to ===== ============================ ==== == 0 ntile, shiny, blend 0 2 1 material 3 5 2 umult, vmult (only 2 used) 6 7 ===== ============================ ==== == """ self.shape = shape if not normals: LOGGER.debug("Calculating normals ...") normals = [[] for p in pts] # Calculate normals. for f in faces: a, b, c = f[0:3] ab = Utility.vec_sub(pts[a], pts[b]) bc = Utility.vec_sub(pts[a], pts[c]) n = tuple(Utility.vec_normal(Utility.vec_cross(ab, bc))) for x in f[0:3]: normals[x].append(n) for i, n in enumerate(normals): if n: if smooth: norms = [sum(v[k] for v in n) for k in range(3)] else: # This should be slightly faster for large shapes norms = [n[0][k] for k in range(3)] normals[i] = tuple(Utility.vec_normal(norms)) else: normals[i] = 0, 0, 0.01 # keep a copy for speeding up the collision testing of ElevationMap self.vertices = pts self.normals = normals self.tex_coords = texcoords self.indices = faces self.material = (0.5, 0.5, 0.5, 1.0) # Pack points,normals and texcoords into tuples and convert to ctype floats. points = [p + n + t for p, n, t in zip(pts, normals, texcoords)] self.array_buffer = c_floats(list(itertools.chain(*points))) self.ntris = len(faces) points = [f[0:3] for f in faces] self.element_array_buffer = c_shorts(list(itertools.chain(*points)))
def _lathe(self, path, sides=12, rise=0.0, loops=1.0): """Returns a Buffer object by rotating the points defined in path. Arguments: *path* An array of points [(x0, y0), (x1, y1) ...] to rotate around the y axis. Keyword arguments: *sides* Number of sides to divide each rotation into. *rise* Amount to increment the path y values for each rotation (ie helix) *loops* Number of times to rotate the path by 360 (ie helix). """ self.sides = sides s = len(path) rl = int(self.sides * loops) pn = 0 pp = 0 tcx = 1.0 / self.sides pr = (pi / self.sides) * 2.0 rdiv = rise / rl # Find largest and smallest y of the path used for stretching the texture miny = path[0][1] maxy = path[s - 1][1] for p in range(s): if path[p][1] < miny: miny = path[p][1] if path[p][1] > maxy: maxy = path[p][1] verts = [] norms = [] idx = [] tex_coords = [] opx = path[0][0] opy = path[0][1] for p in range(s): px = path[p][0] * 1.0 py = path[p][1] * 1.0 tcy = 1.0 - ((py - miny) / (maxy - miny)) # Normalized 2D vector between path points dx, dy = Utility.vec_normal(Utility.vec_sub((px, py), (opx, opy))) for r in range(0, rl): sinr = sin(pr * r) cosr = cos(pr * r) verts.append((px * sinr, py, px * cosr)) norms.append((-sinr * dy, dx, -cosr * dy)) tex_coords.append((1.0 - tcx * r, tcy)) py += rdiv # Last path profile (tidies texture coords). verts.append((0, py, px)) norms.append((0, dx, -dy)) tex_coords.append((0, tcy)) if p < s - 1: pn += (rl + 1) for r in range(rl): idx.append((pp + r + 1, pp + r, pn + r)) idx.append((pn + r, pn + r + 1, pp + r + 1)) pp += (rl + 1) opx = px opy = py return Buffer(self, verts, tex_coords, idx, norms)
def _lathe(self, path, sides=12, rise=0.0, loops=1.0): """Returns a Buffer object by rotating the points defined in path. Arguments: *path* An array of points [(x0, y0), (x1, y1) ...] to rotate around the y axis. Keyword arguments: *sides* Number of sides to divide each rotation into. *rise* Amount to increment the path y values for each rotation (ie helix) *loops* Number of times to rotate the path by 360 (ie helix). """ self.sides = sides s = len(path) rl = int(self.sides * loops) pn = 0 pp = 0 tcx = 1.0 / self.sides pr = (pi / self.sides) * 2.0 rdiv = rise / rl # Find largest and smallest y of the path used for stretching the texture miny = path[0][1] maxy = path[s-1][1] for p in range(s): if path[p][1] < miny: miny = path[p][1] if path[p][1] > maxy: maxy = path[p][1] verts = [] norms = [] idx = [] tex_coords = [] opx = path[0][0] opy = path[0][1] for p in range(s): px = path[p][0] * 1.0 py = path[p][1] * 1.0 tcy = 1.0 - ((py - miny) / (maxy - miny)) # Normalized 2D vector between path points dx, dy = Utility.vec_normal(Utility.vec_sub((px, py), (opx, opy))) for r in range (0, rl): sinr = sin(pr * r) cosr = cos(pr * r) verts.append((px * sinr, py, px * cosr)) norms.append((-sinr * dy, dx, -cosr * dy)) tex_coords.append((1.0 - tcx * r, tcy)) py += rdiv # Last path profile (tidies texture coords). verts.append((0, py, px)) norms.append((0, dx, -dy)) tex_coords.append((0, tcy)) if p < s - 1: pn += (rl + 1) for r in range(rl): idx.append((pp + r + 1, pp + r, pn + r)) idx.append((pn + r, pn + r + 1, pp + r + 1)) pp += (rl + 1) opx = px opy = py return Buffer(self, verts, tex_coords, idx, norms)
def _lathe(self, path, sides=12, rise=0.0, loops=1.0): """Returns a Buffer object by rotating the points defined in path. Arguments: *path* An array of points [(x0, y0), (x1, y1) ...] to rotate around the y axis. Keyword arguments: *sides* Number of sides to divide each rotation into. *rise* Amount to increment the path y values for each rotation (ie helix) *loops* Number of times to rotate the path by 360 (ie helix). """ self.sides = sides s = len(path) rl = int(self.sides * loops) pn = 0 pp = 0 tcx = 1.0 / self.sides pr = (pi / self.sides) * 2.0 rdiv = rise / rl # Find length of the path path_len = 0.0 for p in range(1, s): path_len += ((path[p][0] - path[p-1][0])**2 + (path[p][1] - path[p-1][1])**2)**0.5 verts = [] norms = [] idx = [] tex_coords = [] opx = path[0][0] opy = path[0][1] tcy = 0.0 for p in range(s): px = path[p][0] * 1.0 py = path[p][1] * 1.0 if p > 0: tcy += ((path[p][0] - path[p-1][0])**2 + (path[p][1] - path[p-1][1])**2)**0.5 / path_len # Normalized 2D vector between path points if p == 0: ipx, ipy = path[1][0] * 1.0, path[1][1] * 1.0 else: ipx, ipy = px, py dx, dy = Utility.vec_normal(Utility.vec_sub((ipx, ipy), (opx, opy))) for r in range (0, rl + 1): sinr = sin(pr * r) cosr = cos(pr * r) verts.append((px * sinr, py, px * cosr)) norms.append((-sinr * dy, dx, -cosr * dy)) tex_coords.append((1.0 - tcx * r, tcy)) py += rdiv if p < s - 1: pn += (rl + 1) for r in range(rl): idx.append((pp + r + 1, pp + r, pn + r)) idx.append((pn + r, pn + r + 1, pp + r + 1)) pp += (rl + 1) opx = px opy = py return Buffer(self, verts, tex_coords, idx, norms)
def _lathe(self, path, sides=12, rise=0.0, loops=1.0): """Returns a Buffer object by rotating the points defined in path. Arguments: *path* An array of points [(x0, y0), (x1, y1) ...] to rotate around the y axis. Keyword arguments: *sides* Number of sides to divide each rotation into. *rise* Amount to increment the path y values for each rotation (ie helix) *loops* Number of times to rotate the path by 360 (ie helix). """ self.sides = sides s = len(path) rl = int(self.sides * loops) pn = 0 pp = 0 tcx = 1.0 / self.sides pr = (pi / self.sides) * 2.0 rdiv = rise / rl # Find length of the path path_len = 0.0 for p in range(1, s): path_len += ((path[p][0] - path[p - 1][0])**2 + (path[p][1] - path[p - 1][1])**2)**0.5 verts = [] norms = [] idx = [] tex_coords = [] opx = path[0][0] opy = path[0][1] tcy = 0.0 for p in range(s): px = path[p][0] * 1.0 py = path[p][1] * 1.0 if p > 0: tcy += ((path[p][0] - path[p - 1][0])**2 + (path[p][1] - path[p - 1][1])**2)**0.5 / path_len # Normalized 2D vector between path points if p == 0: ipx, ipy = path[1][0] * 1.0, path[1][1] * 1.0 else: ipx, ipy = px, py dx, dy = Utility.vec_normal(Utility.vec_sub((ipx, ipy), (opx, opy))) for r in range(0, rl + 1): sinr = sin(pr * r) cosr = cos(pr * r) verts.append((px * sinr, py, px * cosr)) norms.append((-sinr * dy, dx, -cosr * dy)) tex_coords.append((1.0 - tcx * r, tcy)) py += rdiv if p < s - 1: pn += (rl + 1) for r in range(rl): idx.append((pp + r + 1, pp + r, pn + r)) idx.append((pn + r, pn + r + 1, pp + r + 1)) pp += (rl + 1) opx = px opy = py return Buffer(self, verts, tex_coords, idx, norms)
def __init__(self, shape, pts, texcoords, faces, normals=None, smooth=True): """Generate a vertex buffer to hold data and indices. If no normals are provided then these are generated. Arguments: *shape* Shape object that this Buffer is a child of *pts* array of vertices tuples i.e. [(x0,y0,z0), (x1,y1,z1),...] *texcoords* array of texture (uv) coordinates tuples i.e. [(u0,v0), (u1,v1),...] *faces* array of indices (of pts array) defining triangles i.e. [(a0,b0,c0), (a1,b1,c1),...] Keyword arguments: *normals* array of vector component tuples defining normals at each vertex i.e. [(x0,y0,z0), (x1,y1,z1),...] *smooth* if calculating normals then average normals for all faces meeting at this vertex, otherwise just use first (for speed). """ super(Buffer, self).__init__() # Uniform variables all in one array! self.unib = (c_float * 12)(0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) """ pass to shader array of vec3 uniform variables: ===== ============================ ==== == vec3 description python ----- ---------------------------- ------- index from to ===== ============================ ==== == 0 ntile, shiny, blend 0 2 1 material 3 5 2 umult, vmult (only 2 used) 6 7 3 u_off, v_off (only 2 used) 9 10 ===== ============================ ==== == """ self.shape = shape if not normals: LOGGER.debug("Calculating normals ...") normals = [[] for p in pts] # Calculate normals. for f in faces: a, b, c = f[0:3] ab = Utility.vec_sub(pts[a], pts[b]) bc = Utility.vec_sub(pts[a], pts[c]) n = tuple(Utility.vec_normal(Utility.vec_cross(ab, bc))) for x in f[0:3]: normals[x].append(n) for i, n in enumerate(normals): if n: if smooth: norms = [sum(v[k] for v in n) for k in range(3)] else: # This should be slightly faster for large shapes norms = [n[0][k] for k in range(3)] normals[i] = tuple(Utility.vec_normal(norms)) else: normals[i] = 0, 0, 0.01 # keep a copy for speeding up the collision testing of ElevationMap self.vertices = pts self.normals = normals self.tex_coords = texcoords self.indices = faces self.material = (0.5, 0.5, 0.5, 1.0) # Pack points,normals and texcoords into tuples and convert to ctype floats. points = [p + n + t for p, n, t in zip(pts, normals, texcoords)] self.array_buffer = c_floats(list(itertools.chain(*points))) self.ntris = len(faces) points = [f[0:3] for f in faces] self.element_array_buffer = c_shorts(list(itertools.chain(*points)))