def update_objects(self) -> None: """Update proxy objects when object list changes. Called from GLCanvas upon core_o_list_changed signal. """ self._meshes.clear() for index, object3d in enumerate(self.core.objects): vao = glGenVertexArrays(1) glBindVertexArray(vao) vertices: glm.array = None normals: glm.array = None indices: glm.array = None if object3d.__class__ == CylinderObject3D: vertices, normals, indices = get_cylinder_vertices( object3d, 24) elif object3d.__class__ == OBJObject3D: vertices = object3d.vertices normals = object3d.normals indices = object3d.indices elif object3d.__class__ == AABBObject3D: vertices, normals, indices = get_aabb_vertices(object3d) else: continue vbo = glGenBuffers(3) # vertices glBindBuffer(GL_ARRAY_BUFFER, vbo[0]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices.ptr, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) # normals glBindBuffer(GL_ARRAY_BUFFER, vbo[1]) glBufferData(GL_ARRAY_BUFFER, normals.nbytes, normals.ptr, GL_STATIC_DRAW) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) # indices glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]) glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices.ptr, GL_STATIC_DRAW) self._meshes.append( Mesh(color=vec4(0.8, 0.8, 0.8, 0.85), count=indices.length * 3, vao=vao, object_id=index, selected=False)) glBindVertexArray(0)
def create_vaos(self) -> None: """Bind VAOs to define vertex data.""" self._vao_gridlines, self._vao_bounding_box = glGenVertexArrays(2) vbo = glGenBuffers(5) vertices, colors = self._get_gridlines() self._count_gridlines = vertices.size // 3 glBindVertexArray(self._vao_gridlines) # gridlines glBindBuffer(GL_ARRAY_BUFFER, vbo[0]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vbo[1]) glBufferData(GL_ARRAY_BUFFER, colors.nbytes, colors, GL_STATIC_DRAW) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) # --- points, indices = self._get_bounding_box() self._count_bounding_box = indices.length glBindVertexArray(self._vao_bounding_box) # bounding box glBindBuffer(GL_ARRAY_BUFFER, vbo[2]) glBufferData(GL_ARRAY_BUFFER, points.nbytes, points, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vbo[3]) glBufferData(GL_ARRAY_BUFFER, points.nbytes, points, GL_STATIC_DRAW) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12)) glEnableVertexAttribArray(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[4]) glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices.ptr, GL_STATIC_DRAW) self._axes.create_vaos() glBindVertexArray(0) glDeleteBuffers(5, vbo)
def _render_bounding_box(self) -> None: """Render bounding box.""" if self._vao_bounding_box is None: return glBindVertexArray(self._vao_bounding_box) glDrawElements(GL_LINES, self._count_bounding_box, GL_UNSIGNED_INT, ctypes.c_void_p(0))
def create_vaos(self) -> None: """Bind VAOs to define vertex data.""" vbo = glGenBuffers(1) # initialize camera box # TODO: update to obj file vertices = glm.array( vec3(-1.0, -0.5, -1.0), # bottom vec3(-1.0, -0.5, 1.0), vec3(-1.0, 0.5, 1.0), vec3(-1.0, 0.5, -1.0), vec3(1.0, -0.5, -1.0), # right vec3(-1.0, -0.5, -1.0), vec3(-1.0, 0.5, -1.0), vec3(1.0, 0.5, -1.0), vec3(1.0, -0.5, 1.0), # top vec3(1.0, -0.5, -1.0), vec3(1.0, 0.5, -1.0), vec3(1.0, 0.5, 1.0), vec3(-1.0, -0.5, 1.0), # left vec3(1.0, -0.5, 1.0), vec3(1.0, 0.5, 1.0), vec3(-1.0, 0.5, 1.0), vec3(1.0, 0.5, -1.0), # back vec3(-1.0, 0.5, -1.0), vec3(-1.0, 0.5, 1.0), vec3(1.0, 0.5, 1.0), vec3(-1.0, -0.5, -1.0), # front vec3(1.0, -0.5, -1.0), vec3(1.0, -0.5, 1.0), vec3(-1.0, -0.5, 1.0), ) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices.ptr, GL_STATIC_DRAW) self._vaos['box'] = glGenVertexArrays(1) glBindVertexArray(self._vaos['box']) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) self._vaos['camera'] = glGenVertexArrays(1) glBindVertexArray(self._vaos['camera']) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0)
def render(self) -> None: """Render proxy objects to canvas with a diffuse shader.""" if not self.init(): return proj = self.parent.projection_matrix view = self.parent.modelview_matrix glUseProgram(self.parent.shaders['diffuse']) glUniformMatrix4fv(0, 1, GL_FALSE, glm.value_ptr(proj)) glUniformMatrix4fv(1, 1, GL_FALSE, glm.value_ptr(view)) for mesh in self._meshes: glBindVertexArray(mesh.vao) glUniform4fv(2, 1, glm.value_ptr(mesh.color)) glUniform1i(3, int(mesh.selected)) glDrawElements(GL_TRIANGLES, mesh.count, GL_UNSIGNED_INT, ctypes.c_void_p(0)) glBindVertexArray(0) glUseProgram(0)
def render_for_picking(self) -> None: """Render proxy objects for picking pass.""" if not self.init(): return proj = self.parent.projection_matrix view = self.parent.modelview_matrix glUseProgram(self.parent.shaders['solid']) glUniformMatrix4fv(0, 1, GL_FALSE, glm.value_ptr(proj)) glUniformMatrix4fv(1, 1, GL_FALSE, glm.value_ptr(view)) for mesh in self._meshes: glBindVertexArray(mesh.vao) glUniform1i(2, MAX_ID - mesh.object_id) glDrawElements(GL_TRIANGLES, mesh.count, GL_UNSIGNED_INT, ctypes.c_void_p(0)) glBindVertexArray(0) glUseProgram(0) glBindVertexArray(0) glUseProgram(0)
def _bind_vao_mat_col_id(self, vao, mat: glm.array, col: glm.array, ids: glm.array) -> None: vbo = glGenBuffers(3) glBindBuffer(GL_ARRAY_BUFFER, vbo[0]) glBufferData(GL_ARRAY_BUFFER, mat.nbytes, mat.ptr, GL_STATIC_DRAW) glBindVertexArray(vao) # modelmats glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 64, ctypes.c_void_p(0)) glEnableVertexAttribArray(3) glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 64, ctypes.c_void_p(16)) # sizeof(glm::vec4) glVertexAttribDivisor(3, 1) glEnableVertexAttribArray(4) glVertexAttribDivisor(4, 1) glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 64, ctypes.c_void_p(32)) # 2 * sizeof(glm::vec4) glEnableVertexAttribArray(5) glVertexAttribDivisor(5, 1) glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 64, ctypes.c_void_p(48)) # 3 * sizeof(glm::vec4) glEnableVertexAttribArray(6) glVertexAttribDivisor(6, 1) # colors glBindBuffer(GL_ARRAY_BUFFER, vbo[1]) glBufferData(GL_ARRAY_BUFFER, col.nbytes, col.ptr, GL_STATIC_DRAW) glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(7) glVertexAttribDivisor(7, 1) # ids for picking glBindBuffer(GL_ARRAY_BUFFER, vbo[2]) glBufferData(GL_ARRAY_BUFFER, ids.nbytes, ids.ptr, GL_STATIC_DRAW) # it should be GL_INT here, yet only GL_FLOAT works. huh?? glVertexAttribPointer(8, 1, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(8) glVertexAttribDivisor(8, 1) glEnableVertexAttribArray(0) glBindVertexArray(0)
def update_action_vaos(self) -> None: """Update VAOs when action list changes.""" self._vaos['line'].clear() self._vaos['point'].clear() # --- bind data for lines --- for key, value in self._items['line'].items(): # ignore if 1 or fewer points if len(value) <= 1: continue points = glm.array([vec3(mat[1][3]) for mat in value]) vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, points.nbytes, points.ptr, GL_STATIC_DRAW) vao = glGenVertexArrays(1) glBindVertexArray(vao) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) self._vaos['line'][key] = vao glBindVertexArray(0) # --- bind data for points --- point_mats: glm.array = None point_cols: glm.array = None point_ids: glm.array = None scale = glm.scale(mat4(), vec3(3, 3, 3)) for key, value in self._items['point'].items(): new_mats = glm.array([p[1] * scale for p in value]) color = shade_color(vec4(self.colors[key % len(self.colors)]), -0.3) new_cols = glm.array([color] * len(value)) # if point is selected, darken its color for i, v in enumerate(value): # un-offset ids if (v[0] - self._num_devices) in self.core.selected_points: new_cols[i] = shade_color(vec4(new_cols[i]), 0.6) new_ids = glm.array.from_numbers(ctypes.c_int, *(p[0] for p in value)) point_mats = new_mats if point_mats is None else point_mats.concat( new_mats) point_cols = new_cols if point_cols is None else point_cols.concat( new_cols) point_ids = new_ids if point_ids is None else point_ids.concat( new_ids) # we're done if no points to set if not self._items['point']: return self._num_points = sum(len(i) for i in self._items['point'].values()) self._bind_vao_mat_col_id(self._vaos['box'], point_mats, point_cols, point_ids)
def create_vaos(self) -> None: """Bind VAOs to define vertex data.""" self._vao_axes, *self._vao_arrows = glGenVertexArrays(3) vbo = glGenBuffers(5) build_dimensions = self.parent.build_dimensions x = build_dimensions[0] - build_dimensions[3], build_dimensions[3] y = build_dimensions[1] - build_dimensions[4], build_dimensions[4] z = build_dimensions[2] - build_dimensions[5], build_dimensions[5] points = np.array([ x[0], 0.0, 0.0, 1.0, 0.0, 0.0, -x[1], 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, y[0], 0.0, 0.0, 1.0, 0.0, 0.0, -y[1], 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, z[0], 0.0, 0.0, 1.0, 0.0, 0.0, -z[1], 0.0, 0.0, 1.0, ], dtype=np.float32) glBindVertexArray(self._vao_axes) # colored axes lines glBindBuffer(GL_ARRAY_BUFFER, vbo[0]) glBufferData(GL_ARRAY_BUFFER, points.nbytes, points, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vbo[1]) glBufferData(GL_ARRAY_BUFFER, points.nbytes, points, GL_STATIC_DRAW) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12)) glEnableVertexAttribArray(1) # --- vertices, colors = self._get_cones() glBindVertexArray(self._vao_arrows[0]) # colored axes arrows, cone glBindBuffer(GL_ARRAY_BUFFER, vbo[2]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vbo[3]) glBufferData(GL_ARRAY_BUFFER, colors.nbytes, colors, GL_STATIC_DRAW) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) # --- vertices[0] = x[0] vertices[17 * 3 + 1] = y[0] vertices[17 * 6 + 2] = z[0] glBindVertexArray(self._vao_arrows[1]) # colored axes arrows, base glBindBuffer(GL_ARRAY_BUFFER, vbo[4]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vbo[3]) glBufferData(GL_ARRAY_BUFFER, colors.nbytes, colors, GL_STATIC_DRAW) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) # --- glBindVertexArray(0) glDeleteBuffers(5, vbo)
def create_vaos(self) -> None: """Bind VAOs to define vertex data.""" self._vaos['box'], self._vaos['side'], \ self._vaos['top'] = glGenVertexArrays(3) vbo = glGenBuffers(4) vertices = np.array( [ -0.5, -1.0, -1.0, # bottom 0.5, -1.0, -1.0, 0.5, -1.0, 1.0, -0.5, -1.0, 1.0, -0.5, 1.0, -1.0, # right 0.5, 1.0, -1.0, 0.5, -1.0, -1.0, -0.5, -1.0, -1.0, -0.5, 1.0, 1.0, # top 0.5, 1.0, 1.0, 0.5, 1.0, -1.0, -0.5, 1.0, -1.0, -0.5, -1.0, 1.0, # left 0.5, -1.0, 1.0, 0.5, 1.0, 1.0, -0.5, 1.0, 1.0, 0.5, 1.0, -1.0, # back 0.5, 1.0, 1.0, 0.5, -1.0, 1.0, 0.5, -1.0, -1.0, -0.5, -1.0, -1.0, # front -0.5, -1.0, 1.0, -0.5, 1.0, 1.0, -0.5, 1.0, -1.0, ], dtype=np.float32) glBindVertexArray(self._vaos['box']) glBindBuffer(GL_ARRAY_BUFFER, vbo[0]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) # --- below are unused vaos for rendering a cylinder (for the camerae model) # keep them, but TODO implement general object class thetas = np.linspace(0, 2 * np.pi, 24, endpoint=True) y = np.cos(thetas) * 0.7 z = np.sin(thetas) * 0.7 vertices = np.zeros(6 * 24, dtype=np.float32) vertices[::3] = np.tile(np.array([1.0, 0.5], dtype=np.float32), 24) vertices[1::3] = np.repeat(y, 2) vertices[2::3] = np.repeat(z, 2) glBindVertexArray(self._vaos['side']) glBindBuffer(GL_ARRAY_BUFFER, vbo[1]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) # --- vertices = np.concatenate( (np.array([1.0, 0.0, 0.0]), vertices)).astype(np.float32) indices = np.insert(np.arange(24) * 2 + 1, 0, 0).astype(np.uint16) glBindVertexArray(self._vaos['top']) glBindBuffer(GL_ARRAY_BUFFER, vbo[2]) glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]) glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, GL_STATIC_DRAW) # --- glBindVertexArray(0) glDeleteBuffers(4, vbo)