@ch4dfun

Vector instructions in GRAB Assembly

0
0m read

In GRAB Assembly, you can now work with vectors using new vector instructions: VEC_SET, VEC_ADD, VEC_SUB, VEC_MUL, VEC_SCL, VEC_LEN, and VEC_DOT.

What are Vectors?

Vectors are groups of three consecutive registers that represent things like:

  • Position (X, Y, Z)
  • Rotation (X, Y, Z)
  • Color (R, G, B)

Instead of writing the same operation three times, vector instructions let you operate on all three components at once.

So for example, something like this:

MUL Obj.Pos.X Obj.Pos.X 0.5
MUL Obj.Pos.Y Obj.Pos.Y 0.5
MUL Obj.Pos.Z Obj.Pos.Z 0.5

becomes a single instruction:

VEC_SCL Obj.Pos.X Obj.Pos.X 0.5 ; X, Y, and Z all at once

How vectors work

If you pass Obj.Pos.X as a vector operand, the instruction uses Obj.Pos.X, Obj.Pos.Y, and Obj.Pos.Z. If you pass R0, it uses R0, R1, and R2.

This works with any registers that are laid out consecutively, which includes most connections. For example, Obj.Col.R is followed by Obj.Col.G and Obj.Col.B, so all three form a color vector.

Errors

Any vector instruction with a vector operand that does not have 3 consecutive registers will throw an error. Such as using R6 where there is no R8 for the third value.

Note: Special registers cannot be used as vectors

The Instructions

InstructionOperandsDescription
VEC_SETDST SRCDST..DST+2 = SRC..SRC+2
VEC_ADDDST A BDST..DST+2 = A..A+2 + B..B+2
VEC_SUBDST A BDST..DST+2 = A..A+2 - B..B+2
VEC_MULDST A BDST..DST+2 = A..A+2 * B..B+2
VEC_SCLDST A SDST..DST+2 = A..A+2 * S
VEC_LENDST ADST = length(A..A+2)
VEC_DOTDST A BDST = dot(A..A+2, B..B+2)
VEC_SET

VEC_SET copies three consecutive registers from a source vector to a destination vector.

VEC_SET R0 R3        ; (R0, R1, R2) = (R3, R4, R5)
VEC_SET Obj.Pos.X R0 ; Obj.Pos = (R0, R1, R2)

This is equivalent to writing three SET instructions:

SET Obj.Pos.X R0
SET Obj.Pos.Y R1
SET Obj.Pos.Z R2
VEC_ADD

VEC_ADD adds two vectors. Each register of A is added to the matching register of B.

VEC_ADD R0 R0 R3               ; (R0, R1, R2) += (R3, R4, R5)
VEC_ADD Obj.Pos.X Obj.Pos.X R0 ; Obj.Pos += (R0, R1, R2)

This is equivalent to writing three ADD instructions:

ADD Obj.Pos.X Obj.Pos.X R0
ADD Obj.Pos.Y Obj.Pos.Y R1
ADD Obj.Pos.Z Obj.Pos.Z R2
VEC_SUB

VEC_SUB subtracts two vectors.

VEC_SUB Obj.Pos.X Obj.Pos.X R0 ; Obj.Pos -= (R0, R1, R2)

This is equivalent to writing three SUB instructions:

SUB Obj.Pos.X Obj.Pos.X R0
SUB Obj.Pos.Y Obj.Pos.Y R1
SUB Obj.Pos.Z Obj.Pos.Z R2
VEC_MUL

VEC_MUL multiplies two vectors component-wise.

VEC_MUL Obj.Pos.X Obj.Pos.X R0 ; Obj.Pos *= (R0, R1, R2)

This is equivalent to writing three MUL instructions:

MUL Obj.Pos.X Obj.Pos.X R0
MUL Obj.Pos.Y Obj.Pos.Y R1
MUL Obj.Pos.Z Obj.Pos.Z R2
VEC_SCL

VEC_SCL multiplies each register of a vector by a single scalar value. The value can be a register or a constant.

VEC_SCL Obj.Pos.X Obj.Pos.X 0.5 ; scale Obj.Pos by half
VEC_SCL R0 R0 DeltaTime         ; scale (R0, R1, R2) by DeltaTime

This is equivalent to writing three MUL instructions:

MUL Obj.Pos.X Obj.Pos.X 0.5
MUL Obj.Pos.Y Obj.Pos.Y 0.5
MUL Obj.Pos.Z Obj.Pos.Z 0.5
VEC_LEN

VEC_LEN computes the length of a vector. The result is a single float, not a vector.

VEC_LEN R0 Obj.Pos.X ; R0 = sqrt(X^2 + Y^2 + Z^2)

This is equivalent to writing three MUL and two ADD instructions, followed by a SQRT:

MUL R0 Obj.Pos.X Obj.Pos.X
MUL R1 Obj.Pos.Y Obj.Pos.Y
MUL R2 Obj.Pos.Z Obj.Pos.Z
ADD R0 R0 R1
ADD R0 R0 R2
SQRT R0 R0
VEC_DOT

VEC_DOT computes the dot product of two vectors. The result is a single float.

VEC_DOT R0 Obj.Pos.X R3 ; R0 = X*R3 + Y*R4 + Z*R5

This is equivalent to writing three MUL and two ADD instructions:

MUL R0 Obj.Pos.X R3
MUL R1 Obj.Pos.Y R4
MUL R2 Obj.Pos.Z R5
ADD R0 R0 R1
ADD R0 R0 R2

Examples

Moving an object per frame

Instead of writing three ADD instructions, use VEC_ADD to move all at once:

LABEL loop
	VEC_ADD Obj.Pos.X Obj.Pos.X R0
	SLEEP 0
GOTO loop
Distance check

VEC_LEN combined with a comparison lets you check how far an object is from a target:

; get distance from object to player
VEC_SUB R0 Player.Pos.X Obj.Pos.X ; vector from obj to player
VEC_LEN R0 R0                     ; R0 = distance

; check if close enough
LESS R0 R0 5                      ; is distance < 5?
IF R0 do_something
Scaling a velocity vector
VEC_SCL R0 R0 DeltaTime        ; scale velocity by frame time
VEC_ADD Obj.Pos.X Obj.Pos.X R0 ; apply scaled velocity

That’s all for now

Thanks for reading, now go make something cool!

View Source