This adds support for a subset of HMD animation types. Specifically only coordinate update drivers (TGT==0) that use linear interpolation.
Bezier curve, B-Spline, and Beta-Spline interpolation is not supported yet.
General update drivers (TGT==1) is not supported yet. This would update individual vertices or normals.
Animation format
Animation is defined as a list of dataCount sequence pointers (just a data structure. "pointer" is just the name). Each sequence pointer defines what data will be changed for that part of the animation (like a coordinate that transforms models).
Each sequence pointer defines a count for the number of individual sequences (4-byte structures that appear after the sequence pointer structure). Consider each individual sequence a separate animation, while each sequence pointer in dataCount of the same individual sequence index is part of the same animation.
Example:
Each sequence pointer defines what data that part of the animation updates. Each sequence of each sequence pointer defines what instruction to start on, and what Stream ID (variable state) to start execution with.
SP 0: Updates coords[4] (TMDID 5)
Sequence 0: Part of animation 0
Sequence 1: Part of animation 1
Sequence 2: Part of animation 2
SP 1: Updates coords[3] (TMDID 4)
Sequence 0: Part of animation 0
Sequence 1: Part of animation 1
Sequence 2: Part of animation 2
Animations work by interpolating between coordinates (TGT==0) or individual data values (TGT==1). Values are changed using either Linear, Bezier Curve, B-Spline, or Beta-Spline interpolation. The type of interpolation can change during the animation sequence, though it's not clear if TGT can change...
Animations use a bytecode instruction set (each instruction is 4-bytes) that can perform Interpolation (normal instruction), Jumps, End the sequence (control instruction), or setup the work area for interpolation (control instruction).
A stream has 3 variables of note:
The current instruction index (idx).
The current Stream ID (sid). Consider this the one and only variable that can be used for conditional logic flow.
The current time. Time is incremented by the TFrame value of each Normal instruction.
Normal (interpolation) instructions always come in pairs. The first instruction must define TFRAME==0. A tframe of 0 means the instruction isn't ready to perform interpolation. Once an instruction where TFRAME!=0 is reached, interpolation is defined using this instruction as the destination values, and the last instruction as the source values.
The B-Spline interpolation type is special, in that it requires 3 source instructions before interpolation can start. In this case, 3 instructions must define TFRAME==0.
When the type of interpolation changes, instructions need to define a STOP (a normal instruction where TFRAME==0 using the current interpolation type). After that, instructions are added as the source for the new interpolation type (with TFRAME==0 until the source data is ready).
instruction / parameterIndex(or @jump) / tframe / interpolationType
0: jmp @1 // Commonly seen in animations, even if @1 is the start index.
1: norm p:0 t:0 f:0 // Pretend f:0 is linear interpolation type
2: norm p:1 t:3 f:0 // Linear using p:0 as source parameter
3: norm p:2 t:1 f:0 // Linear using p:1 as source parameter
4: norm p:3 t:1 f:0 // Linear using p:2 as source parameter
5: norm p:3 t:0 f:0 // Transition away from f:0 before B-Spline
6: norm p:10 t:0 f:1 // Pretend f:1 is B-Spline interpolation type
7: norm p:11 t:0 f:1
8: norm p:12 t:0 f:1
9: norm p:13 t:10 f:1 // B-Spline using p:10,11,12 as source parameters
10: norm p:14 t:7 f:1 // B-Spline using p:11,12,13 as source parameters
11: norm p:14 t:0 f:1 // Transition away from f:1 before looping
12: jmp @1 // Looping animations commonly start at the beginning
Preview of real animation instructions
![image](https://github.com/rickomax/psxprev/assets/9752430/3f7617ea-c1f8-4c80-a441-44f4fa84c161)
Animation support changes
Added OriginalWorldMatrix property for only using OriginalLocalMatrix.
Added TempWorldMatrix shortcut property for use in-place of TempMatrix * WorldMatrix.
Fixed FixConnections not accounting for TempMatrix.
FixConnections is now called while animating.
Changed how coords are parsed in HMD. There's no more need for a hacky nested check.
HMD coords are now parsed as CoordUnit classes.
Added support for parsing HMD animations using coordinate update drivers and linear interpolation.
HMD animations have a try catch around parsing so that failure will still allow reading the rest of the model.
Added disabled-by-default helper function to print the instructions used for HMD animation sequences. (WITH COLOR~)
RootEntity now stores a table of CoordUnits which are used solely for updating HMD animations.
Added HMD AnimationType.
Sanity check changes
Changed storage of dataSize and sequenceSize to be in byte units instead of 4-byte units. Because of this, MaxHMDDataSize has been multiplied by 4.
Coords can no longer be assinged to post-process primitives (if coord.ID > blockCount - 2).
This adds support for a subset of HMD animation types. Specifically only coordinate update drivers (TGT==0) that use linear interpolation.
Animation format
Animation is defined as a list of
dataCount
sequence pointers (just a data structure. "pointer" is just the name). Each sequence pointer defines what data will be changed for that part of the animation (like a coordinate that transforms models).Each sequence pointer defines a count for the number of individual sequences (4-byte structures that appear after the sequence pointer structure). Consider each individual sequence a separate animation, while each sequence pointer in
dataCount
of the same individual sequence index is part of the same animation.Example: Each sequence pointer defines what data that part of the animation updates. Each sequence of each sequence pointer defines what instruction to start on, and what Stream ID (variable state) to start execution with.
Animations work by interpolating between coordinates (TGT==0) or individual data values (TGT==1). Values are changed using either Linear, Bezier Curve, B-Spline, or Beta-Spline interpolation. The type of interpolation can change during the animation sequence, though it's not clear if TGT can change...
Animations use a bytecode instruction set (each instruction is 4-bytes) that can perform Interpolation (normal instruction), Jumps, End the sequence (control instruction), or setup the work area for interpolation (control instruction).
A stream has 3 variables of note:
idx
).sid
). Consider this the one and only variable that can be used for conditional logic flow.Normal (interpolation) instructions always come in pairs. The first instruction must define TFRAME==0. A tframe of 0 means the instruction isn't ready to perform interpolation. Once an instruction where TFRAME!=0 is reached, interpolation is defined using this instruction as the destination values, and the last instruction as the source values.
The B-Spline interpolation type is special, in that it requires 3 source instructions before interpolation can start. In this case, 3 instructions must define TFRAME==0.
When the type of interpolation changes, instructions need to define a STOP (a normal instruction where TFRAME==0 using the current interpolation type). After that, instructions are added as the source for the new interpolation type (with TFRAME==0 until the source data is ready).
Preview of real animation instructions
![image](https://github.com/rickomax/psxprev/assets/9752430/3f7617ea-c1f8-4c80-a441-44f4fa84c161)Animation support changes
Sanity check changes