Skip to content

Commit

Permalink
VOXEDIT: a 2d edit mode (next to edit and scene mode) (2d slice edit) #…
Browse files Browse the repository at this point in the history
…394

The editing is not yet limited to the slice
  • Loading branch information
mgerhardy committed Nov 10, 2024
1 parent c313846 commit 7718166
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 39 deletions.
1 change: 1 addition & 0 deletions src/modules/voxelrender/RawVolumeRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct RenderContext : public core::NonCopyable {
bool onlyModels = false;
// render the built-in normals
bool renderNormals = false;
voxel::Region sliceRegion = voxel::Region::InvalidRegion;

bool init(const glm::ivec2 &size);
void shutdown();
Expand Down
62 changes: 39 additions & 23 deletions src/modules/voxelrender/SceneGraphRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,6 @@ video::Camera toCamera(const glm::ivec2 &size, const scenegraph::SceneGraphNodeC
return camera;
}

static inline int getVolumeId(int nodeId) {
// TODO: using the node id here is not good as they are increasing when you modify the scene graph
return nodeId;
}

static inline int getVolumeId(const scenegraph::SceneGraphNode &node) {
return getVolumeId(node.id());
}

static inline int getNodeId(int volumeIdx) {
// TODO: using the node id here is not good as they are increasing when you modify the scene graph
return volumeIdx;
}

SceneGraphRenderer::SceneGraphRenderer() {
}

Expand All @@ -127,7 +113,12 @@ void SceneGraphRenderer::update(const voxel::MeshStatePtr &meshState) {
}

void SceneGraphRenderer::scheduleRegionExtraction(const voxel::MeshStatePtr &meshState, scenegraph::SceneGraphNode &node, const voxel::Region &region) {
_volumeRenderer.scheduleRegionExtraction(meshState, getVolumeId(node), region);
const int idx = getVolumeId(node);
if (_sliceVolume && _sliceVolume.get() == meshState->volume(idx)) {
_sliceVolumeDirty = true;
return;
}
_volumeRenderer.scheduleRegionExtraction(meshState, idx, region);
}

void SceneGraphRenderer::setAmbientColor(const glm::vec3 &color) {
Expand Down Expand Up @@ -207,10 +198,35 @@ void SceneGraphRenderer::prepare(const voxel::MeshStatePtr &meshState, const Ren
continue;
}
const voxel::RawVolume *v = meshState->volume(id);
_volumeRenderer.setVolume(meshState, id, node, true);
const voxel::Region &region = node.region();
if (v != node.volume()) {
_volumeRenderer.scheduleRegionExtraction(meshState, id, region);
const voxel::RawVolume *nodeVolume = sceneGraph.resolveVolume(node);

bool sliceView = false;
voxel::Region region;
if (node.id() == activeNodeId) {
if (renderContext.sliceRegion.isValid()) {
sliceView = true;
if (_sliceVolumeDirty || !_sliceVolume || _sliceVolume->region() != renderContext.sliceRegion) {
_sliceVolume = core::make_shared<voxel::RawVolume>(nodeVolume, renderContext.sliceRegion);
// either node or slice volume (nodes get their volume managed - and here we have a smart pointer)
(void)_volumeRenderer.setVolume(meshState, id, _sliceVolume.get(), &node.palette(), &node.normalPalette(), !_sliceVolumeDirty);
_volumeRenderer.scheduleRegionExtraction(meshState, id, _sliceVolume->region());
_sliceVolumeDirty = false;

region = _sliceVolume->region();
v = _sliceVolume.get();
}
} else {
_sliceVolume = nullptr;
_sliceVolumeDirty = false;
}
}

if (!sliceView) {
_volumeRenderer.setVolume(meshState, id, node, true);
region = node.region();
if (v != nodeVolume) {
_volumeRenderer.scheduleRegionExtraction(meshState, id, region);
}
}
if (renderContext.renderMode == RenderMode::Scene) {
const scenegraph::FrameTransform &transform = sceneGraph.transformForFrame(node, frame);
Expand Down Expand Up @@ -240,15 +256,15 @@ void SceneGraphRenderer::prepare(const voxel::MeshStatePtr &meshState, const Ren
hideNode = true;
}
} else {
hideNode = id != activeNodeId;
hideNode = node.id() != activeNodeId;
}
} else {
hideNode = !node.visible();
}
meshState->hide(id, hideNode);

if (grayInactive) {
meshState->gray(id, id != activeNodeId);
meshState->gray(id, node.id() != activeNodeId);
} else {
meshState->gray(id, false);
}
Expand Down Expand Up @@ -283,15 +299,15 @@ void SceneGraphRenderer::prepare(const voxel::MeshStatePtr &meshState, const Ren
hideNode = true;
}
} else {
hideNode = id != activeNodeId;
hideNode = node.id() != activeNodeId;
}
} else {
hideNode = !node.visible();
}
meshState->hide(id, hideNode);

if (grayInactive) {
meshState->gray(id, id != activeNodeId);
meshState->gray(id, node.id() != activeNodeId);
} else {
meshState->gray(id, false);
}
Expand Down
19 changes: 18 additions & 1 deletion src/modules/voxelrender/SceneGraphRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

#include "RawVolumeRenderer.h"
#include "app/I18N.h"
#include "core/SharedPtr.h"
#include "core/collection/DynamicArray.h"
#include "render/CameraFrustum.h"
#include "scenegraph/SceneGraphNode.h"
#include "video/Camera.h"
#include "voxel/RawVolume.h"

/**
* Basic voxel rendering
Expand Down Expand Up @@ -41,7 +43,8 @@ class SceneGraphRenderer : public core::NonCopyable {
render::CameraFrustum _cameraRenderer;
core::DynamicArray<video::Camera> _cameras;
void prepare(const voxel::MeshStatePtr &meshState, const RenderContext &renderContext);

core::SharedPtr<voxel::RawVolume> _sliceVolume;
bool _sliceVolumeDirty = false;
public:
SceneGraphRenderer();
void construct();
Expand Down Expand Up @@ -69,6 +72,20 @@ class SceneGraphRenderer : public core::NonCopyable {
void render(const voxel::MeshStatePtr &meshState, RenderContext &renderContext, const video::Camera &camera, bool shadow = true,
bool waitPending = false);
void clear(const voxel::MeshStatePtr &meshState);

static inline int getVolumeId(int nodeId) {
// TODO: using the node id here is not good as they are increasing when you modify the scene graph
return nodeId;
}

static inline int getVolumeId(const scenegraph::SceneGraphNode &node) {
return getVolumeId(node.id());
}

static inline int getNodeId(int volumeIdx) {
// TODO: using the node id here is not good as they are increasing when you modify the scene graph
return volumeIdx;
}
};

} // namespace voxelrender
47 changes: 46 additions & 1 deletion src/tools/voxedit/modules/voxedit-ui/Viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Viewport.h"
#include "Gizmo.h"
#include "DragAndDropPayload.h"
#include "imgui.h"
#include "scenegraph/SceneGraphAnimation.h"
#include "scenegraph/SceneGraphKeyFrame.h"
#include "ui/IconsLucide.h"
Expand Down Expand Up @@ -229,14 +230,57 @@ void Viewport::renderCursor() {
renderCursorDetails();
}

bool Viewport::renderSlicer(const glm::ivec2 &contentSize) {
auto &sceneGraph = _sceneMgr->sceneGraph();
const int activeNode = sceneGraph.activeNode();
bool changed = false;
if (const scenegraph::SceneGraphNode *node = _sceneMgr->sceneGraphModelNode(activeNode)) {
glm::ivec3 mins = _renderContext.sliceRegion.getLowerCorner();
const voxel::Region &nodeRegion = sceneGraph.resolveRegion(*node);
bool sliceActive = _renderContext.sliceRegion.isValid();
if (ImGui::Checkbox("##sliceactive", &sliceActive)) {
if (!sliceActive) {
_renderContext.sliceRegion = voxel::Region::InvalidRegion;
} else {
glm::ivec3 nodeMaxs = nodeRegion.getUpperCorner();
glm::ivec3 nodeMins = nodeRegion.getLowerCorner();
nodeMaxs.y = nodeMaxs.y;
_renderContext.sliceRegion.setLowerCorner(nodeMins);
_renderContext.sliceRegion.setUpperCorner(nodeMaxs);
}
changed = true;
}
if (ImGui::IsItemHovered()) {
_viewportUIElementHovered = true;
}
if (sliceActive && ImGui::VSliderInt("##slicepos", {ImGui::Size(3.0f), (float)contentSize.y}, &mins.y,
nodeRegion.getLowerY(), nodeRegion.getUpperY())) {
glm::ivec3 nodeMaxs = nodeRegion.getUpperCorner();
glm::ivec3 nodeMins = nodeRegion.getLowerCorner();
nodeMaxs.y = mins.y;
nodeMins.y = mins.y;
_renderContext.sliceRegion.setLowerCorner(nodeMins);
_renderContext.sliceRegion.setUpperCorner(nodeMaxs);
changed = true;
}
if (ImGui::IsItemHovered()) {
_viewportUIElementHovered = true;
}
}
return changed;
}

void Viewport::renderViewport() {
core_trace_scoped(Viewport);
glm::ivec2 contentSize = ImGui::GetContentRegionAvail();
const float headerSize = ImGui::GetCursorPosY();
ImVec2 cursorPos = ImGui::GetCursorPos();
const float headerSize = cursorPos.y;
if (setupFrameBuffer(contentSize)) {
_camera.update(_app->deltaFrameSeconds());

renderToFrameBuffer();
renderSlicer(contentSize);
ImGui::SetCursorPos(cursorPos);
renderViewportImage(contentSize);
const bool modifiedRegion = renderGizmo(camera(), headerSize, contentSize);

Expand Down Expand Up @@ -452,6 +496,7 @@ void Viewport::update(command::CommandExecutionListener *listener) {
core_trace_scoped(ViewportPanel);
_camera.setFarPlane(_viewDistance->floatVal());

_viewportUIElementHovered = false;
_hovered = false;
_visible = false;
_cameraManipulated = false;
Expand Down
4 changes: 3 additions & 1 deletion src/tools/voxedit/modules/voxedit-ui/Viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Viewport : public ui::Panel {
bool _hovered = false;
// is this viewport instance visible at all?
bool _visible = false;
bool _viewportUIElementHovered = false;
/**
* while we are still modifying the transform or shifting the volume we don't want to
* flood the memento states - thus we lock the memento handler and track this here.
Expand Down Expand Up @@ -132,6 +133,7 @@ class Viewport : public ui::Panel {
void dragAndDrop(float headerSize);
void renderCursor();
void renderCursorDetails() const;
bool renderSlicer(const glm::ivec2 &contentSize);
void renderViewport();
void toggleVideoRecording();
void menuBarPolygonModeOptions();
Expand Down Expand Up @@ -189,7 +191,7 @@ inline int Viewport::id() const {
}

inline bool Viewport::isHovered() const {
return _hovered && !_cameraManipulated;
return _hovered && !_cameraManipulated && !_viewportUIElementHovered;
}

inline bool Viewport::isVisible() const {
Expand Down
5 changes: 5 additions & 0 deletions src/tools/voxedit/modules/voxedit-util/ISceneRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "core/IComponent.h"
#include "math/Axis.h"
#include "scenegraph/SceneGraphNode.h"
#include "voxel/RawVolume.h"
#include "voxel/Region.h"
#include "voxelrender/RawVolumeRenderer.h"

Expand Down Expand Up @@ -44,6 +46,9 @@ class ISceneRenderer : public core::IComponent {
}
virtual void renderScene(voxelrender::RenderContext &renderContext, const video::Camera &camera) {
}
virtual const voxel::RawVolume *volumeForNode(const scenegraph::SceneGraphNode &node) {
return node.volume();
}
};

using SceneRendererPtr = core::SharedPtr<ISceneRenderer>;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/voxedit/modules/voxedit-util/SceneManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2793,7 +2793,7 @@ bool SceneManager::mouseRayTrace(bool force) {
if (node == nullptr) {
return false;
}
const voxel::RawVolume* v = node->volume();
const voxel::RawVolume* v = _sceneRenderer->volumeForNode(*node);
if (v == nullptr) {
return false;
}
Expand Down
33 changes: 22 additions & 11 deletions src/tools/voxedit/modules/voxedit-util/SceneRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
#include "voxedit-util/AxisUtil.h"
#include "voxedit-util/Config.h"
#include "voxel/RawVolume.h"
#include "voxelrender/RawVolumeRenderer.h"
#include "voxelrender/SceneGraphRenderer.h"

namespace voxedit {

SceneRenderer::SceneRenderer() : _meshState(core::make_shared<voxel::MeshState>()) {
}

void SceneRenderer::construct() {
_volumeRenderer.construct();
_sceneGraphRenderer.construct();
_meshState->construct();
}

Expand All @@ -41,7 +43,7 @@ bool SceneRenderer::init() {
Log::error("Failed to initialize the mesh state");
return false;
}
if (!_volumeRenderer.init(_meshState->hasNormals())) {
if (!_sceneGraphRenderer.init(_meshState->hasNormals())) {
Log::error("Failed to initialize the volume renderer");
return false;
}
Expand All @@ -61,11 +63,11 @@ bool SceneRenderer::init() {
}

void SceneRenderer::clear() {
_volumeRenderer.clear(_meshState);
_sceneGraphRenderer.clear(_meshState);
}

void SceneRenderer::shutdown() {
_volumeRenderer.shutdown();
_sceneGraphRenderer.shutdown();
// don't free the volumes here, they belong to the scene graph
(void)_meshState->shutdown();

Expand Down Expand Up @@ -128,7 +130,7 @@ bool SceneRenderer::extractVolume(const scenegraph::SceneGraph &sceneGraph) {
for (size_t i = 0; i < n; ++i) {
const voxel::Region &region = _extractRegions[i].region;
if (scenegraph::SceneGraphNode *node = sceneGraphModelNode(sceneGraph, _extractRegions[i].nodeId)) {
_volumeRenderer.scheduleRegionExtraction(_meshState, *node, region);
_sceneGraphRenderer.scheduleRegionExtraction(_meshState, *node, region);
Log::debug("Extract node %i", _extractRegions[i].nodeId);
voxel::logRegion("Extraction", region);
}
Expand Down Expand Up @@ -272,12 +274,21 @@ void SceneRenderer::updateBoneMesh(bool sceneMode, const scenegraph::SceneGraph
_shapeRenderer.createOrUpdate(_boneMeshIndex, _shapeBuilder);
}

const voxel::RawVolume *SceneRenderer::volumeForNode(const scenegraph::SceneGraphNode &node) {
int idx = voxelrender::SceneGraphRenderer::getVolumeId(node);
const voxel::RawVolume *v = _meshState->volume(idx);
if (v == nullptr) {
v = node.volume();
}
return v;
}

bool SceneRenderer::isVisible(int nodeId, bool hideEmpty) const {
return _volumeRenderer.isVisible(_meshState, nodeId, hideEmpty);
return _sceneGraphRenderer.isVisible(_meshState, nodeId, hideEmpty);
}

void SceneRenderer::removeNode(int nodeId) {
_volumeRenderer.nodeRemove(_meshState, nodeId);
_sceneGraphRenderer.nodeRemove(_meshState, nodeId);
}

void SceneRenderer::update() {
Expand All @@ -287,10 +298,10 @@ void SceneRenderer::update() {
_gridRenderer.setColor(style::color(style::ColorGridBorder));
glm::vec3 val;
_ambientColor->vec3Val(&val[0]);
_volumeRenderer.setAmbientColor(val);
_sceneGraphRenderer.setAmbientColor(val);
_diffuseColor->vec3Val(&val[0]);
_volumeRenderer.setDiffuseColor(val);
_volumeRenderer.update(_meshState);
_sceneGraphRenderer.setDiffuseColor(val);
_sceneGraphRenderer.update(_meshState);
}

void SceneRenderer::renderScene(voxelrender::RenderContext &renderContext, const video::Camera &camera) {
Expand All @@ -306,7 +317,7 @@ void SceneRenderer::renderScene(voxelrender::RenderContext &renderContext, const
video::ScopedState depthTest(video::State::DepthTest, true);
updateAABBMesh(renderContext.renderMode == voxelrender::RenderMode::Scene, *renderContext.sceneGraph, renderContext.frame);
updateBoneMesh(renderContext.renderMode == voxelrender::RenderMode::Scene, *renderContext.sceneGraph, renderContext.frame);
_volumeRenderer.render(_meshState, renderContext, camera, _renderShadow->boolVal(), false);
_sceneGraphRenderer.render(_meshState, renderContext, camera, _renderShadow->boolVal(), false);
extractVolume(*renderContext.sceneGraph);
}

Expand Down
Loading

0 comments on commit 7718166

Please sign in to comment.