/* 
    Delta Compression (Round 2) by Glenn Fiedler. 
    This source code is placed in the public domain.
    http://gafferongames.com/2015/03/14/the-networked-physics-data-compression-challenge/
*/

#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>

static const int NumCubes = 901;

template <typename T> const T & max( const T & a, const T & b )
{
    return ( a > b ) ? a : b;
}

struct FrameCubeData
{
    float orientation_x;
    float orientation_y;
    float orientation_z;
    float orientation_w;
    float position_x;
    float position_y;
    float position_z;
};

struct Frame
{
    FrameCubeData cubes[NumCubes];
};

int main( int argc, char ** argv )
{
    FILE * file = fopen( "delta_data_round_two.bin", "rb" );
    if ( !file )
    {
        printf( "error: can't open file\n" );
        return 1;
    }

    // count number of frames in file

    fseek( file, 0L, SEEK_END );
    uint64_t file_size = ftell( file );
    fseek( file, 0L, SEEK_SET );

    const int num_frames = (int) floor( double(file_size) / sizeof( Frame ) );
    printf( "%d input frames\n", num_frames );
    assert( num_frames > 6 );

    // read in frames

    Frame * frames = new Frame[num_frames];
    uint64_t frames_read = fread( frames, sizeof( Frame ), num_frames, file );
    assert( frames_read == num_frames );
    fclose( file );

    // output orientation, base orientation, and base base orientation to text file

    FILE * output_file = fopen( "orientation_values.txt", "w" );
    for ( int i = 6; i < num_frames; ++i )
    {
        const Frame & current = frames[i];
        const Frame & base = frames[max(0,i-6)];
        const Frame & base_base = frames[max(0,i-6*2)];

        for ( int j = 0; j < NumCubes; ++j )
        {
            fprintf( output_file, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n", 
                current.cubes[j].orientation_x,
                current.cubes[j].orientation_y,
                current.cubes[j].orientation_z,
                current.cubes[j].orientation_w,
                base.cubes[j].orientation_x,
                base.cubes[j].orientation_y,
                base.cubes[j].orientation_z,
                base.cubes[j].orientation_w,
                base_base.cubes[j].orientation_x,
                base_base.cubes[j].orientation_y,
                base_base.cubes[j].orientation_z,
                base_base.cubes[j].orientation_w );
        }
    }
    fclose( output_file );

    // clean up everything

    delete [] frames;

    return 0;
}