rickomax / psxprev

PSXPREV - Playstation (PSX) Files Previewer/Extractor
BSD 2-Clause "Simplified" License
193 stars 10 forks source link

Add HMD animation coordinate linear interpolation support #68

Closed trigger-segfault closed 12 months ago

trigger-segfault commented 12 months ago

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:

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

Sanity check changes