From 5f0a852093fb4480337501ccb563be3c9fb9caba Mon Sep 17 00:00:00 2001 From: sercero Date: Sat, 20 Apr 2024 19:15:16 -0300 Subject: [PATCH 1/3] Add Grid Floor for better orientation --- ogre_grid.py | 114 ++++++++++++++++++++++++++++++++++++++++++++ ogre_mesh_viewer.py | 33 +++++++++++-- 2 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 ogre_grid.py diff --git a/ogre_grid.py b/ogre_grid.py new file mode 100644 index 0000000..fe7760c --- /dev/null +++ b/ogre_grid.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +import Ogre +import math + +GRID_MATERIAL = "MeshViewer/VertexColour" + +class GridFloor: + def __init__(self, scene, resource_group): + self.scn_mgr = scene + self.resource_group = resource_group + self.plane_names = ["YZPlane", "XZPlane", "XYPlane"] + self.normals = [ + (1, 0, 0), # YZPlane normal + (0, 1, 0), # XZPlane normal + (0, 0, 1) # XYPlane normal + ] + self.axis_colors = [ + Ogre.ColourValue(1, 0, 0, 1), + Ogre.ColourValue(0, 1, 0, 1), + Ogre.ColourValue(0, 0, 1, 1) + ] + + def nearest_power_of_two(self, n): + if n < 1: + return 1 + + # Calculate the logarithm base 2 and find the floor and ceil + log2_n = math.log2(n) + lower_power = 2 ** math.floor(log2_n) + higher_power = 2 ** math.ceil(log2_n) + + # Compare which power of two is closer to the original number + if abs(lower_power - n) < abs(higher_power - n): + return lower_power + else: + return higher_power + + def show_plane(self, plane): + for p in range(0, 3): + plane_name = "MeshViewer/" + self.plane_names[p] + plane_node = self.scn_mgr.getSceneNode(plane_name) + plane_node.setVisible(p == plane) + + def create_material(self): + material = Ogre.MaterialManager.getSingleton().create(GRID_MATERIAL, self.resource_group); + p = material.getTechnique(0).getPass(0); + p.setLightingEnabled(False); + p.setVertexColourTracking(Ogre.TVC_AMBIENT); + + def create_planes(self, diam): + self.create_material() + if diam < 1: + subdiv = int(self.nearest_power_of_two(1/diam)) + else: + subdiv = 1 + + for plane in range(0, 3): + plane_name = "MeshViewer/" + self.plane_names[plane] + self.create_plane(plane, int(math.ceil(diam)), subdiv) + + def create_plane(self, plane, diam, subdiv): + cl = None + axis_color = None + plane_name = "MeshViewer/" + self.plane_names[plane] + min_val = -diam + max_val = diam + + normal = self.normals[plane] + + color_X = self.axis_colors[0] + color_Y = self.axis_colors[1] + color_Z = self.axis_colors[2] + + if plane == 0: + axis_color = [color_Y, color_Z] + elif plane == 1: + axis_color = [color_X, color_Z] + elif plane == 2: + axis_color = [color_Y, color_X] + + c1 = 0.2 + c2 = 0.4 + grid_color = Ogre.ColourValue(c1, c1, c1, 1) + subd_color = Ogre.ColourValue(c2, c2, c2, 1) + + # Compute the other axes based on the normal vector + axis = [ + Ogre.Vector3(normal[1], normal[2], normal[0]), + Ogre.Vector3(normal[2], normal[0], normal[1]) + ] + + o = self.scn_mgr.createManualObject(plane_name); + o.begin(GRID_MATERIAL, Ogre.RenderOperation.OT_LINE_LIST, self.resource_group) + o.setQueryFlags(0) + + for i in range(0, 2): + for j in range(min_val * subdiv, max_val * subdiv + 1): + if j == 0: + cl = axis_color[i] + elif (j * (1/subdiv)) % 1 == 0: + cl = grid_color + else: + cl = subd_color + o.position(axis[i] * min_val + axis[1 - i] * j * (1/subdiv)) + o.colour(cl) + o.position(axis[i] * max_val + axis[1 - i] * j * (1/subdiv)) + o.colour(cl) + + o.end() + + plane_node = self.scn_mgr.getRootSceneNode().createChildSceneNode(plane_name) + plane_node.attachObject(o) + plane_node.setVisible(False) diff --git a/ogre_mesh_viewer.py b/ogre_mesh_viewer.py index 6b16341..cb4fbe0 100755 --- a/ogre_mesh_viewer.py +++ b/ogre_mesh_viewer.py @@ -10,9 +10,10 @@ import Ogre.RTShader as OgreRTShader import Ogre.Bites as OgreBites import Ogre.Overlay - import Ogre.ImGui as ImGui +import ogre_grid + RGN_MESHVIEWER = "OgreMeshViewer" RGN_USERDATA = "UserData" @@ -258,6 +259,8 @@ def preRenderTargetUpdate(self, evt): ImGui.Separator() if ImGui.MenuItem("Show Axes", "A", self.app.axes_visible): self.app._toggle_axes() + if ImGui.MenuItem("Show Grid", "G", self.app.grid_visible): + self.app._toggle_grid() if ImGui.MenuItem("Show Bounding Box", "B", enode.getShowBoundingBox()): self.app._toggle_bbox() if ImGui.MenuItem("Wireframe Mode", "W", app.cam.getPolygonMode() == Ogre.PM_WIREFRAME): @@ -458,6 +461,8 @@ def __init__(self, infile, rescfg): self.fixed_yaw_axes = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] self.fixed_yaw_axis = 1 self.default_tilt = Ogre.Degree(20) + self.grid_floor = None + self.grid_visible = True self.active_controllers = {} @@ -476,6 +481,8 @@ def keyPressed(self, evt): self.gui.side_panel_visible = not self.gui.side_panel_visible elif evt.keysym.sym == ord("a"): self._toggle_axes() + elif evt.keysym.sym == ord("g"): + self._toggle_grid() elif evt.keysym.sym == ord("p"): self._save_screenshot() elif evt.keysym.sym == ord("w"): @@ -498,6 +505,7 @@ def mousePressed(self, evt): return True new_entity = hit.movable.castEntity() + if self.attach_node and new_entity and evt.button == OgreBites.BUTTON_LEFT: if self.entity is not None: self.entity.getParentSceneNode().showBoundingBox(False) @@ -528,11 +536,19 @@ def _toggle_axes(self): self.axes_visible = not self.axes_visible + def _toggle_grid(self): + self.grid_visible = not self.grid_visible + + if self.grid_visible: + self.grid_floor.show_plane(self.fixed_yaw_axis) + else: + self.grid_floor.show_plane(-1) + def _save_screenshot(self): name = os.path.splitext(self.filename)[0] outpath = os.path.join(self.filedir, f"screenshot_{name}_") - Ogre.LogManager.getSingleton().logMessage(f"Screenshot saved to folder: {self.filedir}") + Ogre.LogManager.getSingleton().logMessage(f"Screenshot saved to folder: {os.path.normpath(self.filedir)}") self.cam.getViewport().setOverlaysEnabled(False) self.getRoot().renderOneFrame() @@ -545,6 +561,8 @@ def set_orientation(self): camnode.setOrientation(Ogre.Quaternion.IDENTITY) camnode.setFixedYawAxis(self.fixed_yaw_axis != -1, self.fixed_yaw_axes[self.fixed_yaw_axis]) self.camman.setFixedYaw(self.fixed_yaw_axis != -1) + if self.grid_visible: + self.grid_floor.show_plane(self.fixed_yaw_axis) if self.fixed_yaw_axis == 0: self.camman.setYawPitchDist(0, 0, diam) @@ -584,7 +602,7 @@ def locateResources(self): # add fonts to default resource group rgm.addResourceLocation(os.path.dirname(__file__) + "/fonts", "FileSystem", RGN_MESHVIEWER) - + def loadResources(self): rgm = Ogre.ResourceGroupManager.getSingleton() rgm.initialiseResourceGroup(Ogre.RGN_INTERNAL) @@ -652,6 +670,8 @@ def setup(self): self.getRoot().renderOneFrame() self.getRoot().renderOneFrame() + Ogre.LogManager.getSingleton().logMessage(f"Opening file: {os.path.normpath(self.infile)}") + if self.filename.lower().endswith(".scene"): self.attach_node = scn_mgr.getRootSceneNode().createChildSceneNode() self.attach_node.loadChildren(self.filename) @@ -667,6 +687,7 @@ def setup(self): diam = c.getDerivedPosition().length() break else: + self.attach_node = None self.entity = scn_mgr.createEntity(self.filename) scn_mgr.getRootSceneNode().createChildSceneNode().attachObject(self.entity) diam = self.entity.getBoundingBox().getSize().length() @@ -685,9 +706,15 @@ def setup(self): light.setSpecularColour(Ogre.ColourValue.White) camnode.attachObject(light) + self.grid_floor = ogre_grid.GridFloor(scn_mgr, RGN_MESHVIEWER) + self.grid_floor.create_planes(diam) + if self.grid_visible: + self.grid_floor.show_plane(self.fixed_yaw_axis) + self.camman = OgreBites.CameraMan(camnode) self.camman.setStyle(OgreBites.CS_ORBIT) self.camman.setYawPitchDist(0, self.default_tilt, diam) + self.set_orientation() self.input_dispatcher = OgreBites.InputListenerChain([self.getImGuiInputListener(), self.camman, self]) self.addInputListener(self.input_dispatcher) From bf81f4e14efb0a9e0df532d76bcc9d0eeaf25e4e Mon Sep 17 00:00:00 2001 From: sercero Date: Wed, 24 Apr 2024 11:08:20 -0300 Subject: [PATCH 2/3] Solve linting problems --- ogre_grid.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ogre_grid.py b/ogre_grid.py index fe7760c..1f20189 100644 --- a/ogre_grid.py +++ b/ogre_grid.py @@ -43,10 +43,10 @@ def show_plane(self, plane): plane_node.setVisible(p == plane) def create_material(self): - material = Ogre.MaterialManager.getSingleton().create(GRID_MATERIAL, self.resource_group); - p = material.getTechnique(0).getPass(0); - p.setLightingEnabled(False); - p.setVertexColourTracking(Ogre.TVC_AMBIENT); + material = Ogre.MaterialManager.getSingleton().create(GRID_MATERIAL, self.resource_group) + p = material.getTechnique(0).getPass(0) + p.setLightingEnabled(False) + p.setVertexColourTracking(Ogre.TVC_AMBIENT) def create_planes(self, diam): self.create_material() @@ -56,7 +56,6 @@ def create_planes(self, diam): subdiv = 1 for plane in range(0, 3): - plane_name = "MeshViewer/" + self.plane_names[plane] self.create_plane(plane, int(math.ceil(diam)), subdiv) def create_plane(self, plane, diam, subdiv): @@ -90,7 +89,7 @@ def create_plane(self, plane, diam, subdiv): Ogre.Vector3(normal[2], normal[0], normal[1]) ] - o = self.scn_mgr.createManualObject(plane_name); + o = self.scn_mgr.createManualObject(plane_name) o.begin(GRID_MATERIAL, Ogre.RenderOperation.OT_LINE_LIST, self.resource_group) o.setQueryFlags(0) From a18e569fb73240bc222733078f525aebd9b45867 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 25 Apr 2024 19:08:12 +0200 Subject: [PATCH 3/3] simplify GridFloor --- ogre_grid.py | 113 -------------------------------------------- ogre_mesh_viewer.py | 53 +++++++++++++++++++-- 2 files changed, 49 insertions(+), 117 deletions(-) delete mode 100644 ogre_grid.py diff --git a/ogre_grid.py b/ogre_grid.py deleted file mode 100644 index 1f20189..0000000 --- a/ogre_grid.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python - -import Ogre -import math - -GRID_MATERIAL = "MeshViewer/VertexColour" - -class GridFloor: - def __init__(self, scene, resource_group): - self.scn_mgr = scene - self.resource_group = resource_group - self.plane_names = ["YZPlane", "XZPlane", "XYPlane"] - self.normals = [ - (1, 0, 0), # YZPlane normal - (0, 1, 0), # XZPlane normal - (0, 0, 1) # XYPlane normal - ] - self.axis_colors = [ - Ogre.ColourValue(1, 0, 0, 1), - Ogre.ColourValue(0, 1, 0, 1), - Ogre.ColourValue(0, 0, 1, 1) - ] - - def nearest_power_of_two(self, n): - if n < 1: - return 1 - - # Calculate the logarithm base 2 and find the floor and ceil - log2_n = math.log2(n) - lower_power = 2 ** math.floor(log2_n) - higher_power = 2 ** math.ceil(log2_n) - - # Compare which power of two is closer to the original number - if abs(lower_power - n) < abs(higher_power - n): - return lower_power - else: - return higher_power - - def show_plane(self, plane): - for p in range(0, 3): - plane_name = "MeshViewer/" + self.plane_names[p] - plane_node = self.scn_mgr.getSceneNode(plane_name) - plane_node.setVisible(p == plane) - - def create_material(self): - material = Ogre.MaterialManager.getSingleton().create(GRID_MATERIAL, self.resource_group) - p = material.getTechnique(0).getPass(0) - p.setLightingEnabled(False) - p.setVertexColourTracking(Ogre.TVC_AMBIENT) - - def create_planes(self, diam): - self.create_material() - if diam < 1: - subdiv = int(self.nearest_power_of_two(1/diam)) - else: - subdiv = 1 - - for plane in range(0, 3): - self.create_plane(plane, int(math.ceil(diam)), subdiv) - - def create_plane(self, plane, diam, subdiv): - cl = None - axis_color = None - plane_name = "MeshViewer/" + self.plane_names[plane] - min_val = -diam - max_val = diam - - normal = self.normals[plane] - - color_X = self.axis_colors[0] - color_Y = self.axis_colors[1] - color_Z = self.axis_colors[2] - - if plane == 0: - axis_color = [color_Y, color_Z] - elif plane == 1: - axis_color = [color_X, color_Z] - elif plane == 2: - axis_color = [color_Y, color_X] - - c1 = 0.2 - c2 = 0.4 - grid_color = Ogre.ColourValue(c1, c1, c1, 1) - subd_color = Ogre.ColourValue(c2, c2, c2, 1) - - # Compute the other axes based on the normal vector - axis = [ - Ogre.Vector3(normal[1], normal[2], normal[0]), - Ogre.Vector3(normal[2], normal[0], normal[1]) - ] - - o = self.scn_mgr.createManualObject(plane_name) - o.begin(GRID_MATERIAL, Ogre.RenderOperation.OT_LINE_LIST, self.resource_group) - o.setQueryFlags(0) - - for i in range(0, 2): - for j in range(min_val * subdiv, max_val * subdiv + 1): - if j == 0: - cl = axis_color[i] - elif (j * (1/subdiv)) % 1 == 0: - cl = grid_color - else: - cl = subd_color - o.position(axis[i] * min_val + axis[1 - i] * j * (1/subdiv)) - o.colour(cl) - o.position(axis[i] * max_val + axis[1 - i] * j * (1/subdiv)) - o.colour(cl) - - o.end() - - plane_node = self.scn_mgr.getRootSceneNode().createChildSceneNode(plane_name) - plane_node.attachObject(o) - plane_node.setVisible(False) diff --git a/ogre_mesh_viewer.py b/ogre_mesh_viewer.py index cb4fbe0..48d665a 100755 --- a/ogre_mesh_viewer.py +++ b/ogre_mesh_viewer.py @@ -12,8 +12,6 @@ import Ogre.Overlay import Ogre.ImGui as ImGui -import ogre_grid - RGN_MESHVIEWER = "OgreMeshViewer" RGN_USERDATA = "UserData" @@ -73,6 +71,54 @@ def askopenfilename(initialdir=None): ("Common mesh files", "*.obj *.fbx *.ply *.gltf *.glb ")]) return infile +class GridFloor: + def __init__(self, scale, parent_node): + self.material = Ogre.MaterialManager.getSingleton().create("VertexColour", RGN_MESHVIEWER) + p = self.material.getTechnique(0).getPass(0) + p.setLightingEnabled(False) + p.setVertexColourTracking(Ogre.TVC_AMBIENT) + + self.plane_node = parent_node.createChildSceneNode() + self.plane_node.setScale(scale, scale, scale) + + self.planes = [self._create_plane(i) for i in range(3)] + + def show_plane(self, plane): + for i, grid in enumerate(self.planes): + grid.setVisible(i == plane) + + def _create_plane(self, plane): + normal = [0, 0, 0] + normal[plane] = 1 + + axis_color = [[0, 0, 0], [0, 0, 0]] + axis_color[0][(plane + 2) % 3] = 1 + axis_color[1][(plane + 1) % 3] = 1 + + grid_color = (0.2, 0.2, 0.2) + + # Compute the other axes based on the normal vector + axis = [Ogre.Vector3(normal[1], normal[2], normal[0]), + Ogre.Vector3(normal[2], normal[0], normal[1])] + + o = self.plane_node.getCreator().createManualObject(f"MeshViewer/plane{plane}") + o.begin(self.material, Ogre.RenderOperation.OT_LINE_LIST) + o.setQueryFlags(0) + o.setVisible(False) + + for i in range(2): + for j in range(-5, 6): + cl = axis_color[i] if j == 0 else grid_color + o.position(-axis[i] + axis[1 - i] * j/5) + o.colour(cl) + o.position(axis[i] + axis[1 - i] * j/5) + o.colour(cl) + + o.end() + + self.plane_node.attachObject(o) + return o + class MaterialCreator(Ogre.MeshSerializerListener): def __init__(self): @@ -706,8 +752,7 @@ def setup(self): light.setSpecularColour(Ogre.ColourValue.White) camnode.attachObject(light) - self.grid_floor = ogre_grid.GridFloor(scn_mgr, RGN_MESHVIEWER) - self.grid_floor.create_planes(diam) + self.grid_floor = GridFloor(diam, scn_mgr.getRootSceneNode()) if self.grid_visible: self.grid_floor.show_plane(self.fixed_yaw_axis)