14.5. Making 3D Calculations

To make it easy to to make 3D Calculations, Kick Assembler supports vector and matrix values.

Vector values are used to hold 3D vectors. They are created by the Vector function that takes x, y and z as argument:

.var v1 = Vector(1,2,3)
.var v2 = Vector(0,0,2)

You can access the coordinates of the vector by its get functions and do the most common vector operations by the assigned functions. Here are some examples:

.var v1PlusV2 = v1+v2
.print "V1 scaled by 10 is " +  (v1*10)
.var dotProduct = v1*v2

Here is a list of vector functions and operators:

Table 14.3. Vector Value Functions

Function/Operator Example Description
get(n)   Returns the n'th coordinate (x=0, y=1, z=2).
getX()   Returns the x coordinate.
getY()   Returns the y coordinate.
getZ()   Returns the z coordinate.
+ Vector(1,2,3)+Vector(2,3,4) Returns the sum of two vectors.
- Vector(1,2,3)-Vector(2,3,4) Returns the result of a subtraction between the two vectors.
* Number Vector(1,2,3)* 4.2 Return the vector scaled by a number.
* Vector Vector(1,2,3)*Vector(2,3,4) Returns the dot product.
/ Vector(1,2,3)/2 Divides each coordinate by a factor and returns the result.
X(v) Vector(0,1,0).X(Vector(1,0,0)) Returns the cross product between two vectors.

The matrix value represents a 4x4 matrix. You create it by using the Matrix function, or one of the other constructor functions described later. You access the entries of the matrix by using its get and set functions:

.var matrix = Matrix()    // Creates an identity matrix
.eval matrix.set(2,3,100)
.print "Matrix.get(2,3)=" + matrix.get(2,3)
.print "The entire matrix=" + matrix

In 3d graphics matrixes are usually used to describe a transformation of a vector space. That can be to move the coordinates, to scale them, to rotate then, etc. The Matrix() operator creates an identity matrix, which is one that leaves the coordinates unchanged. By using the set function you can construct any matrix you like. However, Kick Assembler has constructor functions that create the most common transformation matrixes:

Table 14.4. Matrix Value Constructors

Function Description
Matrix() Creates an identity matrix.
RotationMatrix(aX,aY,aZ) Creates a rotation matrix where aX, aY and aZ are the angles rotated around the x, y and z axis. The angles are given in radians.
ScaleMatrix(sX,sY,sZ) Creates a scale matrix where the x coordinate is scaled by sX, the y-coordinate by sY and the z-coordinate by sZ.
MoveMatrix(mX,mY,mZ) Creates a move matrix that moves mX along the x-axis, mY along the y-axis and mZ along the z-axis.
PerspectiveMatrix(zProj) Creates a perspective projection where the eye-point is placed in (0,0,0) and coordinates are projected on the XY-plane where z=zProj.

You can multiply the matrixes and thereby combine their transformations. The transformation is read from right to left, so if you want to move the space 10 along the x axis and then rotate it 45 degrees around the z-axis, you write:

.var m = RotationMatrix(0,0,toRadians(45))*MoveMatrix(10,0,0)

To transform a coordinate you multiply the matrix to transformed vector:

.var v = m*Vector(10,0,0)
.print "Transformed v=" + v

The functions defined on matrixes are the following:

Table 14.5. Matrix Value Functions

Function/Operator Example Description
get(n,m)   Gets the value at n,m.
set(n,m,value)   Sets the value at n,m.
*Vector Matrix()*Vector(1,2,3) Return the product of the matrix and a vector.
*Matrix Matrix()*Matrix() Returns the product of two matrixes.

Here is a little program to illustrate how matrixes can be used. It pre calculates an animation of a cube that rotates around the x, y and z-axis and is projected on the plane where z=2.5. The data is placed at the label ‘cubeCoords’:

//--------------------------------------------------------------------------------
// Objects 
//--------------------------------------------------------------------------------
.var Cube = List().add( 
          Vector(1,1,1),  Vector(1,1,-1),  Vector(1,-1,1),  Vector(1,-1,-1),
          Vector(-1,1,1), Vector(-1,1,-1), Vector(-1,-1,1), Vector(-1,-1,-1))


//--------------------------------------------------------------------------------
// Macro for doing the precalculation
//--------------------------------------------------------------------------------
.macro PrecalcObject(object, animLength, nrOfXrot, nrOfYrot, nrOfZrot) {

    // Rotate the coordinate and place the coordinates of each frams in a list
    .var frames = List()
    .for(var frameNr=0; frameNr<animLength;frameNr++) {
        // Set up the transform matrix
        .var aX = toRadians(frameNr*360*nrOfXrot/animLength)
        .var aY = toRadians(frameNr*360*nrOfYrot/animLength)
        .var aZ = toRadians(frameNr*360*nrOfZrot/animLength)
        .var zp = 2.5 // z-coordinate for the projection plane
        .var m = ScaleMatrix(120,120,0)*
                    PerspectiveMatrix(zp)*
                    MoveMatrix(0,0,zp+5)*
                    RotationMatrix(aX,aY,aZ)

        // Transform the coordinates
        .var coords = List()
        .for (var i=0; i<object.size(); i++) {
            .eval coords.add(m*object.get(i))
        }
        .eval frames.add(coords)
    }

    // Dump the list to the memory
    .for (var coordNr=0; coordNr<object.size(); coordNr++) {
        .for (var xy=0;xy<2; xy++) {
            .fill animLength, $80+round(frames.get(i).get(coordNr).get(xy))
        }
    }
}
//--------------------------------------------------------------------------------
// The vector data
//--------------------------------------------------------------------------------
.align $100
cubeCoords: PrecalcObject(Cube,256,2,-1,1)
//--------------------------------------------------------------------------------