1
$\begingroup$

As Grease Pencil has no canvas flipping function, I'd like to write a script to invert the 3D view on its X axis.

It's possible to do this on a camera object by negating its local X scale, but no such option exists for the 3D view; I believe its matrix must be modified mathematically, which I'm not sure how to do.

I've been testing everything in the console. To find the view matrix, I start by grabbing the first 'VIEW_3D' area in the interface:

for area in bpy.context.window.screen.areas:
    if ( area.type == 'VIEW_3D' ):
        v3d = area;

Then, I can print its 3d view matrix with the following line:

v3d.spaces.active.region_3d.view_matrix

I can rotate the view by passing a quaternion to v3d.spaces.active.region_3d.view_rotation, or translate it by changing the components of v3d.spaces.active.region_3d.view_matrix.translation.

view_matrix does have a Scale() function, but I don't know how it works and can't find any examples.

So, is there a way to flip the 3D view on its X axis in Blender Python?

Additional context: I don't know if mirroring the view will affect the modals for rotations and translations, which is another potential problem.

Also, my previous attempt at canvas rotation/mirroring involved rotating the active camera rather than the view. This works (when I'm looking through the camera), but modifies the camera's transform and adds the operation to the Undo stack, meaning that hitting Ctrl+Z reverses the canvas manipulation; extremely cumbersome when sketching roughs in Grease Pencil and regularly undoing stroke operations.

$\endgroup$
2
  • $\begingroup$ I'm also interested to know a solution for the view matrix. As for the camera, if you change the camera's transforms directly without using existing operators, or if you make an operator without registering it for undo, it shouldn't have the issue you mention AFAIK. $\endgroup$
    – Lauloque
    Commented Sep 4 at 20:15
  • $\begingroup$ I don't believe that's the case; my code directly multiplies the camera's scale.x value by -1. And in the original code, before I added the {'REGISTER', 'UNDO'} line, the camera manipulation was joined with either the previous or following operation (I forget which). Probably a bug. $\endgroup$
    – Latin1
    Commented Sep 4 at 21:26

1 Answer 1

1
$\begingroup$

If it were to work, it would work as follows:

import bpy
import mathutils

for area in bpy.context.screen.areas:
    if ( area.type == 'VIEW_3D' ):
        v3d = area;

m_sca = mathutils.Matrix.LocRotScale(None, None, (1.0, -1.0, 1.0))
v3d.spaces.active.region_3d.view_matrix = m_sca @ v3d.spaces.active.region_3d.view_matrix

But this switches view from back to front, not exactly that you want. This is because Blender recalculates matrix after you make changes

Strangely, negating m_sca's X value flipped the view vertically; I had to change the Y value instead.

You are right. I'm not sure why

Does the view matrix not use local coordinates?

View matrix is not the global or local, it is a projection matrix. It is used to convert world space coordinates to the camera screen.

$\endgroup$
2
  • $\begingroup$ You're right that the behaviour isn't entirely what I'm looking for, but it does the job when the view is aligned with one of the 3 axes. Strangely, negating m_sca's X value flipped the view vertically; I had to change the Y value instead. Does the view matrix not use local coordinates? (Also, I omitted the "camera" line since the object wasn't used anywhere in the code block.) $\endgroup$
    – Latin1
    Commented Sep 4 at 22:28
  • $\begingroup$ Right, I guess I didn't really know if I was dealing with the camera's transform matrix or projection matrix. $\endgroup$
    – Latin1
    Commented Sep 6 at 16:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .