From 77ee210685797c63d4e9a1f8f4e3c9086861066d Mon Sep 17 00:00:00 2001 From: Guillermo Ojea Quintana Date: Thu, 25 Apr 2024 14:11:10 -0300 Subject: [PATCH] Add Grid Floor for better orientation (#37) Co-authored-by: Pavel Rojtberg --- ogre_mesh_viewer.py | 78 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/ogre_mesh_viewer.py b/ogre_mesh_viewer.py index 6b16341..48d665a 100755 --- a/ogre_mesh_viewer.py +++ b/ogre_mesh_viewer.py @@ -10,7 +10,6 @@ import Ogre.RTShader as OgreRTShader import Ogre.Bites as OgreBites import Ogre.Overlay - import Ogre.ImGui as ImGui RGN_MESHVIEWER = "OgreMeshViewer" @@ -72,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): @@ -258,6 +305,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 +507,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 +527,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 +551,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 +582,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 +607,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 +648,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 +716,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 +733,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 +752,14 @@ def setup(self): light.setSpecularColour(Ogre.ColourValue.White) camnode.attachObject(light) + self.grid_floor = GridFloor(diam, scn_mgr.getRootSceneNode()) + 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)