
One of the necessary aspect within the Computer Graphics industry is maths. Building up these foundations, I believe, will benefit and make better connections and processes that can contribute to most tasks. Most of the maths are processed automatically through computational analysis and methods that are built within the software packages. Even though this is the case it is vital to understanding the mathematics behind these computational processes to manipulate and perform logical concepts that can enhance technical workflows.
Below will cover the basic concept of mathematical concepts that are commonly used within the world of computer graphics.
VECTORS


Point and vector values are represented similarly in numerical euclidean space (x, y ,z axis in 3D space). The difference between the two is that a vector is a quantity (set of numbers that read as vector properties) that involves direction and magnitude but cannot describe the position using the same set of numbers. Therefore vectors direction nor magnitude won’t change when it is translated into a different position. Whereas a point describes a position in space but cannot describe direction nor magnitude. Users might know the difference between the two but computers will see just numbers.

For a computer, vector is just another container of real numbers that can be interpreted in a specific way. For example we can use 3 dimensional containers that store RGB colour values, UVW texture coordinates, XYZ point position, XYZ velocity and many more. And without specific directions, a software might not be aware of what type of vector we are dealing with.

Some software require users to specify the type of variable that is being defined. Some will assume that everything is a colour and applying specific functions willl force them to behave a different type. Some will see everything as a set of floats by default (like in Houdini) unless specified otherwise. Tracking data type or set of numbers are crucial for any computations otherwise results might be different than expected.
vector velocity = (1, 0, 0);
color Ce = (0.2, 1, 0.5);
normal N = (0, 1, 0);
When creating a new vector in Houdini, for example, using a VEX expression:
v@myvector = set(0.5, 1, 0.5);
Houdini doesn’t know the set of rules to apply. It tries to guess if your vector name is set to predefined names like “N”, “Cd”, “P”, “v” or “uv”. Houdini will just treat “myvector” as a container with 3 float values when middle clicking the node. A way to tell Houdini what kind of rule the vector is supposed to use setattribtypeinfo() which provides many different types of vectors like point, vector, normal and color.

Moving an object (displacement) in space when vector A = (1, 0, 0) and vector B = (0,1, 0) by adding together will create a sum with a displacement value where A + B = C = (1, 1, 0).
Another example of what how vectors can be used to manipulate an object with a wind direction of (-1.5, 0, 0) where we can add a noise (0, 0.5, 0) that creates a displacement vector result of (-1.5, 0.5, 0)
ROTATIONS
Dot Product

Described with a notation as follows a
b = abcos
that produces a scalar (quantity with magnitude) that represents the projection length of vector A and B. will provide the angle in between vectors.

An example that uses the dot product function is when creating fake collisions with a point.
Dot product can be manually calculated in Python as:
def dot(a, b):
c = a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
return c
Cross Product

Produces the perpendicular of a vector to the multiplicand and multiplier vectors.


A useful way to apply the cross product rule can be used is by comparing two planar areas
A Python function to find the cross product is as follows:
def cross(a, b):
c = [a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]]
return c
MATRICES
Similar to vectors, matrices are just rectangular containers/arrays of values. Matrices are described as having rows and columns that are distinguished as “square” matrix. In fact, vectors can be called a single row or a single column matrix.


The geometric interpretation in Maya is a 4 by 4 grid that represents the linear transformation as visualised from the images above.
Matrix Transformations

Combining two or more matrices with one another will perform a multiplication computation. It is a necessary requirement that the matrices “match in size” (by number of column in a row). Therefore extending matrices from 3×3 to 4×4 we are then able to apply the transformation.


In order to apply matrix transformation to a vector the similar rule must follow. Multiplying the vector with matrix 3×3 works by extending the vector to the 4th dimension.

When we apply a transformation matrix to a geometry, same mathematical calculation is being applied on each point separately.
The work below explores a few mathematical concepts:
- Ribbon Rig

I wanted to really learn more about the different deformers in Maya and so I tasked myself to create a ribbon rig which took about 3 days to complete. I had prior knowledge from the more bespoke rigging tasks that I was able to do.
I used a NURBs planar surface as the base geometry for the deformation. I needed to add evenly spaced joints so I opted to use the nHair system to generate follicles that would be placed on the surface. And then I needed to rename each follicle with a transform group, control and joint parented to one another. And in order to make the process less repetitive I wrote a script:
from maya import cmds # store the selected objects into a variable selection=cmds.ls(selection=True) # Loop through each selected item for x in range(0, len(selection)): # rename the curent item in thelist selection[x] = cmds.rename(selection[x], ('ribbon_follicle_' + str(x+1))) # create controller for the current follicle ctrl = cmds.circle(c=(0,0,0), nr=(1,0,0), r=0.5, ch=0, name=('ribbon_ctrl_' + str(x+1)))[0] # create joint for current follicle jnt = cmds.joint(radius=0.15, name=('ribbon_joint_' + str(x+1))) # group the controller grp = cmds.group(ctrl, name=(ctrl + '_xform_grp')) # set colour of the controller cmds.setAttr((cmds.listRelatives(ctrl, type='shape')[0] + '.overrideEnabled'), 1) cmds.setAttr((cmds.listRelatives(ctrl, type='shape')[0] + '.overrideColor'), 1) # parent the controller under the current follicle cmds.parent(grp, selection[x]) # position the controller at the follicle's position cmds.setAttr((grp + '.translate'), 0,0,0)Afterwards I created locator controls for the start, middle and end controls. I then added attributes that will drive the twist, sine deformations. For the twist deformer I had to use the plusminusaverage node to drive the twist and roll deformations. Using both connection editor and node editor to create connections to drive the process through.
I connected the locator controls using the wire deformer to drive and manipulate the curve. I had a double transform issues with the middle control and which was affected by the start and end controls that needed to be decreased to average out the influences.
I then was able to blend the different geometry deformers using blendshapes which behaved differently than I had anticipated. I had to check the inputs and change the hierarchy so that the wire deformer is driving the blendshapes which solved the problem. I added the final blendshape onto the original mesh which was able to behave accordingly.