PS2 Linux Programming
2D Sprite Rotation Using VU1
Introduction
In this tutorial the techniques introduced in the
previous tutorial “Simple Vertex Transformation With VU1” are extended to
perform the rotation of a sprite in two dimensions. All of the sprite vertex
transformations (rotation, offset translation and conversion from floating
point to 12:4 fixed point) are performed with VU1 using a micro program. Data
transfer to the GS is over PATH 1.
This tutorial is very similar to the previous one “Simple
Vertex Transformation With VU1” but with the following additions:
·
The packet that is
sent to VIF1 has a floating point value, which is the angle by which the sprite
is to be rotated, stored in the second qword. This is the qword immediately
after the UNPACK VIF code.
·
The bulk of the VIF
packet is pre-built and stored in unswappable SPS2 memory.
·
The angle parameter
is incremented 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 VU1 processing
consists of calculating the sin and cos of an angle, rotating the sprite
vertices round their local origin, adding on the 2048 GSmem offset to the
vertices, then converting the floating point vertex points to 12:4 fixed point.
It can now be seen that much of the vertex
transformation processing has been offloaded from the main CPU to VU1.
Now the VU code in file vu1code.vcl will be
investigated. It is reproduced below for clarity.
Angle |
.equ |
0 |
StartVert |
.equ |
4 |
NumVerts |
.equ |
4 |
.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 |
|
|
|
lq.x |
fAngle, Angle(vi00) |
; Load the angle |
add.z |
fAngle, vf00, vf00 |
; AngleSinCos takes
another angle in .z |
|
|
|
AngleSinCos |
fAngle, fSinCos |
; Calculate Sin and Cos
of angle |
|
|
|
add.x |
fCosNSin, vf00,
fSinCos[y] |
; fCosNSin makes it
easier to |
|
|
|
sub.y |
fCosNSin, vf00,
fSinCos[x] |
; Rotate the X
coordinate |
loi |
2048.0 |
; Put 2048 into the I
register |
|
|
|
loop: |
|
; For each vertex |
--LoopCS 4,0 |
|
; Minimum of 4
iterations |
|
|
|
lq.xy |
fVert, 0(iVertPtr) |
; Load the XY components
of the vert |
mul.xy |
fTransX, fVert, fCosNSin |
; float tlX = _tlX *
cosi - _tlY * sini |
mul.xy |
fTransY, fVert, fSinCos |
; float tlY = _tlX *
sini + _tlY * cosi |
add.x |
fVert, fTransX,
fTransX[y] |
|
add.y |
fVert, fTransY,
fTransY[x] |
|
add.xy |
fVert, fVert, |
; Add 2048 to the XY
components |
ftoi4.xy |
fVert, fVert |
; Convert to 12:4 fixed
point |
sq.xy |
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 which can be used. In the subsequent code, the macro AngleSinCos,
which calculates the sin and cos of two angles is used. This macro takes two
angles, one in the .x component and one in the .z component of a vector,
computes the sin and cos of both of these angles and stores the results in the
output vector which holds the two sins and the two cosines. Take a look at the
.inc file for more information.
From the tutorial “2D Sprite Movement With Angles” it
will be recalled that the formula to rotate a vertex about the origin is:
x' = x * cos - y * sin
y' = x * sin + y * cos
where x’ and x are the transformed and
untransformed vertices respectively. The untransformed vertices are multiplied
by the variables SinCos and CosNSin (cos with negative sin) to produce the
transformed vertices. 2048 is added to each of the vertices then they are
converted from floating point to 12:4 fixed point. Once all of the vertices are
transformed they are sent of to the GS (xgkick) 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 two dimensions.
Dr Henry S Fortuna
University of Abertay
Dundee