def points_random_3d(count, range_x=(-10.0, 10.0), range_y=(-10.0, 10.0), range_z=(-10.0, 10.0), seed=None): """ Generates random positions :param count: Number of points :param range_x: min-max range for x axis :param range_y: min-max range for y axis :param range_z: min-max range for z axis :param seed: The random seed to be used """ random.seed(seed) def gen(): for i in range(count): yield random.uniform(*range_x) yield random.uniform(*range_y) yield random.uniform(*range_z) data = numpy.fromiter(gen(), count=count * 3, dtype=numpy.float32) pos = VBO(data) vao = VAO("geometry:points_random_3d", mode=GL.GL_POINTS) vao.add_array_buffer(GL.GL_FLOAT, pos) vao.map_buffer(pos, "in_position", 3) vao.build() return vao
def sphere(radius=0.5, sectors=32, rings=16): """ Generate a sphere :param radius: Radius or the sphere :param rings: number or horizontal rings :param sectors: number of vertical segments :return: VAO containing the sphere """ R = 1.0 / (rings - 1) S = 1.0 / (sectors - 1) vertices = [0] * (rings * sectors * 3) normals = [0] * (rings * sectors * 3) uvs = [0] * (rings * sectors * 2) v, n, t = 0, 0, 0 for r in range(rings): for s in range(sectors): y = math.sin(-math.pi / 2 + math.pi * r * R) x = math.cos(2 * math.pi * s * S) * math.sin(math.pi * r * R) z = math.sin(2 * math.pi * s * S) * math.sin(math.pi * r * R) uvs[t] = s * S uvs[t + 1] = r * R vertices[v] = x * radius vertices[v + 1] = y * radius vertices[v + 2] = z * radius normals[n] = x normals[n + 1] = y normals[n + 2] = z t += 2 v += 3 n += 3 indices = [0] * rings * sectors * 6 i = 0 for r in range(rings - 1): for s in range(sectors - 1): indices[i] = r * sectors + s indices[i + 1] = (r + 1) * sectors + (s + 1) indices[i + 2] = r * sectors + (s + 1) indices[i + 3] = r * sectors + s indices[i + 4] = (r + 1) * sectors + s indices[i + 5] = (r + 1) * sectors + (s + 1) i += 6 vbo_vertices = VBO(numpy.array(vertices, dtype=numpy.float32)) vbo_normals = VBO(numpy.array(normals, dtype=numpy.float32)) vbo_uvs = VBO(numpy.array(uvs, dtype=numpy.float32)) vbo_element = VBO(numpy.array(indices, dtype=numpy.uint32), target="GL_ELEMENT_ARRAY_BUFFER") vao = VAO("sphere") # VBOs vao.add_array_buffer(GL.GL_FLOAT, vbo_vertices) vao.add_array_buffer(GL.GL_FLOAT, vbo_normals) vao.add_array_buffer(GL.GL_FLOAT, vbo_uvs) # Mapping vao.map_buffer(vbo_vertices, "in_position", 3) vao.map_buffer(vbo_normals, "in_normal", 3) vao.map_buffer(vbo_uvs, "in_uv", 2) # Index vao.set_element_buffer(GL.GL_UNSIGNED_INT, vbo_element) vao.build() return vao
def quad_2d(width, height, xpos=0.0, ypos=0.0): """ Creates a 2D quad VAO using 2 triangles. :param width: Width of the quad :param height: Height of the quad :param xpos: Center position x :param ypos: Center position y """ pos = VBO( numpy.array([ xpos - width / 2.0, ypos + height / 2.0, 0.0, xpos - width / 2.0, ypos - height / 2.0, 0.0, xpos + width / 2.0, ypos - height / 2.0, 0.0, xpos - width / 2.0, ypos + height / 2.0, 0.0, xpos + width / 2.0, ypos - height / 2.0, 0.0, xpos + width / 2.0, ypos + height / 2.0, 0.0, ], dtype=numpy.float32)) normals = VBO( numpy.array([ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, ], dtype=numpy.float32)) uvs = VBO( numpy.array([ 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, ], dtype=numpy.float32)) vao = VAO("geometry:quad", mode=GL.GL_TRIANGLES) vao.add_array_buffer(GL.GL_FLOAT, pos) vao.add_array_buffer(GL.GL_FLOAT, normals) vao.add_array_buffer(GL.GL_FLOAT, uvs) vao.map_buffer(pos, "in_position", 3) vao.map_buffer(normals, "in_normal", 3) vao.map_buffer(uvs, "in_uv", 2) vao.build() return vao
def plane_xz(size=(10, 10), resolution=(10, 10)): """ Generates a plane on the xz axis of a specific size and resolution :param size: (x, y) tuple :param resolution: (x, y) tuple :return: VAO """ sx, sz = size rx, rz = resolution dx, dz = sx / rx, sz / rz # step ox, oz = -sx / 2, -sz / 2 # start offset def gen_pos(): for z in range(rz): for x in range(rx): yield ox + x * dx yield 0 yield oz + z * dz def gen_uv(): for z in range(rz): for x in range(rx): yield x / (rx - 1) yield 1 - z / (rz - 1) def gen_normal(): for z in range(rx * rz): yield 0.0 yield 1.0 yield 0.0 def gen_index(): for z in range(rz - 1): for x in range(rx - 1): # quad poly left yield z * rz + x yield z * rz + x + 1 yield z * rz + x + rx # quad poly right yield z * rz + x + rx yield z * rz + x + 1 yield z * rz + x + rx + 1 pos_data = numpy.fromiter(gen_pos(), dtype=numpy.float32) position_vbo = VBO(pos_data) uv_data = numpy.fromiter(gen_uv(), dtype=numpy.float32) uv_vbo = VBO(uv_data) normal_data = numpy.fromiter(gen_normal(), dtype=numpy.float32) normal_vbo = VBO(normal_data) index_data = numpy.fromiter(gen_index(), dtype=numpy.uint32) index_vbo = VBO(index_data, target="GL_ELEMENT_ARRAY_BUFFER") vao = VAO("plane_xz", mode=GL.GL_TRIANGLES) vao.add_array_buffer(GL.GL_FLOAT, position_vbo) vao.add_array_buffer(GL.GL_FLOAT, uv_vbo) vao.add_array_buffer(GL.GL_FLOAT, normal_vbo) vao.map_buffer(position_vbo, "in_position", 3) vao.map_buffer(uv_vbo, "in_uv", 2) vao.map_buffer(normal_vbo, "in_normal", 3) vao.set_element_buffer(GL.GL_UNSIGNED_INT, index_vbo) vao.build() return vao
def cube(width, height, depth, normals=True, uvs=True): """ Generates a cube centered at 0, 0, 0 :param width: Width of the cube :param height: height of the cube :param depth: depth of the bubs :param normals: (bool) Include normals :param uvs: (bool) include uv coordinates :return: VAO representing the cube """ width, height, depth = width / 2, height / 2, depth / 2 pos = VBO( numpy.array([ width, -height, depth, width, height, depth, -width, -height, depth, width, height, depth, -width, height, depth, -width, -height, depth, width, -height, -depth, width, height, -depth, width, -height, depth, width, height, -depth, width, height, depth, width, -height, depth, width, -height, -depth, width, -height, depth, -width, -height, depth, width, -height, -depth, -width, -height, depth, -width, -height, -depth, -width, -height, depth, -width, height, depth, -width, height, -depth, -width, -height, depth, -width, height, -depth, -width, -height, -depth, width, height, -depth, width, -height, -depth, -width, -height, -depth, width, height, -depth, -width, -height, -depth, -width, height, -depth, width, height, -depth, -width, height, -depth, width, height, depth, -width, height, -depth, -width, height, depth, width, height, depth, ], dtype=numpy.float32)) if normals: normals = VBO( numpy.array([ -0, 0, 1, -0, 0, 1, -0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, -0, 0, -1, -0, 0, -1, -0, 0, -1, -0, 0, -1, -0, 0, -1, -0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, ], dtype=numpy.float32)) if uvs: uvs = VBO( numpy.array([ 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0 ], dtype=numpy.float32)) vao = VAO("geometry:cube") # Add buffers vao.add_array_buffer(GL.GL_FLOAT, pos) if normals: vao.add_array_buffer(GL.GL_FLOAT, normals) if uvs: vao.add_array_buffer(GL.GL_FLOAT, uvs) # Map buffers vao.map_buffer(pos, "in_position", 3) if normals: vao.map_buffer(normals, "in_normal", 3) if uvs: vao.map_buffer(uvs, "in_uv", 2) vao.build() return vao