Skip to content

Commit

Permalink
VOXEDIT: prepare more render functions to accept the model matrix
Browse files Browse the repository at this point in the history
... to implement #476

cursor, selections, reference position, brush volumes, grid and a few other locations are implemented
  • Loading branch information
mgerhardy committed Jan 29, 2025
1 parent 018c1ca commit 01fdd0f
Showing 11 changed files with 63 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/modules/render/GridRenderer.cpp
Original file line number Diff line number Diff line change
@@ -148,7 +148,7 @@ void GridRenderer::render(const video::Camera &camera, const math::AABB<float> &
_shapeRenderer.hide(_aabbMeshIndex, !_renderAABB);
_shapeRenderer.hide(_plane, true);
if (_renderGrid && aabb.isValid()) {
const glm::vec3 &center = aabb.getCenter();
const glm::vec3 &center = model * glm::vec4(aabb.getCenter(), 1.0f);
const glm::vec3 &halfWidth = aabb.getWidth() / 2.0f;
const math::Plane planeLeft(glm::left(), center + glm::left() * halfWidth);
const math::Plane planeRight(glm::right(), center + glm::right() * halfWidth);
3 changes: 2 additions & 1 deletion src/modules/voxelrender/SceneGraphRenderer.cpp
Original file line number Diff line number Diff line change
@@ -194,7 +194,8 @@ glm::mat4 SceneGraphRenderer::modelMatrix(const voxelrender::RenderContext &rend
const scenegraph::SceneGraph &sceneGraph = *renderContext.sceneGraph;
const voxel::Region &region = sceneGraph.resolveRegion(node);
const scenegraph::FrameTransform &transform = sceneGraph.transformForFrame(node, renderContext.frame);
model = glm::translate(transform.worldMatrix(), -(node.pivot() * glm::vec3(region.getDimensionsInVoxels())));
const glm::vec3 &scale = transform.scale();
model = glm::translate(transform.worldMatrix(), -(scale * node.pivot() * glm::vec3(region.getDimensionsInVoxels())));
}
return model;
}
3 changes: 2 additions & 1 deletion src/tools/voxedit/modules/voxedit-ui/Viewport.cpp
Original file line number Diff line number Diff line change
@@ -130,7 +130,8 @@ void Viewport::updateViewportTrace(float headerSize) {
move(pan, rotate, mouseX, mouseY);
_sceneMgr->setMousePos(_mouseX, _mouseY);
_sceneMgr->setActiveCamera(&camera());
_sceneMgr->trace(isSceneMode());
const glm::mat4 &invModel = glm::inverse(_sceneMgr->modelMatrix(_renderContext));
_sceneMgr->trace(_renderContext.isSceneMode(), false, invModel);
}

void Viewport::dragAndDrop(float headerSize) {
11 changes: 6 additions & 5 deletions src/tools/voxedit/modules/voxedit-util/SceneManager.cpp
Original file line number Diff line number Diff line change
@@ -1563,7 +1563,7 @@ void SceneManager::render(voxelrender::RenderContext &renderContext, const video
if (renderUI) {
_sceneRenderer->renderUI(renderContext, camera);
if (renderContext.isEditMode()) {
_modifierFacade.render(camera, activePalette());
_modifierFacade.render(camera, activePalette(), modelMatrix(renderContext));
}
}
renderContext.frameBuffer.unbind();
@@ -2651,15 +2651,15 @@ void SceneManager::updateDirtyRendererStates() {
}
}

bool SceneManager::trace(bool sceneMode, bool force) {
bool SceneManager::trace(bool sceneMode, bool force, const glm::mat4 &invModel) {
if (_modifierFacade.isLocked()) {
return false;
}
if (sceneMode) {
return true;
}

return mouseRayTrace(force);
return mouseRayTrace(force, invModel);
}

int SceneManager::traceScene() {
@@ -2723,7 +2723,7 @@ void SceneManager::updateCursor() {
}
}

bool SceneManager::mouseRayTrace(bool force) {
bool SceneManager::mouseRayTrace(bool force, const glm::mat4 &invModel) {
// mouse tracing is disabled - e.g. because the voxel cursor was moved by keyboard
// shortcuts. In this case the execution of the modifier would result in a
// re-execution of the trace. And that would move the voxel cursor to the mouse pos
@@ -2748,7 +2748,8 @@ bool SceneManager::mouseRayTrace(bool force) {
if (v == nullptr) {
return false;
}
const math::Ray& ray = camera->mouseRay(_mouseCursor);
math::Ray ray = camera->mouseRay(_mouseCursor);
ray.origin = glm::vec3(invModel * glm::vec4(ray.origin, 1.0f));
const float rayLength = camera->farPlane();

const glm::vec3& dirWithLength = ray.direction * rayLength;
4 changes: 2 additions & 2 deletions src/tools/voxedit/modules/voxedit-util/SceneManager.h
Original file line number Diff line number Diff line change
@@ -145,7 +145,7 @@ class SceneManager : public core::DeltaFrameSeconds {
void setReferencePosition(const glm::ivec3 &pos);
void updateDirtyRendererStates();
void zoom(video::Camera &camera, float level) const;
bool mouseRayTrace(bool force);
bool mouseRayTrace(bool force, const glm::mat4 &invModel);
void updateCursor();
int traceScene();

@@ -393,7 +393,7 @@ class SceneManager : public core::DeltaFrameSeconds {
*
* @sa resetLastTrace()
*/
bool trace(bool sceneMode, bool force = false);
bool trace(bool sceneMode, bool force = false, const glm::mat4 &invModel = glm::mat4(1.0f));
void resetLastTrace();

bool setGridResolution(int resolution);
39 changes: 22 additions & 17 deletions src/tools/voxedit/modules/voxedit-util/SceneRenderer.cpp
Original file line number Diff line number Diff line change
@@ -395,34 +395,39 @@ void SceneRenderer::renderUI(voxelrender::RenderContext &renderContext, const vi
}
// TODO: allow to render a grid in scene mode - makes shifting a lot easier
// TODO: render arrows for the distance of the region mins to the origin - to indicate a shifted region

if (isSliceModeActive()) {
// TODO: model matrix for the slice region
_shapeRenderer.render(_sliceRegionMeshIndex, camera);
}
} else if (n != nullptr) {
const voxel::Region &region = n->region();
const glm::mat4 &model = region.isValid() ? _sceneGraphRenderer.modelMatrix(renderContext, *n) : glm::mat4(1.0f);
const glm::mat4 &model = region.isValid() ? modelMatrix(renderContext, *n) : glm::mat4(1.0f);
_gridRenderer.render(camera, scenegraph::toAABB(region), model);

if (_showLockedAxis->boolVal()) {
for (int i = 0; i < lengthof(_planeMeshIndex); ++i) {
// TODO: fix z-fighting
_shapeRenderer.render(_planeMeshIndex[i], camera);
_shapeRenderer.render(_planeMeshIndex[i], camera, model);
}
}
}

if (isSliceModeActive()) {
_shapeRenderer.render(_sliceRegionMeshIndex, camera);
}
if (isSliceModeActive()) {
_shapeRenderer.render(_sliceRegionMeshIndex, camera, model);
}

const core::TimeProviderPtr &timeProvider = app::App::getInstance()->timeProvider();
const uint64_t highlightMillis = _highlightRegion.remaining(timeProvider->tickNow());
if (highlightMillis > 0) {
video::ScopedPolygonMode o(video::PolygonMode::Solid, glm::vec2(1.0f, 1.0f));
_shapeBuilder.clear();
_shapeBuilder.setColor(style::color(style::ColorHighlightArea));
_shapeBuilder.cube(_highlightRegion.value().getLowerCornerf(),
_highlightRegion.value().getUpperCornerf() + 1.0f);
_shapeRenderer.createOrUpdate(_highlightMeshIndex, _shapeBuilder);
_shapeRenderer.render(_highlightMeshIndex, camera);
video::polygonOffset(glm::vec2(0.0f));
const core::TimeProviderPtr &timeProvider = app::App::getInstance()->timeProvider();
const uint64_t highlightMillis = _highlightRegion.remaining(timeProvider->tickNow());
if (highlightMillis > 0) {
video::ScopedPolygonMode o(video::PolygonMode::Solid, glm::vec2(1.0f, 1.0f));
_shapeBuilder.clear();
_shapeBuilder.setColor(style::color(style::ColorHighlightArea));
_shapeBuilder.cube(_highlightRegion.value().getLowerCornerf(),
_highlightRegion.value().getUpperCornerf() + 1.0f);
_shapeRenderer.createOrUpdate(_highlightMeshIndex, _shapeBuilder);
_shapeRenderer.render(_highlightMeshIndex, camera, model);
video::polygonOffset(glm::vec2(0.0f));
}
}
}

Original file line number Diff line number Diff line change
@@ -30,16 +30,16 @@ class IModifierRenderer : public core::IComponent {
void shutdown() override {
}

virtual void renderBrushVolume(const video::Camera &camera) {
virtual void renderBrushVolume(const video::Camera &camera, const glm::mat4 &model) {
}
virtual void clear() {
}
virtual void updateBrushVolume(int idx, voxel::RawVolume *volume, palette::Palette *palette) {
}

virtual void render(const video::Camera &camera, const glm::mat4 &model) {
virtual void render(const video::Camera &camera, const glm::mat4 &cursor, const glm::mat4 &model) {
}
virtual void renderSelection(const video::Camera &camera) {
virtual void renderSelection(const video::Camera &camera, const glm::mat4 &model) {
}

virtual void updateReferencePosition(const glm::ivec3 &pos) {
Original file line number Diff line number Diff line change
@@ -110,11 +110,11 @@ void ModifierFacade::updateBrushVolumePreview(palette::Palette &activePalette) {
}
}

void ModifierFacade::render(const video::Camera &camera, palette::Palette &activePalette) {
void ModifierFacade::render(const video::Camera &camera, palette::Palette &activePalette, const glm::mat4 &model) {
if (_locked) {
return;
}
const glm::mat4 &translate = glm::translate(glm::vec3(_brushContext.cursorPosition));
const glm::mat4 &translate = glm::translate(model, glm::vec3(_brushContext.cursorPosition));
const glm::mat4 &scale = glm::scale(translate, glm::vec3((float)_brushContext.gridResolution));
const bool flip = voxel::isAir(_brushContext.voxelAtCursor.getMaterial());
_modifierRenderer->updateCursor(_brushContext.cursorVoxel, _brushContext.cursorFace, flip);
@@ -128,7 +128,7 @@ void ModifierFacade::render(const video::Camera &camera, palette::Palette &activ
}
}
_modifierRenderer->updateReferencePosition(referencePosition());
_modifierRenderer->render(camera, scale);
_modifierRenderer->render(camera, scale, model);

// TODO: SELECTION: remove me - let the SelectionManager render the SparseVolume
if (_brushType == BrushType::Select && brush->active()) {
@@ -142,7 +142,7 @@ void ModifierFacade::render(const video::Camera &camera, palette::Palette &activ
} else {
_modifierRenderer->updateSelectionBuffers(selectionMgr().selections());
}
_modifierRenderer->renderSelection(camera);
_modifierRenderer->renderSelection(camera, model);

if (isMode(ModifierType::ColorPicker)) {
return;
@@ -154,7 +154,7 @@ void ModifierFacade::render(const video::Camera &camera, palette::Palette &activ
brush->markClean();
}
video::polygonOffset(glm::vec3(-0.1f));
_modifierRenderer->renderBrushVolume(camera);
_modifierRenderer->renderBrushVolume(camera, model);
video::polygonOffset(glm::vec3(0.0f));
} else {
_modifierRenderer->clear();
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ class ModifierFacade : public Modifier {
ModifierFacade(SceneManager *sceneMgr, const ModifierRendererPtr &modifierRenderer);
bool init() override;
void shutdown() override;
void render(const video::Camera &camera, palette::Palette &activePalette);
void render(const video::Camera &camera, palette::Palette &activePalette, const glm::mat4 &model = glm::mat4(1.0f));
};

} // namespace voxedit
Original file line number Diff line number Diff line change
@@ -143,31 +143,37 @@ void ModifierRenderer::updateBrushVolume(int idx, voxel::RawVolume *volume, pale
}
}

void ModifierRenderer::renderBrushVolume(const video::Camera &camera) {
void ModifierRenderer::renderBrushVolume(const video::Camera &camera, const glm::mat4 &model) {
if (_volumeRendererCtx.frameBuffer.dimension() != camera.size()) {
_volumeRendererCtx.shutdown();
_volumeRendererCtx.init(camera.size());
}
_meshState->extractAllPending();
if (_meshState->volume(0) != nullptr) {
_meshState->setModelMatrix(0, model, glm::vec3(0.0f), glm::vec3(0.0f), glm::vec3(0.0f));
}
if (_meshState->volume(1) != nullptr) {
_meshState->setModelMatrix(1, model, glm::vec3(0.0f), glm::vec3(0.0f), glm::vec3(0.0f));
}
_volumeRenderer.update(_meshState);
_volumeRenderer.render(_meshState, _volumeRendererCtx, camera, false);
_volumeRenderer.render(_meshState, _volumeRendererCtx, camera, false/*, model*/);
}

void ModifierRenderer::render(const video::Camera& camera, const glm::mat4& model) {
void ModifierRenderer::render(const video::Camera& camera, const glm::mat4 &cursor, const glm::mat4& model) {
const video::ScopedState depthTest(video::State::DepthTest, false);
const video::ScopedState cullFace(video::State::CullFace, false);
_shapeRenderer.render(_voxelCursorMesh, camera, model);
_shapeRenderer.render(_mirrorMeshIndex, camera);
_shapeRenderer.render(_referencePointMesh, camera, _referencePointModelMatrix);
_shapeRenderer.render(_voxelCursorMesh, camera, cursor);
_shapeRenderer.render(_mirrorMeshIndex, camera, model);
_shapeRenderer.render(_referencePointMesh, camera, glm::translate(model, _referencePoint));
}

void ModifierRenderer::updateReferencePosition(const glm::ivec3 &pos) {
const glm::vec3 posAligned((float)pos.x + 0.5f, (float)pos.y + 0.5f, (float)pos.z + 0.5f);
_referencePointModelMatrix = glm::translate(posAligned);
_referencePoint = posAligned;
}

void ModifierRenderer::renderSelection(const video::Camera& camera) {
_shapeRenderer.render(_selectionIndex, camera);
void ModifierRenderer::renderSelection(const video::Camera& camera, const glm::mat4 &model) {
_shapeRenderer.render(_selectionIndex, camera, model);
}

void ModifierRenderer::updateMirrorPlane(math::Axis axis, const glm::ivec3& mirrorPos, const voxel::Region &region) {
Original file line number Diff line number Diff line change
@@ -22,17 +22,17 @@ class ModifierRenderer : public IModifierRenderer {
int32_t _mirrorMeshIndex = -1;
int32_t _voxelCursorMesh = -1; // TODO: remove me - should be a brush - see issue #130
int32_t _referencePointMesh = -1;
glm::mat4 _referencePointModelMatrix{1.0f};
glm::vec3 _referencePoint{0.0f};

public:
ModifierRenderer();
ModifierRenderer(const voxel::MeshStatePtr &meshState);
bool init() override;
void shutdown() override;

void render(const video::Camera &camera, const glm::mat4 &model) override;
void renderBrushVolume(const video::Camera &camera) override;
void renderSelection(const video::Camera &camera) override;
void render(const video::Camera &camera, const glm::mat4 &cursor, const glm::mat4 &model) override;
void renderBrushVolume(const video::Camera &camera, const glm::mat4 &model) override;
void renderSelection(const video::Camera &camera, const glm::mat4 &model) override;
void clear() override;
/**
* @note The given volume must still get freed by the caller - the renderer is not taking overship.

0 comments on commit 01fdd0f

Please sign in to comment.