Source code for yt_idv.scene_components.blocks

from math import ceil, floor

import numpy as np
import traitlets
from OpenGL import GL

from yt_idv.gui_support import add_popup_help
from yt_idv.opengl_support import TransferFunctionTexture
from yt_idv.scene_components.base_component import SceneComponent
from yt_idv.scene_data.block_collection import BlockCollection
from yt_idv.shader_objects import component_shaders


[docs]class BlockRendering(SceneComponent): """ A class that renders block data. It may do this in one of several ways, including mesh outline. This allows us to render a single collection of blocks multiple times in a single scene and to separate out the memory handling from the display. """ name = "block_rendering" data = traitlets.Instance(BlockCollection) box_width = traitlets.CFloat(0.1) sample_factor = traitlets.CFloat(1.0) transfer_function = traitlets.Instance(TransferFunctionTexture) tf_min = traitlets.CFloat(0.0) tf_max = traitlets.CFloat(1.0) tf_log = traitlets.Bool(True) slice_position = traitlets.Tuple((0.5, 0.5, 0.5), trait=traitlets.CFloat()) slice_normal = traitlets.Tuple((1.0, 0.0, 0.0), trait=traitlets.CFloat()) priority = 10
[docs] def render_gui(self, imgui, renderer, scene): changed = super().render_gui(imgui, renderer, scene) _, sample_factor = imgui.slider_float( "Sample Factor", self.sample_factor, 1.0, 20.0 ) if _: self.sample_factor = sample_factor # Now, shaders shader_combos = list(sorted(component_shaders[self.name])) descriptions = [ component_shaders[self.name][_]["description"] for _ in shader_combos ] selected = shader_combos.index(self.render_method) _, shader_ind = imgui.listbox("Shader", selected, descriptions) if _: self.render_method = shader_combos[shader_ind] changed = changed or _ if imgui.button("Add Block Outline"): from ..scene_annotations.block_outline import BlockOutline block_outline = BlockOutline(data=self.data) scene.annotations.append(block_outline) if imgui.button("Add Grid Outline"): from ..scene_annotations.grid_outlines import GridOutlines from ..scene_data.grid_positions import GridPositions grids = self.data.data_source.ds.index.grids.tolist() gp = GridPositions(grid_list=grids) scene.data_objects.append(gp) scene.components.append(GridOutlines(data=gp)) if self.render_method == "transfer_function": # Now for the transfer function stuff imgui.image_button( self.transfer_function.texture_name, 256, 32, frame_padding=0 ) imgui.text("Right click and drag to change") update = False data = self.transfer_function.data.astype("f4") / 255 for i, c in enumerate("rgba"): imgui.plot_lines( f"## {c}", data[:, 0, i].copy(), scale_min=0.0, scale_max=1.0, graph_size=(256, 32), ) if imgui.is_item_hovered() and imgui.is_mouse_dragging(2): update = True dx, dy = renderer.io.mouse_delta dy = -dy mi = imgui.get_item_rect_min() ma = imgui.get_item_rect_max() x, y = renderer.io.mouse_pos x = x - mi.x y = (ma.y - mi.y) - (y - mi.y) xb1 = floor(min(x + dx, x) * data.shape[0] / (ma.x - mi.x)) xb2 = ceil(max(x + dx, x) * data.shape[0] / (ma.x - mi.x)) yv1 = y / (ma.y - mi.y) yv2 = (y + dy) / (ma.y - mi.y) yv1, yv2 = (max(min(_, 1.0), 0.0) for _ in (yv1, yv2)) if dx < 0: yv2, yv1 = yv1, yv2 xb1 -= 1 elif dx > 0: xb2 += 1 xb1 = max(0, xb1) xb2 = min(255, xb2) if renderer.io.key_shift: yv1 = yv2 = 1.0 elif renderer.io.key_ctrl: yv1 = yv2 = 0.0 data[xb1:xb2, 0, i] = np.mgrid[yv1 : yv2 : (xb2 - xb1) * 1j] if update: self.transfer_function.data = (data * 255).astype("u1") elif self.render_method == "slice": imgui.text("Set slicing parameters:") _, self.slice_position = imgui.input_float3( "Position", *self.slice_position ) changed = changed or _ _ = add_popup_help(imgui, "The position of a point on the slicing plane.") changed = changed or _ _, self.slice_normal = imgui.input_float3("Normal", *self.slice_normal) changed = changed or _ _ = add_popup_help(imgui, "The normal vector of the slicing plane.") changed = changed or _ return changed
@traitlets.default("transfer_function") def _default_transfer_function(self): tf = TransferFunctionTexture(data=np.ones((256, 1, 4), dtype="u1") * 255) return tf
[docs] def draw(self, scene, program): each = self.data.vertex_array.each GL.glEnable(GL.GL_CULL_FACE) GL.glCullFace(GL.GL_BACK) with self.transfer_function.bind(target=2): for tex_ind, tex, bitmap_tex in self.data.viewpoint_iter(scene.camera): with tex.bind(target=0): with bitmap_tex.bind(target=1): GL.glDrawArrays(GL.GL_POINTS, tex_ind * each, each)
def _set_uniforms(self, scene, shader_program): shader_program._set_uniform("box_width", self.box_width) shader_program._set_uniform("sample_factor", self.sample_factor) shader_program._set_uniform("ds_tex", np.array([0, 0, 0, 0, 0, 0])) shader_program._set_uniform("bitmap_tex", 1) shader_program._set_uniform("tf_tex", 2) shader_program._set_uniform("tf_min", self.tf_min) shader_program._set_uniform("tf_max", self.tf_max) shader_program._set_uniform("tf_log", float(self.tf_log)) shader_program._set_uniform("slice_normal", np.array(self.slice_normal)) shader_program._set_uniform("slice_position", np.array(self.slice_position))