Skip to content

Instantly share code, notes, and snippets.

@nkint
Created November 19, 2019 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nkint/7a80d89e8d5e9b2b1d992f1971738cf6 to your computer and use it in GitHub Desktop.
Save nkint/7a80d89e8d5e9b2b1d992f1971738cf6 to your computer and use it in GitHub Desktop.
numpy - vec3 transformation mat4
import numpy as np
def cube_geometry(x, y, z):
xSize = x / 2
ySize = y / 2
zSize = z / 2
positions = np.array([
[-xSize, ySize, zSize], [xSize, ySize, zSize],
[-xSize, -ySize, zSize], [xSize, -ySize, zSize],
[xSize, ySize, -zSize], [-xSize, ySize, -zSize],
[xSize, -ySize, -zSize], [-xSize, -ySize, -zSize],
[-xSize, ySize, -zSize], [-xSize, ySize, zSize],
[-xSize, -ySize, -zSize], [-xSize, -ySize, zSize],
[xSize, ySize, zSize], [xSize, ySize, -zSize],
[xSize, -ySize, zSize], [xSize, -ySize, -zSize],
[-xSize, ySize, -zSize], [xSize, ySize, -zSize],
[-xSize, ySize, zSize], [xSize, ySize, zSize],
[-xSize, -ySize, zSize], [xSize, -ySize, zSize],
[-xSize, -ySize, -zSize], [xSize, -ySize, -zSize]
])
normals = np.array([
[0, 0, 1], [0, 0, 1],
[0, 0, 1], [0, 0, 1],
[0, 0, -1], [0, 0, -1],
[0, 0, -1], [0, 0, -1],
[-1, 0, 0], [-1, 0, 0],
[-1, 0, 0], [-1, 0, 0],
[1, 0, 0], [1, 0, 0],
[1, 0, 0], [1, 0, 0],
[0, 1, 0], [0, 1, 0],
[0, 1, 0], [0, 1, 0],
[0, -1, 0], [0, -1, 0],
[0, -1, 0], [0, -1, 0]
])
uvs = np.array([
[0, 1], [1, 1], [0, 0],
[1, 0], [0, 1], [1, 1],
[0, 0], [1, 0], [0, 1],
[1, 1], [0, 0], [1, 0],
[0, 1], [1, 1], [0, 0],
[1, 0], [0, 1], [1, 1],
[0, 0], [1, 0], [0, 1],
[1, 1], [0, 0], [1, 0]
])
cells = np.array([
[0, 2, 3], [0, 3, 1],
[4, 6, 7], [4, 7, 5],
[8, 10, 11], [8, 11, 9],
[12, 14, 15], [12, 15, 13],
[16, 18, 19], [16, 19, 17],
[20, 22, 23], [20, 23, 21]
])
return positions, cells, normals, uvs
def transform_vec3_mat4(a: np.ndarray, _m: np.ndarray):
"""
Transforms the vec3 with a mat4.
4th vector component is implicitly '1'
Reference:
https://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_3D_computer_graphics
http://math.hws.edu/graphicsbook/c3/transform-matrices-3d.png
Code from:
https://github.com/stackgl/gl-vec3/blob/master/transformMat4.js
:param a: (3) -- float64
3 dimensions vector
:param m: (4, 4) -- float64
Mat 4x4 representing a transformation in 3D cartesian space
:return: (3) -- float64
transfromed vec3
"""
m = _m.flatten()
x = a[0]
y = a[1]
z = a[2]
w = m[3] * x + m[7] * y + m[11] * z + m[15]
w = w or 1.0
out = np.array([
(m[0] * x + m[4] * y + m[8] * z + m[12]) / w,
(m[1] * x + m[5] * y + m[9] * z + m[13]) / w,
(m[2] * x + m[6] * y + m[10] * z + m[14]) / w
])
return out
def transform_points(array: np.ndarray, mat: np.ndarray):
return np.array([transform_vec3_mat4(point, mat) for point in array])
positions, cells, normals, uvs = cube_geometry(1, 1, 1)
vx = 0.5
vy = 0
vz = 0
translate = np.array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
vx, vy, vz, 1,
])
positionsTranslated = transform_points(positions, translate)
print(positions)
print(positionsTranslated)
"""
result:
[[-0.5 0.5 0.5]
[ 0.5 0.5 0.5]
[-0.5 -0.5 0.5]
[ 0.5 -0.5 0.5]
[ 0.5 0.5 -0.5]
[-0.5 0.5 -0.5]
[ 0.5 -0.5 -0.5]
[-0.5 -0.5 -0.5]
[-0.5 0.5 -0.5]
[-0.5 0.5 0.5]
[-0.5 -0.5 -0.5]
[-0.5 -0.5 0.5]
[ 0.5 0.5 0.5]
[ 0.5 0.5 -0.5]
[ 0.5 -0.5 0.5]
[ 0.5 -0.5 -0.5]
[-0.5 0.5 -0.5]
[ 0.5 0.5 -0.5]
[-0.5 0.5 0.5]
[ 0.5 0.5 0.5]
[-0.5 -0.5 0.5]
[ 0.5 -0.5 0.5]
[-0.5 -0.5 -0.5]
[ 0.5 -0.5 -0.5]]
[[ 0. 0.5 0.5]
[ 1. 0.5 0.5]
[ 0. -0.5 0.5]
[ 1. -0.5 0.5]
[ 1. 0.5 -0.5]
[ 0. 0.5 -0.5]
[ 1. -0.5 -0.5]
[ 0. -0.5 -0.5]
[ 0. 0.5 -0.5]
[ 0. 0.5 0.5]
[ 0. -0.5 -0.5]
[ 0. -0.5 0.5]
[ 1. 0.5 0.5]
[ 1. 0.5 -0.5]
[ 1. -0.5 0.5]
[ 1. -0.5 -0.5]
[ 0. 0.5 -0.5]
[ 1. 0.5 -0.5]
[ 0. 0.5 0.5]
[ 1. 0.5 0.5]
[ 0. -0.5 0.5]
[ 1. -0.5 0.5]
[ 0. -0.5 -0.5]
[ 1. -0.5 -0.5]]
"""
@NoFishLikeIan
Copy link

NoFishLikeIan commented Nov 20, 2019

Much faster like this. You can make it faster with Linear Algebra

import numpy as np

def translate_points(positions, translate):
    trans = translate.copy()
    pos = positions.copy()

    n, c = positions.shape
    m_1, m_2 = trans.shape

    if c != m_1:
        pos = np.hstack((positions, np.ones((n, 1))))

    if m_1 != m_2:
        raise ValueError(
            f'Translate matrix needs to be square, found {(m_1, m_2)}')

    if m_1 - 1 != c:
        raise ValueError(
            f'Check your translate and positions matrix shapes!')

    translated = pos @ translate

    return translated[:, :-1]


def make_squared(translation_array):
    """
    Takes iterable and tries to produce square matrix.
    Assumes len(translation_array) is a square.
    """

    transl = translation_array if type(
        translation_array) == np.array else np.array(translation_array)

    square = np.int(np.sqrt(len(translation_array)))

    return transl.reshape((square, square))


def make_translation_matrix(v):

    return np.array([
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [*v, 1]])


v = [0.5, 0, 0]

positions, cells, normals, uvs = cube_geometry(1, 1, 1)

translation_matrix = make_translation_matrix(v)

position_translated = translate_points(positions, translation_matrix)
print(position_translated)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment