nortikin / sverchok

Sverchok
http://nortikin.github.io/sverchok/
GNU General Public License v3.0
2.25k stars 233 forks source link

Homography transform proposal #3518

Closed brunopostle closed 3 years ago

brunopostle commented 4 years ago

A homography transform is a plane-preserving and straight-line preserving matrix transform that produces a perspective effect. Normally this is used to generate 2D perspective views, but the 3D transform works too - the result is similar to the Blender taper transform except that it preserves straight-lines and planes, so it doesn't suck.

A normal 3D matrix transform multiplies a 4x4 matrix with a 1x4 matrix, resulting in a 1x4 matrix where the first three numbers are the new XYZ coordinates and the fourth number is discarded. For a homography transform you simply only need to divide each of the XYZ values by the normally discarded value.

I've implemented this using simple Sverchok nodes in the attached Blender file, so you can see how this works, but I don't have the python skills to implement this in Sverchok. It would be nice to have this as a toggle option somewhere in the existing matrix node collection.

homography.zip

Here is the node arrangement in the .blend file, note that the normal Blender taper transform would completely mangle this shape:

homography-001

This is the kind of thing it may be useful for, the centre model now has a perfect false perspective 'entasis' effect:

porch-001

Thanks for Sverchok! I'm enjoying using the tool.

vicdoval commented 3 years ago

I was trying to replicate your example and i found this issue: the matrix of your example looks like this: image But i cant replicate that matrix with any of the existing matrix nodes: image They all have a 0,0,0,1 in the last row so they do not produce that homography effect... Am I missing something?

brunopostle commented 3 years ago

The standard rotation, translation, scaling, and shear transforms all have [0,0,0,1] in the bottom row, but the homography transform uses this row. I don't have any rules for these numbers, [0,0,0.5,0] results in a vertical taper, so I use that.

The existing Sverchok 'matrix apply' node takes a 4x4 matrix and a 3x1 matrix (a 3D vector) as input, and outputs a 3x1 matrix (a 3D vector) - this shouldn't work. What happens 'under the hood' is that the 3x1 matrix is converted to a 4x1 matrix (by adding 1 to the bottom row), this is multiplied by the 4x4 matrix with a 4x1 result, Sverchock then discards the bottom row and outputs a 3x1 vector.

For the Homography transform, instead of discarding the number in the bottom row of the output, it is used to divide each of the other three values.

I hope that makes sense, I'm not a mathematician, so I can't explain why this is like this. Usually this method is used to create 2D perspective drawings from 3D models, but the 3D output works fine too.

vicdoval commented 3 years ago

It is indeed an interesting algorithm... image This is the SNL script that does the work

"""
in   verts  v          .=[]   n=0
in   x_tapper  s       .=0.0  n=1
in   y_tapper  s       .=0.0  n=1
in   z_tapper  s       .=0.0  n=1
in   scale_tapper  s   .=1.0  n=1
out  overts   v
"""

from mathutils import Matrix
from sverchok.data_structure import (
                            zip_long_repeat as zlp, 
                            ensure_nesting_level as enl)
import numpy as np

if verts:
    overts = []

    for vs, xt, yt, zt, st in zlp(verts, 
                                enl(x_tapper,1), 
                                enl(y_tapper,1), 
                                enl(z_tapper,1), 
                                enl(scale_tapper,1)):
        mat=np.array(Matrix())
        mat[3, 0] = xt
        mat[3, 1] = yt
        mat[3, 2] = zt
        mat[3, 3] = st

        np_verts = np.array(vs)
        np_verts_4d = np.ones((np_verts.shape[0],4))
        np_verts_4d[:, :3] = np_verts

        v_out = mat.dot(np_verts_4d.T)

        sc = v_out[3,:]
        overts.append((v_out[:3,:].T)/sc[:,np.newaxis])

i will add it to the SNL templates asap :D

vicdoval commented 3 years ago

You can already find it in the SNL templates/utils