Thoughts on non-standard viewport transformation

Hi,

I was inquired about how to implement a scaled viewport drawing option. There are different ways of acchieving this.

I decided to share the anwer here so that it can benefit more people. But also as a way to illustrate how to tackle such a problem.

Tools/Workflow

  1. Lattice

  2. Work in a collection, and instance that collection as a separate object: scale the instanced collection

  3. Geometry Nodes: add to an object that you want to see scaled.

The Geometry Nodes solution has the advantage that it works even in Edit Mode, with the On Cage option.

Python

You can render the viewport from the point of view of a camera, and overlay it in the viewport.

The API documentation has an example that does precisely this. Just change the scale it draws back.

You can have a viewport dedicated to draw this, while another one dedicated to the interaction itself.

C++ coding

You can either approach this as a engine level setting (for the Workbench Engine), or a per-object Viewport Display option.

The nice thing about the engine option, is that it would be global and easily setup. The downside is that you won’t (easily anyways) manage to get the gizmos, mouse selection and other UI elements to play nice with it.

Blender does have a separation between what the render engine handles, and what the interaction layer does. So you would need to make sure the render engines is changing the view transform of the render buffer (and the depth and selection buffer). And make sure the interaction layer is NOT distorted, while is made aware of the new transforms.

Not rocket science, but probably not a walk in the park either. But if done well it could be acceptable as Blender contribution. This topics comes around any time we talk about supporting fisheye lens, fulldomes, panoramas on the viewport.

You can also make a custom render engine (using a hydra delegate even), that just ignores the fact that the interaction/clicking don’t match what you see on the viewport. Not a good experience, but technically is what Blender does with Cycles when you use Panorama/Fisheye lens. (and what EEVEE plans to do once it supports those options too).

3 Likes

Not sure what exactly you’re trying to achieve. Would be good to have some examples and not just possible solutions.

As for the custom render engine you don’t need that, a lot of flexibility will come with Cycles OSL Camera - Feedback At least for Cycles. A lot of flexibility tho :slight_smile:

After having some concrete examples we should be able to find a solution that works for all engines though. Hopefully.

4 Likes

One massive (at least in our particular niche) use case is to squeeze viewport in different orientations with overlays - ideally to be able to work in this mode to finetune mesh curvature for automotive car design development.

example
You have side of a car and its curves are quite long. Its difficult to judge quality of the curves visually on monitor, so one would

  1. use diagnostic tools (I made some with curvature graph wink wink)
  2. squeeze the viewport in direction of the curve to better visually see vertex relationships and fine tune in

I use linking to parent empty and scaling the empty in some direction, while rotating the child body. GN trick Dalai mentions sounds good as well.
However this takes too much clicks, so addon would be useful, or core feature - ideally viewport-base to have best context.

This is being used extremely frequently while modelling in that industry standard software.
Personally I’d love this and it would transform my daily work, as well as many other’s.
I dont want to post here direct example from other commercial software, its not allowed here?
Anyways I can and would love to provide solid feedback, if this is where it should go!

2 Likes

Hi …
I have tried the python gpu library approach and it works … by scaling the projection matrix in 00 and 11 elements its possible to get a non uniform scaled views in Horizontal and Vertical directions …
The scaled view is drawn as a texture overlayed on 3d view port.
If we scale this texture to fill the entire viewport, then the problem is now the object is not editable … as now we cannot select individual vertices when there is a overlay texture on top …
Is there any workaround for this … so that we can allow inputs to be passed to the mesh below the overlay texture ?

Hi Dalai,
Thank you for posting your thoughts here. I was trying Geometry nodes solution for non-standard viewport transformation, on changing scale it works in object mode but when we try to do it in edit mode it does not work as expected with vertices. On changing scale, it scales the object targeted axis, but vertices remain on the same position.

You got to check that triangle icon in the modifier.
However I was thinking more something like this. Challenge is to get viewport coordinates into the GN modifier, in this case I used a Camera as reference, or somehow feed it into GN modifier with Python API.
Disadvantage is working without perspective gets awkward in Camera (zoom).

This is close to what Id need, could be nicely automated (will try over Christmas holidays)

1 Like

Hi Dalai,

Based on your suggestion, I am able to use the GPU library of python and then create a projected texture to be overlayed on the 3d view. This projected texture uses camera projection matrix and modifies it to scale in horizontal and vertical axis to get the effect of scaled view in either axis.

You mentioned about having dedicated view for showing this projected texture different from the default 3d view (which can be used for editing)… is there a way to draw this texture in a different 3d view ? so that we can have two 3d views one showing original object and other the scaled view ?

Uv editor might require non-uniform viewport scaling as well, especially in trims workflow.

In car modeling scaling 3d objects is typically used at the moment.

For C++, this would be making the Aspect X and Y render options available for the 3D viewport. And then using it in every relevant BKE_camera_params_compute_viewplane call.

Most importantly this one:

diff --git a/source/blender/editors/space_view3d/view3d_utils.cc b/source/blender/editors/space_view3d/view3d_utils.cc
index 6de3710..9683d85 100644
--- a/source/blender/editors/space_view3d/view3d_utils.cc
+++ b/source/blender/editors/space_view3d/view3d_utils.cc
@@ -192,7 +192,7 @@ bool ED_view3d_viewplane_get(const Depsgraph *depsgraph,

   BKE_camera_params_init(&params);
   BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
-  BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
+  BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 2.0f);

   if (r_viewplane) {
     *r_viewplane = params.viewplane;
1 Like