PS2 Linux Programming
Simple Matrix Transformation with VU1
Introduction
In this tutorial VU1 is used to transform the
vertices of a textured quad using a transformation matrix that is uploaded to
VU1 data memory every frame.
The structure of the packet loaded into VU1 data
memory each frame is outline below. The first four locations contain the
transformation matrix, this being followed by the GIFTag then the untransformed
vertex data.
Address |
Contents |
0x000 |
Matrix Row 0 |
0x001 |
Matrix Row 1 |
0x002 |
Matrix Row 2 |
0x003 |
Matrix Row 3 |
0x004 |
GIFTag |
0x005 |
STQ for Vertex 0 |
0x006 |
RGBA for Vertex 0 |
0x007 |
Position for Vertex 0 |
0x008 |
STQ for Vertex 1 |
0x009 |
RGBA for Vertex 1 |
0x00A |
Position for Vertex 1 |
0x00B |
STQ for Vertex 2 |
0x00C |
RGBA for Vertex 2 |
0x00D |
Position for Vertex 2 |
0x00E |
STQ for Vertex 3 |
0x00F |
RGBA for Vertex 3 |
0x010 |
Position for Vertex 3 |
The flow of the main program code is detailed given
below:
·
The packet sent to
VIF1 is 4 kBytes in size. There are VIF codes at the start and end of the
packet.
·
The UNPACK VIF Code
at the start of the packet unpacks 254 qwords, this being 256 qwords (4 kBytes)
minus the 2 qwords containing VIF Codes at the start and end of the packet.
·
The bulk of the VIF
packet is pre-built and stored in unswappable SPS2 memory.
·
The transformation
matrix is altered slightly each frame and stored in the correct location in the
VIF packet.
·
The VIF packet is
sent to VU1 each frame to be processed.
The VU code in file vu1code.vcl is shown below.
StartVert |
equ 7 |
; The first vertex is at
address 7 |
NumVerts |
equ 4 |
; There are 4 vertices |
.include "vcl_sml.inc"
.init_vf_all
.init_vi_all
.syntax new
.vu
--enter
--endenter
iaddiu |
iVert, vi00, 0 |
; Start vertex counter |
iaddiu |
iVertPtr, vi00, StartVert |
; Point to the first
vert |
iaddiu |
iNumVerts, vi00,
NumVerts |
; Load the loop end
condition |
|
|
|
MatrixLoad |
fRotMatrix,0,vi00 |
; Load the matrix from
VUMEM 0 |
|
|
|
|
|
|
loop: |
|
; For each vertex |
--LoopCS 4,0 |
|
; Minimum of 4
iterations |
|
|
|
lq.xy |
fVert, 0(iVertPtr) |
; Load the XY components
of the vert |
MatrixMultiplyVertex |
fVert,fRotMatrix,fVert |
; Rotate the vertex |
ftoi4.xy |
fVert, fVert |
; Convert to 12:4 fixed
point |
ftoi0.z |
fVert, fVert |
; Convert z to integer |
mfir.w |
fVert, vi00 |
; set ADC to zero (DRAW) |
sq.xyzw |
fVert, 0(iVertPtr) |
; Store the newly
converted data |
addiu |
iVert, iVert, 1 |
; Increment the vertex
counter |
iaddiu |
iVertPtr, iVertPtr, 3 |
; Increment the vertex
pointer |
ibne |
iVert, iNumVerts, loop |
; Branch back to
"loop" label if |
|
|
; iVert and iNumVerts
are not equal |
iaddiu |
iGIFTag, vi00, 1 |
; Kick the data at VUMEM
location 1 |
xgkick |
iGIFTag |
; to the GS |
|
|
|
--exit
--endexit
The first thing to be notices about this code is
that the file vcl_sml.inc is included. This file (supplied by Sony) contains
useful macros. The macro MatrixLoad, loads the matrix data into floating point
registers from data memory and the macro MatrixMultiplyVertex multiplies a
vector containing vertex data by a matrix.
The reader is directed to the tutorial “2D Sprite
Movement With Matrices (3D?)” for further information about this process. After
the vertex data is transformed, the floating point x and y values are converted
into 12:4 fixed point format and the z value is converted into an integer. It
can be seen that there are appropriate VU instructions to perform the
conversions.
Once all of the vertices are transformed they are
sent of to the GS using the xgkick instruction for drawing.
It is recommended that the details of this VU code
are investigated with the addition of the VU Users Manual
In this tutorial VU1 has been used to perform
sprite rotation in three dimensions with the application of a transformation
matrix.
Dr Henry S Fortuna
University of Abertay
Dundee