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.

 

 

The Example Program

 

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

 

 

Conclusions

 

In this tutorial VU1 has been used to perform sprite rotation in two dimensions.

 

Dr Henry S Fortuna

University of Abertay Dundee

h.s.fortuna@abertay.ac.uk