Created
October 3, 2014 08:07
-
-
Save mikearmstrong001/3355da4794527fe91cae to your computer and use it in GitHub Desktop.
Random train snippets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// brickportals.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <malloc.h> | |
#include <vector> | |
#include <map> | |
#include <set> | |
class sparebitset | |
{ | |
std::map<unsigned int, unsigned char> bits; | |
public: | |
void set( unsigned int index ) | |
{ | |
bits[index/8] |= (index%8); | |
} | |
bool get( unsigned int index ) | |
{ | |
return (bits[index/8] & (index%8)) ? true : false; | |
} | |
}; | |
struct brick | |
{ | |
int version; | |
int x, y, z; | |
unsigned char solid[256][256][256/8]; | |
}; | |
void *readfile( const char *filename, int *len = NULL ) | |
{ | |
if ( filename == NULL ) | |
return NULL; | |
FILE *f = fopen( filename, "rb" ); | |
if ( f ) | |
{ | |
fseek( f, 0, SEEK_END ); | |
int l = ftell( f ); | |
fseek( f, 0, SEEK_SET ); | |
char *mem = (char*)malloc( l + 1 ); | |
fread( mem, l, 1, f ); | |
mem[l] = 0; | |
fclose( f ); | |
if ( len ) | |
{ | |
*len = l; | |
} | |
return mem; | |
} | |
else | |
{ | |
return NULL; | |
} | |
} | |
struct node | |
{ | |
short box[2][3]; | |
node *kids[2]; | |
int id; | |
short group; | |
node() | |
{ | |
kids[0] = kids[1] = NULL; | |
} | |
~node() | |
{ | |
delete kids[0]; | |
delete kids[1]; | |
} | |
}; | |
inline int min( int a, int b ) | |
{ | |
return (a<b) ? a : b; | |
} | |
inline int max( int a, int b ) | |
{ | |
return (a>b) ? a : b; | |
} | |
node* genportals( brick *b, int mnx, int mny, int mnz, int mxx, int mxy, int mxz, int depth, int axis ) | |
{ | |
if ( b == NULL ) | |
{ | |
node *n = new node; | |
n->box[0][0] = mnx; | |
n->box[0][1] = mny; | |
n->box[0][2] = mnz; | |
n->box[1][0] = mxx; | |
n->box[1][1] = mxy; | |
n->box[1][2] = mxz; | |
n->kids[0] = NULL; | |
n->kids[1] = NULL; | |
return n; | |
} | |
if ( depth ) | |
{ | |
int mdy = (mny+mxy) / 2; | |
int mdz = (mnz+mxz) / 2; | |
node *g0; | |
node *g1; | |
if ( axis == 0 ) | |
{ | |
int mdx = (mnx+mxx) / 2; | |
g0 = genportals( b, mnx, mny, mnz, mdx, mxy, mxz, depth-1, (axis+1)%3 ); | |
g1 = genportals( b, mdx, mny, mnz, mxx, mxy, mxz, depth-1, (axis+1)%3 ); | |
} | |
else | |
if ( axis == 1 ) | |
{ | |
int mdy = (mny+mxy) / 2; | |
g0 = genportals( b, mnx, mny, mnz, mxx, mdy, mxz, depth-1, (axis+1)%3 ); | |
g1 = genportals( b, mnx, mdy, mnz, mxx, mxy, mxz, depth-1, (axis+1)%3 ); | |
} | |
else | |
//if ( axis == 2 ) | |
{ | |
int mdz = (mnz+mxz) / 2; | |
g0 = genportals( b, mnx, mny, mnz, mxx, mxy, mdz, depth-1, (axis+1)%3 ); | |
g1 = genportals( b, mnx, mny, mdz, mxx, mxy, mxz, depth-1, (axis+1)%3 ); | |
} | |
// both empty combine | |
if ( g0 && g1 && g0->kids[0] == NULL && g1->kids[1] == NULL ) | |
{ | |
node *n = new node; | |
n->box[0][0] = mnx; | |
n->box[0][1] = mny; | |
n->box[0][2] = mnz; | |
n->box[1][0] = mxx; | |
n->box[1][1] = mxy; | |
n->box[1][2] = mxz; | |
n->kids[0] = NULL; | |
n->kids[1] = NULL; | |
delete g0; | |
delete g1; | |
return n; | |
} | |
else | |
if ( g0 == NULL && g1 == NULL ) | |
{ | |
return NULL; | |
} | |
else | |
{ | |
node *n = new node; | |
n->box[0][0] = mnx; | |
n->box[0][1] = mny; | |
n->box[0][2] = mnz; | |
n->box[1][0] = mxx; | |
n->box[1][1] = mxy; | |
n->box[1][2] = mxz; | |
n->kids[0] = g0; | |
n->kids[1] = g1; | |
return n; | |
} | |
} | |
else | |
{ | |
bool g = false; | |
for (int z=mnz; z<mxz; z++) | |
{ | |
for (int y=mny; y<mxy; y++) | |
{ | |
for (int x=mnx; x<mxx; x++) | |
{ | |
if ( b->solid[z][y][x/8] & (1<<(x%8)) ) | |
g = true; | |
} | |
} | |
} | |
if ( g ) | |
{ | |
return NULL; | |
} | |
else | |
{ | |
node *n = new node; | |
n->box[0][0] = mnx; | |
n->box[0][1] = mny; | |
n->box[0][2] = mnz; | |
n->box[1][0] = mxx; | |
n->box[1][1] = mxy; | |
n->box[1][2] = mxz; | |
n->kids[0] = NULL; | |
n->kids[1] = NULL; | |
return n; | |
} | |
} | |
} | |
void outputleafboxes( FILE *f, node *n ) | |
{ | |
if ( n == NULL ) | |
return; | |
if ( n->kids[0]==NULL && n->kids[1]==NULL ) | |
{ | |
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[0][1], n->box[0][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[0][1], n->box[0][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[1][1], n->box[0][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[1][1], n->box[0][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[0][1], n->box[1][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[0][1], n->box[1][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[1][1], n->box[1][2] ); | |
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[1][1], n->box[1][2] ); | |
fprintf( f, "f -8 -7 -5 -6\n" ); | |
fprintf( f, "f -6 -5 -1 -2\n" ); | |
fprintf( f, "f -8 -6 -2 -4\n" ); | |
fprintf( f, "f -7 -8 -4 -3\n" ); | |
fprintf( f, "f -5 -7 -3 -1\n" ); | |
fprintf( f, "f -1 -2 -4 -3\n" ); | |
} | |
else | |
{ | |
outputleafboxes( f, n->kids[0] ); | |
outputleafboxes( f, n->kids[1] ); | |
} | |
} | |
void addleaves( std::vector<node*> &leaves, node *n ) | |
{ | |
if ( n == NULL ) | |
return; | |
if ( n->kids[0]==NULL && n->kids[1]==NULL ) | |
{ | |
leaves.push_back( n ); | |
} | |
else | |
{ | |
addleaves( leaves, n->kids[0] ); | |
addleaves( leaves, n->kids[1] ); | |
} | |
} | |
bool touching( node *a, node *b ) | |
{ | |
for (int axis=0; axis<3; axis++) | |
{ | |
if ( a->box[1][axis] < b->box[0][axis] ) | |
return false; | |
if ( a->box[0][axis] > b->box[1][axis] ) | |
return false; | |
} | |
return true; | |
} | |
struct quad | |
{ | |
short v[4][3]; | |
}; | |
quad generatequad( node *n, int face ) | |
{ | |
const static int faceids[6][4] = | |
{ | |
{ 0, 2, 6, 4 }, // ---, -+-, -++, --+ -x | |
{ 1, 0, 4, 5 }, // +--, ---, --+, +-+ -y | |
{ 0, 1, 3, 2 }, // ---, +--, ++-, -+- -z | |
{ 3, 1, 5, 7 }, // ++-, +--, +-+, +++ +x | |
{ 2, 3, 7, 6 }, // -+-, ++-, +++, -++ +y | |
{ 7, 6, 4, 5 }, // +++, -++, --+, +-+ +z | |
}; | |
quad q; | |
for (int i=0; i<4; i++) | |
{ | |
q.v[i][0] = faceids[face][i] & 1 ? n->box[1][0] : n->box[0][0]; | |
q.v[i][1] = faceids[face][i] & 2 ? n->box[1][1] : n->box[0][1]; | |
q.v[i][2] = faceids[face][i] & 4 ? n->box[1][2] : n->box[0][2]; | |
} | |
return q; | |
} | |
quad clipquad( quad q, node *n ) | |
{ | |
quad empty; | |
memset( &empty, 0, sizeof(empty) ); | |
int bb[2][4]; | |
bb[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) ); | |
bb[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) ); | |
bb[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) ); | |
bb[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) ); | |
bb[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) ); | |
bb[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) ); | |
for (int axis=0; axis<3; axis++) | |
{ | |
if ( bb[1][axis] < n->box[0][axis] ) | |
return empty; | |
if ( bb[0][axis] > n->box[1][axis] ) | |
return empty; | |
} | |
for (int i=0; i<4; i++) | |
{ | |
q.v[i][0] = max( n->box[0][0], min( n->box[1][0], q.v[i][0] ) ); | |
q.v[i][1] = max( n->box[0][1], min( n->box[1][1], q.v[i][1] ) ); | |
q.v[i][2] = max( n->box[0][2], min( n->box[1][2], q.v[i][2] ) ); | |
} | |
return q; | |
} | |
bool isvalidquad( quad const &q ) | |
{ | |
int mn[3] = { q.v[0][0], q.v[0][1], q.v[0][2] }; | |
int mx[3] = { q.v[0][0], q.v[0][1], q.v[0][2] }; | |
for (int i=0; i<4; i++) | |
{ | |
mn[0] = min( mn[0], q.v[i][0] ); | |
mn[1] = min( mn[1], q.v[i][1] ); | |
mn[2] = min( mn[2], q.v[i][2] ); | |
mx[0] = max( mx[0], q.v[i][0] ); | |
mx[1] = max( mx[1], q.v[i][1] ); | |
mx[2] = max( mx[2], q.v[i][2] ); | |
} | |
int count = 0; | |
count += (mn[0] == mx[0]) ? 0 : 1; | |
count += (mn[1] == mx[1]) ? 0 : 1; | |
count += (mn[2] == mx[2]) ? 0 : 1; | |
return count == 2; | |
} | |
void outputquad( FILE *f, quad const &q ) | |
{ | |
fprintf( f, "v %d %d %d\n", q.v[0][0], q.v[0][1], q.v[0][2] ); | |
fprintf( f, "v %d %d %d\n", q.v[1][0], q.v[1][1], q.v[1][2] ); | |
fprintf( f, "v %d %d %d\n", q.v[2][0], q.v[2][1], q.v[2][2] ); | |
fprintf( f, "v %d %d %d\n", q.v[3][0], q.v[3][1], q.v[3][2] ); | |
fprintf( f, "f -1 -2 -3 -4\n" ); | |
} | |
node *createbound( int mnx, int mny, int mnz, int mxx, int mxy, int mxz ) | |
{ | |
node *n = new node; | |
n->box[0][0] = mnx; | |
n->box[0][1] = mny; | |
n->box[0][2] = mnz; | |
n->box[1][0] = mxx; | |
n->box[1][1] = mxy; | |
n->box[1][2] = mxz; | |
n->kids[0] = NULL; | |
n->kids[1] = NULL; | |
return n; | |
} | |
node *findfreenode( std::vector< node* > const &leaves ) | |
{ | |
for (unsigned int i=0; i<leaves.size(); i++) | |
{ | |
if ( leaves[i]->group == -1 ) | |
return leaves[i]; | |
} | |
return NULL; | |
} | |
#include <assert.h> | |
void floodfill( node *n, std::vector< node* > const &leaves, std::map<int,std::set<int>> &connected, int group ) | |
{ | |
assert( n->group == -1 ); | |
n->group = group; | |
std::set<int>::const_iterator b = connected[n->id].cbegin(); | |
while ( b != connected[n->id].cend() ) | |
{ | |
int c = *b++; | |
if ( leaves[c]->group == group ) | |
{ | |
continue; | |
} | |
floodfill( leaves[c], leaves, connected, group ); | |
} | |
} | |
bool canmerge( node *a, node *b ) | |
{ | |
if ( a->group != b->group ) | |
return false; | |
for (int axis=0; axis<3; axis++) | |
{ | |
if ( a->box[1][axis] < b->box[0][axis] ) | |
return false; | |
if ( a->box[0][axis] > b->box[1][axis] ) | |
return false; | |
int ext0 = (axis+1)%3; | |
int ext1 = (axis+2)%3; | |
if ( a->box[0][ext0] == b->box[0][ext0] && | |
a->box[0][ext1] == b->box[0][ext1] && | |
a->box[1][ext0] == b->box[1][ext0] && | |
a->box[1][ext1] == b->box[1][ext1] ) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
void merge( node *a, node *b ) | |
{ | |
a->box[0][0] = min( a->box[0][0], b->box[0][0] ); | |
a->box[0][1] = min( a->box[0][1], b->box[0][1] ); | |
a->box[0][2] = min( a->box[0][2], b->box[0][2] ); | |
a->box[1][0] = max( a->box[1][0], b->box[1][0] ); | |
a->box[1][1] = max( a->box[1][1], b->box[1][1] ); | |
a->box[1][2] = max( a->box[1][2], b->box[1][2] ); | |
b->group = -1; | |
} | |
struct cellbound | |
{ | |
short bb[2][3]; | |
int group; | |
}; | |
struct portal | |
{ | |
short v[2][3]; | |
short group; | |
unsigned char other_group; | |
unsigned char other_cell; | |
}; | |
struct cell | |
{ | |
int grid[3]; | |
std::vector< cellbound > bounds; | |
std::vector< portal > portals; | |
sparebitset vis; | |
}; | |
struct plane | |
{ | |
float n[3]; | |
int loc[3]; | |
}; | |
void fwriteint( FILE *f, int v ) | |
{ | |
fwrite( &v, sizeof(v), 1, f ); | |
} | |
void fwriteshort( FILE *f, short v ) | |
{ | |
fwrite( &v, sizeof(v), 1, f ); | |
} | |
int freadint( FILE *f ) | |
{ | |
int v; | |
fread( &v, sizeof(v), 1, f ); | |
return v; | |
} | |
short freadshort( FILE *f ) | |
{ | |
short v; | |
fread( &v, sizeof(v), 1, f ); | |
return v; | |
} | |
void writecell( const char *filename, cell &c ) | |
{ | |
FILE *f = fopen( filename, "wb" ); | |
if ( f ) | |
{ | |
fwriteint( f, 0x100 ); | |
fwriteint( f, c.grid[0] ); | |
fwriteint( f, c.grid[1] ); | |
fwriteint( f, c.grid[2] ); | |
fwriteint( f, c.bounds.size() ); | |
fwriteint( f, c.portals.size() ); | |
for (unsigned int i=0; i<c.bounds.size(); i++) | |
{ | |
fwriteshort( f, c.bounds[i].bb[0][0] ); | |
fwriteshort( f, c.bounds[i].bb[0][1] ); | |
fwriteshort( f, c.bounds[i].bb[0][2] ); | |
fwriteshort( f, c.bounds[i].bb[1][0] ); | |
fwriteshort( f, c.bounds[i].bb[1][1] ); | |
fwriteshort( f, c.bounds[i].bb[1][2] ); | |
fwriteint( f, c.bounds[i].group ); | |
} | |
for (unsigned int i=0; i<c.portals.size(); i++) | |
{ | |
fwriteshort( f, c.portals[i].v[0][0] ); | |
fwriteshort( f, c.portals[i].v[0][1] ); | |
fwriteshort( f, c.portals[i].v[0][2] ); | |
fwriteshort( f, c.portals[i].v[1][0] ); | |
fwriteshort( f, c.portals[i].v[1][1] ); | |
fwriteshort( f, c.portals[i].v[1][2] ); | |
fwriteint( f, c.portals[i].group ); | |
fwriteint( f, c.portals[i].other_cell ); | |
fwriteint( f, c.portals[i].other_group ); | |
} | |
fclose( f ); | |
} | |
} | |
void writeobjofcell( const char *filename, cell *cs, int numcells ) | |
{ | |
FILE *f = fopen( filename, "wb" ); | |
if ( f ) | |
{ | |
for (int n=0; n<numcells; n++) | |
{ | |
cell &c = cs[n]; | |
for (unsigned int i=0; i<c.portals.size(); i++) | |
{ | |
portal &p = c.portals[i]; | |
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[0][1], p.v[0][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[0][1], p.v[0][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[1][1], p.v[0][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[1][1], p.v[0][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[0][1], p.v[1][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[0][1], p.v[1][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[1][1], p.v[1][2] ); | |
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[1][1], p.v[1][2] ); | |
fprintf( f, "f -8 -7 -5 -6\n" ); | |
fprintf( f, "f -6 -5 -1 -2\n" ); | |
fprintf( f, "f -8 -6 -2 -4\n" ); | |
fprintf( f, "f -7 -8 -4 -3\n" ); | |
fprintf( f, "f -5 -7 -3 -1\n" ); | |
fprintf( f, "f -1 -2 -4 -3\n" ); | |
} | |
} | |
fclose( f ); | |
} | |
} | |
void offsetcell( cell &c, int ox, int oy, int oz ) | |
{ | |
for (unsigned int i=0; i<c.bounds.size(); i++) | |
{ | |
c.bounds[i].bb[0][0] += ox; | |
c.bounds[i].bb[0][1] += oy; | |
c.bounds[i].bb[0][2] += oz; | |
c.bounds[i].bb[1][0] += ox; | |
c.bounds[i].bb[1][1] += oy; | |
c.bounds[i].bb[1][2] += oz; | |
} | |
for (unsigned int i=0; i<c.portals.size(); i++) | |
{ | |
c.portals[i].v[0][0] += ox; | |
c.portals[i].v[0][1] += oy; | |
c.portals[i].v[0][2] += oz; | |
c.portals[i].v[1][0] += ox; | |
c.portals[i].v[1][1] += oy; | |
c.portals[i].v[1][2] += oz; | |
} | |
} | |
bool readcell( cell &c, const char *filename, int ox, int oy, int oz ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f ) | |
{ | |
int version = freadint( f ); | |
assert( version == 0x100 ); | |
c.grid[0] = freadint( f ); | |
c.grid[1] = freadint( f ); | |
c.grid[2] = freadint( f ); | |
c.bounds.resize( freadint( f ) ); | |
c.portals.resize( freadint( f ) ); | |
for (unsigned int i=0; i<c.bounds.size(); i++) | |
{ | |
c.bounds[i].bb[0][0] = freadshort( f ) + ox; | |
c.bounds[i].bb[0][1] = freadshort( f ) + oy; | |
c.bounds[i].bb[0][2] = freadshort( f ) + oz; | |
c.bounds[i].bb[1][0] = freadshort( f ) + ox; | |
c.bounds[i].bb[1][1] = freadshort( f ) + oy; | |
c.bounds[i].bb[1][2] = freadshort( f ) + oz; | |
c.bounds[i].group = freadint( f ); | |
} | |
for (unsigned int i=0; i<c.portals.size(); i++) | |
{ | |
c.portals[i].v[0][0] = freadshort( f ) + ox; | |
c.portals[i].v[0][1] = freadshort( f ) + oy; | |
c.portals[i].v[0][2] = freadshort( f ) + oz; | |
c.portals[i].v[1][0] = freadshort( f ) + ox; | |
c.portals[i].v[1][1] = freadshort( f ) + oy; | |
c.portals[i].v[1][2] = freadshort( f ) + oz; | |
c.portals[i].group = freadint( f ); | |
c.portals[i].other_cell = freadint( f ); | |
c.portals[i].other_group = freadint( f ); | |
} | |
fclose( f ); | |
return true; | |
} | |
return false; | |
} | |
void makecell( cell &c, const char *cellfilename, const char *voxelfilename ) | |
{ | |
brick *b = (brick*)readfile( voxelfilename ); | |
node *n = genportals( b, 0, 0, 0, 256, 256, 256, 10, 0 ); | |
c.grid[0] = b ? b->x : 0; | |
c.grid[1] = b ? b->y : 0; | |
c.grid[2] = b ? b->z : 0; | |
free( b ); | |
std::vector< node* > leaves; | |
addleaves( leaves, n ); | |
{ | |
std::map<int,std::set<int>> connected; | |
for (unsigned int i=0; i<leaves.size(); i++) | |
{ | |
leaves[i]->id = i; | |
leaves[i]->group = -1; | |
for (unsigned int j=0; j<leaves.size(); j++) | |
{ | |
if ( i == j ) | |
continue; | |
if ( !touching( leaves[i], leaves[j] ) ) | |
continue; | |
for (int face=0; face<6; face++) | |
{ | |
quad q = clipquad( generatequad( leaves[i], face ), leaves[j] ); | |
if ( isvalidquad( q ) ) | |
{ | |
connected[i].insert(j); | |
} | |
} | |
} | |
} | |
int group = 0; | |
do | |
{ | |
node *n = findfreenode( leaves ); | |
if ( n == NULL ) | |
break; | |
floodfill( n, leaves, connected, group ); | |
group++; | |
} while ( true ); | |
} | |
{ | |
bool done = false; | |
while ( !done ) | |
{ | |
done = true; | |
for (unsigned int i=0; i<leaves.size(); i++) | |
{ | |
if ( leaves[i]->group == -1 ) | |
continue; | |
for (unsigned int j=0; j<leaves.size(); j++) | |
{ | |
if ( i == j ) | |
continue; | |
if ( leaves[j]->group == -1 ) | |
continue; | |
if ( canmerge( leaves[i], leaves[j] ) ) | |
{ | |
merge( leaves[i], leaves[j] ); | |
done = false; | |
} | |
} | |
} | |
} | |
} | |
{ | |
std::vector< node* >::iterator b = leaves.begin(); | |
while ( b != leaves.end() ) | |
{ | |
if ( (*b)->group == -1 ) | |
{ | |
b = leaves.erase( b ); | |
} | |
else | |
{ | |
b++; | |
} | |
} | |
} | |
{ | |
std::vector< node* > external; | |
external.push_back( createbound( 256, 0, 0, 512, 256, 256 ) ); | |
external.push_back( createbound( 0, 256, 0, 256, 512, 256 ) ); | |
external.push_back( createbound( 0, 0, 256, 256, 256, 512 ) ); | |
external.push_back( createbound( -256, 0, 0, 0, 256, 256 ) ); | |
external.push_back( createbound( 0, -256, 0, 256, 0, 256 ) ); | |
external.push_back( createbound( 0, 0, -256, 256, 256, 0 ) ); | |
for (unsigned int i=0; i<leaves.size(); i++) | |
{ | |
cellbound cb; | |
cb.group = leaves[i]->group; | |
cb.bb[0][0] = leaves[i]->box[0][0]; | |
cb.bb[0][1] = leaves[i]->box[0][1]; | |
cb.bb[0][2] = leaves[i]->box[0][2]; | |
cb.bb[1][0] = leaves[i]->box[1][0]; | |
cb.bb[1][1] = leaves[i]->box[1][1]; | |
cb.bb[1][2] = leaves[i]->box[1][2]; | |
c.bounds.push_back( cb ); | |
for (unsigned int j=0; j<external.size(); j++) | |
{ | |
if ( !touching( leaves[i], external[j] ) ) | |
continue; | |
for (int face=0; face<6; face++) | |
{ | |
quad q = clipquad( generatequad( leaves[i], face ), external[j] ); | |
if ( isvalidquad( q ) ) | |
{ | |
portal p; | |
p.group = leaves[i]->group; | |
p.other_cell = face; | |
p.other_group = 255; | |
p.v[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) ); | |
p.v[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) ); | |
p.v[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) ); | |
p.v[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) ); | |
p.v[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) ); | |
p.v[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) ); | |
c.portals.push_back( p ); | |
} | |
} | |
} | |
} | |
} | |
if ( cellfilename ) | |
{ | |
writecell( cellfilename, c ); | |
} | |
delete n; | |
} | |
bool touching( portal const *a, portal const *b ) | |
{ | |
for (int axis=0; axis<3; axis++) | |
{ | |
if ( a->v[1][axis] < b->v[0][axis] ) | |
return false; | |
if ( a->v[0][axis] > b->v[1][axis] ) | |
return false; | |
} | |
return true; | |
} | |
quad generatequad( portal const *n, int face ) | |
{ | |
const static int faceids[6][4] = | |
{ | |
{ 0, 2, 6, 4 }, // ---, -+-, -++, --+ -x | |
{ 1, 0, 4, 5 }, // +--, ---, --+, +-+ -y | |
{ 0, 1, 3, 2 }, // ---, +--, ++-, -+- -z | |
{ 3, 1, 5, 7 }, // ++-, +--, +-+, +++ +x | |
{ 2, 3, 7, 6 }, // -+-, ++-, +++, -++ +y | |
{ 7, 6, 4, 5 }, // +++, -++, --+, +-+ +z | |
}; | |
quad q; | |
for (int i=0; i<4; i++) | |
{ | |
q.v[i][0] = faceids[face][i] & 1 ? n->v[1][0] : n->v[0][0]; | |
q.v[i][1] = faceids[face][i] & 2 ? n->v[1][1] : n->v[0][1]; | |
q.v[i][2] = faceids[face][i] & 4 ? n->v[1][2] : n->v[0][2]; | |
} | |
return q; | |
} | |
quad clipquad( quad q, portal const *n ) | |
{ | |
quad empty; | |
memset( &empty, 0, sizeof(empty) ); | |
int bb[2][4]; | |
bb[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) ); | |
bb[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) ); | |
bb[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) ); | |
bb[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) ); | |
bb[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) ); | |
bb[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) ); | |
for (int axis=0; axis<3; axis++) | |
{ | |
if ( bb[1][axis] < n->v[0][axis] ) | |
return empty; | |
if ( bb[0][axis] > n->v[1][axis] ) | |
return empty; | |
} | |
for (int i=0; i<4; i++) | |
{ | |
q.v[i][0] = max( n->v[0][0], min( n->v[1][0], q.v[i][0] ) ); | |
q.v[i][1] = max( n->v[0][1], min( n->v[1][1], q.v[i][1] ) ); | |
q.v[i][2] = max( n->v[0][2], min( n->v[1][2], q.v[i][2] ) ); | |
} | |
return q; | |
} | |
void intersect( cell &c, cell const *neighbours, int numn ) | |
{ | |
std::vector< portal > src; | |
std::swap( c.portals, src ); | |
for (unsigned int i=0; i<src.size(); i++) | |
{ | |
portal srcp = src[i]; | |
for (unsigned int ni=0; ni<numn; ni++) | |
{ | |
cell const &n = neighbours[ni]; | |
for (unsigned int j=0; j<n.portals.size(); j++) | |
{ | |
if ( !touching( &srcp, &n.portals[j] ) ) | |
continue; | |
{ | |
quad q = clipquad( generatequad( &srcp, srcp.other_cell ), &n.portals[j] ); | |
if ( isvalidquad( q ) ) | |
{ | |
portal p; | |
p.group = srcp.group; | |
p.other_cell = srcp.other_cell; | |
p.other_group = n.portals[j].group; | |
p.v[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) ); | |
p.v[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) ); | |
p.v[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) ); | |
p.v[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) ); | |
p.v[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) ); | |
p.v[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) ); | |
c.portals.push_back( p ); | |
} | |
} | |
} | |
} | |
} | |
} | |
#include <string> | |
#include <vector> | |
#include <io.h> | |
#include <algorithm> | |
char fixseparator( char c ) | |
{ | |
return ( c == '/' ) ? '\\' : c; | |
} | |
void findFiles( std::vector< std::string > &files, const char *pattern ) | |
{ | |
std::string path = pattern; | |
std::transform( path.begin(), path.end(), path.begin(), fixseparator ); | |
std::string::size_type pos = path.find_last_of( '\\' ); | |
if ( pos != std::string::npos ) | |
{ | |
path = path.substr( 0, pos ); | |
} | |
else | |
{ | |
path = "."; | |
} | |
_finddata_t fi; | |
intptr_t fh = _findfirst( pattern, &fi ); | |
if ( fh != -1 ) | |
{ | |
do | |
{ | |
files.push_back( path + "\\" + fi.name ); | |
} | |
while ( _findnext( fh, &fi ) == 0 ); | |
_findclose( fh ); | |
} | |
} | |
bool readhdr( float bb[2][3], const char *filename ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f ) | |
{ | |
bool failed = false; | |
failed |= (fscanf( f, "%f,%f,%f\n", &bb[0][0], &bb[0][1], &bb[0][2] ) != 3); | |
failed |= (fscanf( f, "%f,%f,%f\n", &bb[1][0], &bb[1][1], &bb[1][2] ) != 3); | |
fclose( f ); | |
return !failed; | |
} | |
return false; | |
} | |
bool readormakecell( cell &c, const char *filename, int x, int y, int z ) | |
{ | |
if ( readcell( c, filename, x, y, z ) ) | |
return true; | |
makecell( c, NULL, NULL ); | |
offsetcell( c, x, y, z ); | |
return false; | |
} | |
void clipcelltoportals( cell &c, int x, int y, int z ) | |
{ | |
char filename[256]; | |
sprintf( filename, "brick_%d_%d_%d.v.cell", x, y, z ); | |
if ( !readormakecell( c, filename, x*256, y*256, z*256 ) ) | |
return; | |
int ofs[][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 } }; | |
cell n[6]; | |
for (int i=0; i<6; i++) | |
{ | |
sprintf( filename, "brick_%d_%d_%d.v.cell", x+ofs[i][0], y+ofs[i][1], z+ofs[i][2] ); | |
readormakecell( n[i], filename, (x+ofs[i][0])*256, (y+ofs[i][1])*256, (z+ofs[i][2])*256 ); | |
} | |
intersect( c, n, 6 ); | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
#if 0 | |
std::vector< std::string > files; | |
findFiles( files, argv[1] ); | |
for (unsigned int i=0; i<files.size(); i++) | |
{ | |
printf( "cell '%s'\n", files[i].c_str() ); | |
makecell( (files[i]+".cell").c_str(), files[i].c_str() ); | |
} | |
#endif | |
#if 1 | |
float bb[2][3]; | |
if ( readhdr( bb, "voxel.hdr" ) ) | |
{ | |
int ibb[2][3]; | |
ibb[0][0] = 85-16;//(int)floorf( bb[0][0] ); | |
ibb[0][1] = -712-16;//(int)floorf( bb[0][1] ); | |
ibb[0][2] = 0-16;//(int)floorf( bb[0][2] ); | |
ibb[1][0] = ibb[0][0]+16;//(int)ceilf( bb[1][0] ); | |
ibb[1][1] = ibb[0][1]+16;//(int)ceilf( bb[1][1] ); | |
ibb[1][2] = ibb[0][2]+16;//(int)ceilf( bb[1][2] ); | |
ibb[0][0] = (int)floorf( bb[0][0] ); | |
ibb[0][1] = (int)floorf( bb[0][1] ); | |
ibb[0][2] = (int)floorf( bb[0][2] ); | |
ibb[1][0] = (int)ceilf( bb[1][0] ); | |
ibb[1][1] = (int)ceilf( bb[1][1] ); | |
ibb[1][2] = (int)ceilf( bb[1][2] ); | |
std::vector< cell > cells; | |
int w = (ibb[1][0]-ibb[0][0]); | |
int h = (ibb[1][1]-ibb[0][1]); | |
int d = (ibb[1][2]-ibb[0][2]); | |
cells.resize( w*h*d ); | |
for (int z=ibb[0][2]; z<ibb[1][2]; z++) | |
{ | |
printf("."); fflush(stdout); | |
int basez = z - ibb[0][2]; | |
for (int y=ibb[0][1]; y<ibb[1][1]; y++) | |
{ | |
int basey = y - ibb[0][1]; | |
for (int x=ibb[0][0]; x<ibb[1][0]; x++) | |
{ | |
int basex = x - ibb[0][0]; | |
clipcelltoportals( cells[basex+(basey*w)+(basez*(w*h))], x, y, z ); | |
} | |
} | |
} | |
writeobjofcell( "vis2.obj", &cells[0], cells.size() ); | |
} | |
#endif | |
#if 0 | |
makecell( "brick_25_-705_-7.cell", "brick_25_-705_-7.v" ); | |
makecell( "brick_26_-705_-7.cell", "brick_26_-705_-7.v" ); | |
makecell( "brick_25_-704_-7.cell", "brick_25_-704_-7.v" ); | |
makecell( "brick_25_-705_-6.cell", "brick_25_-705_-6.v" ); | |
makecell( "brick_24_-705_-7.cell", "brick_24_-705_-7.v" ); | |
makecell( "brick_25_-706_-7.cell", "brick_25_-706_-7.v" ); | |
makecell( "brick_25_-705_-8.cell", "brick_25_-705_-8.v" ); | |
cell c00; | |
readcell( c00, "brick_25_-705_-7.cell", 0, 0, 0 ); | |
cell n[6]; | |
readcell( n[0], "brick_26_-705_-7.cell", 256, 0, 0 ); | |
readcell( n[1], "brick_25_-704_-7.cell", 0, 256, 0 ); | |
readcell( n[2], "brick_25_-705_-6.cell", 0, 0, 256 ); | |
readcell( n[3], "brick_24_-705_-7.cell",-256, 0, 0 ); | |
readcell( n[4], "brick_25_-706_-7.cell", 0,-256, 0 ); | |
readcell( n[5], "brick_25_-705_-8.cell", 0, 0,-256 ); | |
intersect( c00, n, 6 ); | |
#endif | |
#if 0 | |
{ | |
FILE *f = fopen( "inter_portals.obj", "wb" ); | |
if ( f ) | |
{ | |
for (unsigned int i=0; i<leaves.size(); i++) | |
{ | |
for (unsigned int j=i+1; j<leaves.size(); j++) | |
{ | |
if ( !touching( leaves[i], leaves[j] ) ) | |
continue; | |
for (int face=0; face<6; face++) | |
{ | |
quad q = clipquad( generatequad( leaves[i], face ), leaves[j] ); | |
if ( isvalidquad( q ) ) | |
{ | |
outputquad( f, q ); | |
} | |
} | |
} | |
} | |
} | |
} | |
{ | |
std::vector< node* > external; | |
external.push_back( createbound( 0, 0, 256, 256, 256, 512 ) ); | |
external.push_back( createbound( 256, 0, 0, 512, 256, 256 ) ); | |
external.push_back( createbound( 0, 256, 0, 256, 512, 256 ) ); | |
external.push_back( createbound( -256, 0, 0, 0, 256, 256 ) ); | |
external.push_back( createbound( 0, -256, 0, 256, 0, 256 ) ); | |
external.push_back( createbound( 0, 0, -256, 256, 256, 0 ) ); | |
FILE *f = fopen( "external_portals.obj", "wb" ); | |
if ( f ) | |
{ | |
for (unsigned int i=0; i<leaves.size(); i++) | |
{ | |
for (unsigned int j=0; j<external.size(); j++) | |
{ | |
if ( !touching( leaves[i], external[j] ) ) | |
continue; | |
for (int face=0; face<6; face++) | |
{ | |
quad q = clipquad( generatequad( leaves[i], face ), external[j] ); | |
if ( isvalidquad( q ) ) | |
{ | |
outputquad( f, q ); | |
} | |
} | |
} | |
} | |
} | |
} | |
if ( 0 ) | |
{ | |
FILE *f = fopen( "debug.obj", "wb" ); | |
if ( f ) | |
{ | |
outputleafboxes( f, n ); | |
fclose( f ); | |
} | |
} | |
#endif | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// compressiondxt.cpp : Defines the entry point for the console application. | |
// | |
#define STB_IMAGE_WRITE_IMPLEMENTATION | |
#include "stdafx.h" | |
#include "malloc.h" | |
#include "DDS.h" | |
#include "DDSTextureLoader.h" | |
#include "stb_image_write.h" | |
#include "crn_win32_timer.h" | |
#include <math.h> | |
#include <vector> | |
#include "miniz.h" | |
#define PARANOID 0 | |
#include <map> | |
#include <list> | |
int *k_means( float **data, float *weights, int n, int m, int k, float t, float **centroids) | |
{ | |
int iter = 50; | |
/* output cluster label for each data point */ | |
int *labels = (int*)calloc(n, sizeof(int)); | |
int h, i, j; /* loop counters, of course :) */ | |
float *counts = (float*)calloc(k, sizeof(float)); /* size of each cluster */ | |
float old_error, error = FLT_MAX; /* sum of squared euclidean distance */ | |
float **c = centroids ? centroids : (float**)calloc(k, sizeof(float*)); | |
float **c1 = (float**)calloc(k, sizeof(float*)); /* temp centroids */ | |
assert(data && k > 0 && k <= n && m > 0 && t >= 0); /* for debugging */ | |
/****** initialization */ | |
for (h = i = 0; i < k; h += n / k, i++) { | |
c1[i] = (float*)calloc(m, sizeof(float)); | |
if (!centroids) { | |
c[i] = (float*)calloc(m, sizeof(float)); | |
} | |
/* pick k points as initial centroids */ | |
for (j = m; j-- > 0; c[i][j] = data[h][j]); | |
} | |
/****** main loop */ | |
do { | |
/* save error from last step */ | |
old_error = error, error = 0; | |
/* clear old counts and temp centroids */ | |
for (i = 0; i < k; counts[i++] = 0) { | |
for (j = 0; j < m; c1[i][j++] = 0); | |
} | |
for (h = 0; h < n; h++) { | |
/* identify the closest cluster */ | |
float min_distance = FLT_MAX; | |
for (i = 0; i < k; i++) { | |
float distance = 0.f; | |
for (j = m; j-- > 0; distance += pow(data[h][j] - c[i][j], 2)); | |
if (distance < min_distance) { | |
labels[h] = i; | |
min_distance = distance; | |
} | |
} | |
float w = weights ? weights[h] : 1.f; | |
/* update size and temp centroid of the destination cluster */ | |
for (j = m; j-- > 0; c1[labels[h]][j] += data[h][j]*w); | |
counts[labels[h]]+=w; | |
/* update standard error */ | |
error += min_distance; | |
} | |
for (i = 0; i < k; i++) { /* update all centroids */ | |
for (j = 0; j < m; j++) { | |
c[i][j] = (counts[i]>0.f) ? c1[i][j] / counts[i] : c1[i][j]; | |
} | |
} | |
printf("err %f\n", fabs(error - old_error) ); | |
} while (--iter && fabs(error - old_error) > t); | |
/**** | |
** housekeeping */ | |
for (i = 0; i < k; i++) { | |
if (!centroids) { | |
free(c[i]); | |
} | |
free(c1[i]); | |
} | |
if (!centroids) { | |
free(c); | |
} | |
free(c1); | |
free(counts); | |
return labels; | |
} | |
struct rc_model | |
{ | |
unsigned int tot; | |
unsigned int *pmf; | |
unsigned int *cdf; | |
int numSym; | |
}; | |
static void rc_model_init (rc_model *acm, int nsym, int *ifreq, int adapt) | |
{ | |
int i; | |
if ( nsym == 0 ) | |
{ | |
memset( acm, 0, sizeof(rc_model) ); | |
return; | |
} | |
acm->numSym = nsym; | |
acm->pmf = (unsigned int *) (void *) calloc (nsym, sizeof (int)); | |
acm->cdf = (unsigned int *) (void *) calloc (nsym+1, sizeof (int)); | |
acm->tot = 0; | |
if (ifreq) { | |
acm->cdf[acm->numSym] = 0; | |
for (i=acm->numSym-1; i>=0; i--) { | |
acm->pmf[i] = ifreq[i]; | |
acm->cdf[i] = acm->cdf[i+1] + acm->pmf[i]; | |
} | |
} else { | |
for (i=0; i<acm->numSym; i++) { | |
acm->pmf[i] = 1; | |
acm->cdf[i] = acm->numSym - i; | |
} | |
} | |
acm->tot = acm->cdf[0]; | |
} | |
static void rc_model_update(rc_model *acm, int sym) | |
{ | |
int i; | |
if (acm->tot==16383) { | |
acm->cdf[acm->numSym] = 0; | |
for (i = acm->numSym-1; i>=0; i--) { | |
acm->pmf[i] = (acm->pmf[i] + 1) / 2; | |
acm->cdf[i] = acm->cdf[i+1] + acm->pmf[i]; | |
} | |
acm->tot = acm->cdf[0]; | |
return; | |
} else | |
{ | |
acm->pmf[sym]++; | |
for (i=sym; i>=0; i--) { | |
acm->cdf[i]++; | |
} | |
acm->tot = acm->cdf[0]; | |
} | |
} | |
static void rc_model_done (rc_model *acm) | |
{ | |
free (acm->pmf); | |
acm->pmf = NULL; | |
free (acm->cdf); | |
acm->cdf = NULL; | |
} | |
struct rc_context | |
{ | |
FILE *f; | |
unsigned char *readbuffer; | |
unsigned int bufferSize; | |
unsigned int range; | |
unsigned int low; | |
unsigned int code; | |
unsigned int pos; | |
unsigned int total_bits; | |
}; | |
// output most significant byte | |
static void putbyte ( rc_context *ctx ) | |
{ | |
unsigned char c = ctx->low >> 24; | |
if ( ctx->f ) | |
{ | |
fwrite( &c, 1, 1, ctx->f ); | |
} | |
else | |
{ | |
if ( (ctx->total_bits/8) < ctx->bufferSize ) | |
{ | |
ctx->readbuffer[ctx->total_bits/8] = c; | |
} | |
} | |
ctx->low <<= 8; // shift out top 8 bits | |
ctx->total_bits += 8; | |
} | |
// normalize the range and output data | |
void rc_normalise_enc ( rc_context *ctx ) | |
{ | |
while ((( ctx->low ^ ( ctx->low + ctx->range )) >> 24) == 0) | |
{ | |
putbyte( ctx ); // top 8 bits of interval are fixed ;... | |
ctx->range <<= 8; // ... output them and normalize interval | |
} | |
if (( ctx->range >> 16) == 0) | |
{ | |
putbyte ( ctx ); // top 8 bits are not fixed but range ... | |
putbyte ( ctx ); // ... is small ; fudge range to avoid ... | |
ctx->range = (~ctx->low+1);//- ctx->low ; // ... carry and output top 16 bits | |
} | |
} | |
inline unsigned int firstHighBit( unsigned int v ) | |
{ | |
register unsigned int r; | |
register unsigned int shift; | |
r = (v > 0xFFFF) << 4; v >>= r; | |
shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; | |
shift = (v > 0xF ) << 2; v >>= shift; r |= shift; | |
shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; | |
r |= (v >> 1); | |
return r; | |
} | |
// normalize the range and output data | |
void rc_normalise_dec ( rc_context *ctx ) | |
{ | |
unsigned int bitTest = ctx->low ^ ( ctx->low + ctx->range ); | |
unsigned int bitShift = 24 - ( firstHighBit( bitTest ) & (~0x7) ); | |
unsigned int rangeShift = 16 * ( ctx->range <= ( (unsigned int)0xffff >> bitShift ) ); | |
bitShift += rangeShift; | |
ctx->pos += bitShift >> 3; | |
ctx->low <<= bitShift; | |
ctx->range = rangeShift ? (~ctx->low+1) : (ctx->range<<bitShift); | |
ctx->code = (((unsigned int)ctx->readbuffer[ctx->pos+0])<<24) | | |
(((unsigned int)ctx->readbuffer[ctx->pos+1])<<16) | | |
(((unsigned int)ctx->readbuffer[ctx->pos+2])<<8) | | |
(((unsigned int)ctx->readbuffer[ctx->pos+3])<<0); | |
} | |
void rc_encoder_init( rc_context *rc, FILE *f ) | |
{ | |
rc->f = f; | |
rc->low = 0; | |
rc->code = 0; | |
rc->pos = 0; | |
rc->range = 0xffffffff; | |
rc->readbuffer = 0; | |
rc->bufferSize = 0; | |
rc->total_bits = 0; | |
} | |
void rc_encoder_init( rc_context *rc, unsigned char *buffer, int bufferSize ) | |
{ | |
rc->f = NULL; | |
rc->low = 0; | |
rc->code = 0; | |
rc->pos = 0; | |
rc->range = 0xffffffff; | |
rc->readbuffer = buffer; | |
rc->bufferSize = bufferSize; | |
rc->total_bits = 0; | |
} | |
void rc_encoder_done( rc_context *ctx ) | |
{ | |
for (int n=0; n<4; n++) | |
{ | |
putbyte( ctx ); | |
} | |
} | |
void rc_decoder_init( rc_context *rc, const unsigned char *data ) | |
{ | |
rc->f = NULL; | |
rc->readbuffer = (unsigned char*)data; | |
rc->low = 0; | |
rc->code = 0; | |
rc->pos = 0; | |
rc->range = 0xffffffff; | |
rc->total_bits = 0; | |
rc->code = (((unsigned int)rc->readbuffer[rc->pos+0])<<24) | | |
(((unsigned int)rc->readbuffer[rc->pos+1])<<16) | | |
(((unsigned int)rc->readbuffer[rc->pos+2])<<8) | | |
(((unsigned int)rc->readbuffer[rc->pos+3])<<0); | |
} | |
// encode a symbol s using probability modeling | |
void rc_encode_symbol ( rc_context *ctx, rc_model * m, unsigned s ) | |
{ | |
if ( m->numSym == 0 ) | |
return; | |
assert( s < m->numSym ); | |
unsigned int cdf = m->cdf[s] - m->pmf[s]; | |
ctx->range /= m-> tot ; // tot = sum of pmf | |
if ( ctx->range == 0 ) | |
printf(""); | |
ctx->low += ctx->range * cdf; // cdf = cum . distribution function P(x < s) | |
ctx->range *= m-> pmf [s ]; // pmf = probability mass function P(x = s) | |
if ( ctx->range == 0 ) | |
printf(""); | |
rc_model_update(m, s ); // update probabilities | |
rc_normalise_enc ( ctx ); // normalize interval | |
} | |
unsigned rc_decode_symbol ( rc_context *ctx, rc_model * m ) | |
{ | |
ctx->range /= m->tot; | |
//unsigned freq= ((*(unsigned int*)&ctx->readbuffer[ctx->pos])/*ctx->code*/-ctx->low) / (ctx->range); | |
unsigned int freq= (ctx->code-ctx->low) / (ctx->range); | |
assert( freq < m->tot ); | |
unsigned s; | |
if ( m->numSym < 8 ) | |
{ | |
for (s = 0; m->cdf[s+1]>freq; s++) ; | |
} else | |
{ | |
int mn = 0; | |
int mx = m->numSym; | |
while ( (mx-mn) > 8 ) | |
{ | |
int md = (mn+mx+1)/2; | |
if ( m->cdf[md+1] > freq ) | |
{ | |
mn = md; | |
} else | |
{ | |
mx = md; | |
} | |
} | |
for (s = mn; m->cdf[s+1]>freq; s++) ; | |
} | |
unsigned int cdf = m->cdf[s] - m->pmf[s]; | |
ctx->low += ctx->range * cdf; // cdf = cum . distribution function P(x < s) | |
ctx->range *= m->pmf[s]; // pmf = probability mass function P(x = s) | |
rc_model_update(m, s ); // update probabilities | |
rc_normalise_dec ( ctx ); // normalize interval | |
return s; | |
} | |
static unsigned int makeCtx( unsigned int a, unsigned int b, unsigned int c ) | |
{ | |
return (a<<16)|(b<<8)|c; | |
} | |
static int determineMatchSize( const unsigned char *buffer, int buffer_len, int a, int b ) | |
{ | |
int len = 0; | |
while ( len < 255 && (a+len)<buffer_len && (b+len)<buffer_len && buffer[a+len] == buffer[b+len] ) | |
{ | |
len++; | |
} | |
return len; | |
} | |
static bool findCode( int &code, int &ofs, const int distances[], int numDistances, int inputDist ) | |
{ | |
for (int i=0; i<numDistances; i++) | |
{ | |
if ( inputDist >= distances[i] && inputDist < distances[i+1] ) | |
{ | |
code = i; | |
ofs = inputDist - distances[code]; | |
return true; | |
} | |
} | |
code = numDistances-1; | |
ofs = inputDist - distances[code]; | |
return true; | |
} | |
int zz_compress( unsigned char *outbuffer, unsigned int *out_buffer_len, const unsigned char *buffer, int buffer_len, int numBits ) | |
{ | |
std::map< unsigned int, std::list<unsigned int> > match; | |
const int lengths[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 83, 99, 115, 131, 163, 195, 227, 258, 259 }; | |
const int numLengths = (sizeof(lengths) / sizeof(lengths[0]))-1; | |
const int distances[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769 }; | |
const int numDistances = (sizeof(distances) / sizeof(distances[0]))-1; | |
const int symbols = 1 << numBits; | |
const int eos = symbols+1; | |
const int matched = eos+1; | |
rc_context ctx; | |
rc_encoder_init( &ctx, outbuffer, *out_buffer_len ); | |
rc_model rc_m_symbol; | |
rc_model rc_m_distances; | |
rc_model rc_m_lengths[numLengths]; | |
rc_model rc_m_distancesExtra[numDistances]; | |
rc_model_init( &rc_m_symbol, symbols+1+numLengths, NULL, 1 ); | |
rc_model_init( &rc_m_distances, 30, NULL, 1 ); | |
for (int i=0; i<numLengths; i++) | |
{ | |
rc_model_init( &rc_m_lengths[i], lengths[i+1]-lengths[i], NULL, 1 ); | |
} | |
for (int i=0; i<numDistances; i++) | |
{ | |
rc_model_init( &rc_m_distancesExtra[i], distances[i+1]-distances[i], NULL, 1 ); | |
} | |
for (int i=0; i<buffer_len;) | |
{ | |
int matchLen = 0; | |
int matchLoc = -1; | |
if ( (i+3) < buffer_len ) | |
{ | |
std::map< unsigned int, std::list<unsigned int> >::iterator f = match.find( makeCtx(buffer[i+0], buffer[i+1], buffer[i+2]) ); | |
if ( f != match.end() ) | |
{ | |
std::list<unsigned int> &matches = f->second; | |
std::list<unsigned int>::iterator m = matches.begin(); | |
while ( m != matches.end() ) | |
{ | |
unsigned int distance = i - *m; | |
if ( distance < 32768 ) | |
{ | |
int ml = determineMatchSize( buffer, buffer_len, i, *m ); | |
if ( ml > matchLen ) | |
{ | |
matchLen = ml; | |
matchLoc = *m; | |
} | |
m++; | |
} | |
else | |
{ | |
m = matches.erase( m ); | |
} | |
} | |
} | |
} | |
int starti = i; | |
if ( matchLen < 3 ) | |
{ | |
rc_encode_symbol( &ctx, &rc_m_symbol, buffer[i] ); | |
i++; | |
} | |
else | |
{ | |
int distance = i - matchLoc; | |
int cl, ol; | |
findCode( cl, ol, lengths, numLengths, matchLen ); | |
rc_encode_symbol( &ctx, &rc_m_symbol, matched+cl ); | |
if ( rc_m_lengths[cl].numSym > 1 ) | |
rc_encode_symbol( &ctx, &rc_m_lengths[cl], ol ); | |
int cd, od; | |
findCode( cd, od, distances, numDistances, distance ); | |
rc_encode_symbol( &ctx, &rc_m_distances, cd ); | |
if ( rc_m_distancesExtra[cd].numSym > 1 ) | |
rc_encode_symbol( &ctx, &rc_m_distancesExtra[cd], od ); | |
i+=matchLen; | |
} | |
unsigned int lastCtx = -1; | |
while ( starti < i ) | |
{ | |
int ctxLoc = starti-2; | |
if ( ctxLoc >= 0 ) | |
{ | |
unsigned int newCtx = makeCtx(buffer[ctxLoc+0], buffer[ctxLoc+1], buffer[ctxLoc+2]); | |
if ( newCtx != lastCtx ) | |
{ | |
match[newCtx].push_back( ctxLoc ); | |
lastCtx = newCtx; | |
} | |
} | |
starti++; | |
} | |
} | |
rc_encode_symbol( &ctx, &rc_m_symbol, eos ); | |
rc_encoder_done( &ctx ); | |
rc_model_done( &rc_m_symbol ); | |
rc_model_done( &rc_m_distances ); | |
for (int i=0; i<numLengths; i++) | |
{ | |
rc_model_done( &rc_m_lengths[i] ); | |
} | |
for (int i=0; i<numDistances; i++) | |
{ | |
rc_model_done( &rc_m_distancesExtra[i] ); | |
} | |
if ( (*out_buffer_len) > (ctx.total_bits / 8) ) | |
{ | |
*out_buffer_len = ctx.total_bits / 8; | |
return 0; | |
} | |
else | |
{ | |
return -5; | |
} | |
} | |
int zz_decompress( unsigned char *outbuffer, unsigned int *out_buffer_len, const unsigned char *buffer, int buffer_len, int numBits ) | |
{ | |
const int lengths[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 83, 99, 115, 131, 163, 195, 227, 258, 259 }; | |
const int numLengths = (sizeof(lengths) / sizeof(lengths[0]))-1; | |
const int distances[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769 }; | |
const int numDistances = (sizeof(distances) / sizeof(distances[0]))-1; | |
const int symbols = 1 << numBits; | |
const int eos = symbols+1; | |
const int matched = eos+1; | |
rc_context ctx; | |
rc_decoder_init( &ctx, buffer ); | |
rc_model rc_m_symbol; | |
rc_model rc_m_distances; | |
rc_model rc_m_lengths[numLengths]; | |
rc_model rc_m_distancesExtra[numDistances]; | |
rc_model_init( &rc_m_symbol, symbols+1+numLengths, NULL, 1 ); | |
rc_model_init( &rc_m_distances, 30, NULL, 1 ); | |
for (int i=0; i<numLengths; i++) | |
{ | |
rc_model_init( &rc_m_lengths[i], lengths[i+1]-lengths[i], NULL, 1 ); | |
} | |
for (int i=0; i<numDistances; i++) | |
{ | |
rc_model_init( &rc_m_distancesExtra[i], distances[i+1]-distances[i], NULL, 1 ); | |
} | |
unsigned int writePos = 0; | |
while ( 1 ) | |
{ | |
int sym = rc_decode_symbol( &ctx, &rc_m_symbol ); | |
if ( sym == eos ) | |
break; | |
if ( sym < symbols ) | |
{ | |
outbuffer[writePos++] = sym; | |
} | |
else | |
{ | |
int cl = sym - matched; | |
int ol = 0; | |
if ( rc_m_lengths[cl].numSym > 1 ) | |
ol = rc_decode_symbol( &ctx, &rc_m_lengths[cl] ); | |
int cd = rc_decode_symbol( &ctx, &rc_m_distances ); | |
int od = 0; | |
if ( rc_m_distancesExtra[cd].numSym > 1 ) | |
od = rc_decode_symbol( &ctx, &rc_m_distancesExtra[cd] ); | |
int distance = distances[cd] + od; | |
int matchLen = lengths[cl] + ol; | |
int matchLoc = writePos - distance; | |
for (int i=0; i<matchLen; i++) | |
{ | |
if ( writePos < *out_buffer_len ) | |
outbuffer[writePos] = outbuffer[matchLoc]; | |
writePos++; | |
matchLoc++; | |
} | |
} | |
} | |
rc_model_done( &rc_m_symbol ); | |
rc_model_done( &rc_m_distances ); | |
for (int i=0; i<numLengths; i++) | |
{ | |
rc_model_done( &rc_m_lengths[i] ); | |
} | |
for (int i=0; i<numDistances; i++) | |
{ | |
rc_model_done( &rc_m_distancesExtra[i] ); | |
} | |
if ( (*out_buffer_len) <= writePos ) | |
{ | |
*out_buffer_len = writePos; | |
return 0; | |
} | |
else | |
{ | |
return -5; | |
} | |
} | |
static void *readFile( const char *filename, int &len ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f ) | |
{ | |
fseek( f, 0, SEEK_END ); | |
len = ftell( f ); | |
fseek( f, 0, SEEK_SET ); | |
void *m = malloc( len ); | |
fread( m, 1, len, f ); | |
fclose( f ); | |
return m; | |
} | |
return NULL; | |
} | |
struct dxtrgbblock | |
{ | |
unsigned char c0[2]; | |
unsigned char c1[2]; | |
unsigned char bits[4]; | |
}; | |
struct bc3block | |
{ | |
unsigned char a[2]; | |
unsigned char bits[6]; | |
}; | |
struct dxta5block | |
{ | |
unsigned char a0; | |
unsigned char a1; | |
unsigned char a[6]; | |
}; | |
struct dxt5block | |
{ | |
bc3block a; | |
dxtrgbblock rgb; | |
}; | |
void extractRGB565( unsigned char rgb[3], unsigned short colour ) | |
{ | |
rgb[0] = (colour >> ( 5 + 6 )) & ((1<<5)-1); | |
rgb[1] = (colour >> ( 5 )) & ((1<<6)-1); | |
rgb[2] = (colour >> ( 0 )) & ((1<<5)-1); | |
rgb[0] = (rgb[0] << 3) | (rgb[0] >> (5-3)); | |
rgb[1] = (rgb[1] << 2) | (rgb[1] >> (6-2)); | |
rgb[2] = (rgb[2] << 3) | (rgb[2] >> (5-3)); | |
} | |
void generate4ColourSet( unsigned char rgb2[3], unsigned char rgb3[3], const unsigned char rgb0[3], const unsigned char rgb1[3] ) | |
{ | |
rgb2[0] = (2*(int)rgb0[0] + (int)rgb1[0])/3; | |
rgb2[1] = (2*(int)rgb0[1] + (int)rgb1[1])/3; | |
rgb2[2] = (2*(int)rgb0[2] + (int)rgb1[2])/3; | |
rgb3[0] = ((int)rgb0[0] + 2*(int)rgb1[0])/3; | |
rgb3[1] = ((int)rgb0[1] + 2*(int)rgb1[1])/3; | |
rgb3[2] = ((int)rgb0[2] + 2*(int)rgb1[2])/3; | |
} | |
void generate3ColourSet( unsigned char rgb2[3], unsigned char rgb3[3], const unsigned char rgb0[3], const unsigned char rgb1[3] ) | |
{ | |
rgb2[0] = ((int)rgb0[0] + (int)rgb1[0])/2; | |
rgb2[1] = ((int)rgb0[1] + (int)rgb1[1])/2; | |
rgb2[2] = ((int)rgb0[2] + (int)rgb1[2])/2; | |
rgb3[0] = 0; | |
rgb3[1] = 0; | |
rgb3[2] = 0; | |
} | |
int predictGreen( int up, int left, int diag, int &method ) | |
{ | |
int ma = abs(abs(diag-up) - abs(diag-left)); | |
int mb = abs(diag-up); | |
int mc = abs(diag-left); | |
if ( ma < 4 && mb < 4 ) | |
{ | |
method = 0; | |
return left+up-diag; | |
} else | |
if ( ma < 10 ) | |
{ | |
method = 1; | |
return (left+up)/2; | |
} else | |
if ( ma < 64 ) | |
{ | |
if ( mb < mc ) | |
{ | |
method = 2; | |
return (3*left+up)/4; | |
} else | |
{ | |
method = 3; | |
return (3*up+left)/4; | |
} | |
} else | |
{ | |
if ( mb < mc ) | |
{ | |
method = 4; | |
return left; | |
} else | |
{ | |
method = 5; | |
return up; | |
} | |
} | |
} | |
int findClosestG( unsigned char blockrgb[4][3], int g ) | |
{ | |
int best = 0; | |
int besterr = abs( blockrgb[best][1] - g ); | |
for (int i=1; i<4; i++) | |
{ | |
int err = abs( blockrgb[i][1] - g ); | |
if ( err < besterr ) | |
{ | |
besterr = err; | |
best = i; | |
} | |
} | |
return best; | |
} | |
inline int sqr( int v ) | |
{ | |
return v*v; | |
} | |
int findClosestRGB( unsigned char blockrgb[4][3], int r, int g, int b ) | |
{ | |
int best = 0; | |
int besterr = sqr( blockrgb[best][0] - r ) + sqr( blockrgb[best][1] - g ) + sqr( blockrgb[best][2] - b ); | |
for (int i=1; i<4; i++) | |
{ | |
int err = sqr( blockrgb[i][0] - r ) + sqr( blockrgb[i][1] - g ) + sqr( blockrgb[i][2] - b );//abs( blockrgb[i][1] - g ); | |
if ( err < besterr ) | |
{ | |
besterr = err; | |
best = i; | |
} | |
} | |
return best; | |
} | |
int findClosestA( unsigned char blocka[8], int a ) | |
{ | |
int best = 0; | |
int besterr = abs(blocka[best] - a); | |
for (int i=1; i<8; i++) | |
{ | |
int err = abs(blocka[i] - a); | |
if ( err < besterr ) | |
{ | |
besterr = err; | |
best = i; | |
} | |
} | |
return best; | |
} | |
inline unsigned int ZigZag(int word) { | |
return (word >> 15) ^ (word << 1); | |
} | |
inline unsigned int UnZigZag(int word) { | |
return (word >> 1) ^ (-(word&1)); | |
} | |
int jpeglsPredictor( int up, int left, int diag, int &method ) | |
{ | |
int mxul = max(up,left); | |
int mnul = min(up,left); | |
if ( diag >= mxul ) | |
{ | |
method = 0; | |
return mnul; | |
} else | |
if ( diag <= mnul ) | |
{ | |
method = 1; | |
return mxul; | |
} | |
method = 2; | |
return up+left-diag; | |
} | |
int PaethPredictor(int up, int left, int diag, int &method ) | |
{ | |
int p = left + up - diag; | |
int pa = abs(p - left); | |
int pb = abs(p - up); | |
int pc = abs(p - diag); | |
// return nearest of left,b,c, | |
// breaking ties in order left,b,c. | |
if ( pa <= pb && pa <= pc ) | |
{ | |
method = 0; | |
return left; | |
} | |
if ( pb <= pc ) | |
{ | |
method = 1; | |
return up; | |
} | |
method = 2; | |
return diag; | |
} | |
int iFreq0[] = | |
{ 53, 1, 24, 8 }; | |
int iFreq1[] = | |
{ 2, 79, 10, 28 }; | |
int iFreq2[] = | |
{ 18, 5, 37, 19 }; | |
int iFreq3[] = | |
{ 6, 26, 31, 58 }; | |
int runLength( dxtrgbblock *blocks, int x, int w ) | |
{ | |
int count = 0; | |
for (int i=1; i<8 && (x+i)<w; i++) | |
{ | |
if ( memcmp( &blocks[x], &blocks[x+i], sizeof(dxtrgbblock) ) ) | |
{ | |
break; | |
} | |
count++; | |
} | |
return count; | |
} | |
int runLength( dxt5block *blocks, int x, int w ) | |
{ | |
int count = 0; | |
for (int i=1; i<8 && (x+i)<w; i++) | |
{ | |
if ( memcmp( &blocks[x], &blocks[x+i], sizeof(dxt5block) ) ) | |
{ | |
break; | |
} | |
count++; | |
} | |
return count; | |
} | |
int runLength( void *blocks, int blockSize, int x, int w ) | |
{ | |
int count = 0; | |
for (int i=1; i<8 && (x+i)<w; i++) | |
{ | |
if ( memcmp( &(((char*)blocks)[i*blockSize]), blocks, blockSize ) ) | |
{ | |
break; | |
} | |
count++; | |
} | |
return count; | |
} | |
static float IndexGradientOrder4[] = { 0.f, 3.f, 1.f, 2.f }; | |
static float IndexGradientOrder3[] = { 1.f, 3.f, 2.f, -10000.f }; | |
static int remap4[] = { 0, 2, 3, 1 }; | |
static int remap3[] = { 3, 0, 2, 1 }; | |
int roundf( float v ) | |
{ | |
return (int)floorf( v + 0.5f ); | |
} | |
inline int clamp( int v, int mn, int mx ) | |
{ | |
return (v<mn) ? mn : (v>mx) ? mx : v; | |
} | |
unsigned int mapSelector( float *v, int *remap ) | |
{ | |
unsigned int bits = 0; | |
int selectorIndex = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
int idx = remap[ clamp( roundf( v[selectorIndex++] ), (remap == remap3) ? 1 : 0, 3 ) ]; | |
bits |= idx << (2*(4*i+j)); | |
} | |
} | |
return bits; | |
} | |
void kmeanstest( const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
return; | |
int curw = desc.width; | |
int curh = desc.height; | |
int numSelectors = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
numSelectors += blockw * blockh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
float **selectors = (float**)malloc( numSelectors * sizeof( float* ) ); | |
float *weights = (float*)malloc( numSelectors * sizeof( float ) ); | |
float *selectorVectors = (float*)malloc( numSelectors * sizeof( float ) * 16 ); | |
int curSelector = 0; | |
curw = desc.width; | |
curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch); | |
for (int x=0; x<blockw; x++) | |
{ | |
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256; | |
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256; | |
unsigned int bits = blocks[x].bits[0] + 256 * ((int)blocks[x].bits[1] + 256 * ((int)blocks[x].bits[2] + 256 * (int)blocks[x].bits[3])); | |
unsigned char blockrgb[2][3]; | |
extractRGB565( blockrgb[0], colour0 ); | |
extractRGB565( blockrgb[1], colour1 ); | |
selectors[curSelector] = &selectorVectors[curSelector*16]; | |
weights[curSelector] = /*sqrtf*/( (((float)blockrgb[0][0]-(float)blockrgb[1][0]) * ((float)blockrgb[0][0]-(float)blockrgb[1][0])) + | |
(((float)blockrgb[0][1]-(float)blockrgb[1][1]) * ((float)blockrgb[0][1]-(float)blockrgb[1][1])) + | |
(((float)blockrgb[0][2]-(float)blockrgb[1][2]) * ((float)blockrgb[0][2]-(float)blockrgb[1][2])) ); | |
float *gradient; | |
if ( (colour0 > colour1) || !isdxt1 ) | |
{ | |
gradient = IndexGradientOrder4; | |
} else | |
{ | |
gradient = IndexGradientOrder3; | |
} | |
int selectorIndex = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
selectors[curSelector][selectorIndex] = gradient[ (bits >> (2*(4*i+j))) & 3 ]; | |
selectorIndex++; | |
} | |
} | |
curSelector++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
int k = 2048; | |
float **centroids = (float **)malloc( k * sizeof( float* ) ); | |
float *centroidVector = (float *)malloc( k * sizeof( float ) * 16 ); | |
for (int i=0; i<k; i++) | |
{ | |
centroids[i] = ¢roidVector[ i * 16 ]; | |
} | |
int *label = k_means( selectors, weights, numSelectors, 16, k, 0.01f, centroids ); | |
curSelector = 0; | |
curw = desc.width; | |
curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch); | |
for (int x=0; x<blockw; x++) | |
{ | |
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256; | |
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256; | |
unsigned int testbits = blocks[x].bits[0] + 256 * ((int)blocks[x].bits[1] + 256 * ((int)blocks[x].bits[2] + 256 * (int)blocks[x].bits[3])); | |
unsigned int bits = mapSelector( centroids[ label[curSelector] ], ( (colour0 > colour1) || !isdxt1 ) ? remap4 : remap3 ); | |
blocks[x].bits[0] = bits & 0xff; | |
blocks[x].bits[1] = (bits>>8) & 0xff; | |
blocks[x].bits[2] = (bits>>16) & 0xff; | |
blocks[x].bits[3] = (bits>>24) & 0xff; | |
curSelector++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
void compress_bc1_lcct( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
static unsigned char imgchunks[2][(4096/4) * (4096/4) * 3 ] = {0}; | |
static unsigned char decompressed[4096 * 4096 * 3] = {0}; | |
// static unsigned char imgindices[2048 * 2048 ] = {0}; | |
// static unsigned char predindices[2048 * 2048 ] = {0}; | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
rc_context rciindicesEnc; | |
rc_encoder_init( &rciindicesEnc, f ); | |
rc_model rciindicesModel[3*3*3][4]; | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_init( &rciindicesModel[i][0], 4, iFreq0, 1 ); | |
rc_model_init( &rciindicesModel[i][1], 4, iFreq1, 1 ); | |
rc_model_init( &rciindicesModel[i][2], 4, iFreq2, 1 ); | |
rc_model_init( &rciindicesModel[i][3], 4, iFreq3, 1 ); | |
} | |
rc_model rcrllModel; | |
rc_model_init( &rcrllModel, 8, NULL, 1 ); | |
rc_model rcTestModel; | |
rc_model_init( &rcTestModel, 256, NULL, 1 ); | |
rc_model rccolmodel[6][2][3]; | |
int initialfreq[256*2]; | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<3; c++) | |
{ | |
int bits = c == 1 ? 6 : 5; | |
for (int i = 0; i<((1<<bits)*2)+1; i++) | |
{ | |
initialfreq[i] = 1+((1<<bits)/(((i+1)/2)+1)); | |
} | |
rc_model_init( &rccolmodel[0][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[1][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[2][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[3][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[4][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[5][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
} | |
} | |
int rcencodeindexbits = 0; | |
int rcencodeimagebits[2] = { 0 }; | |
int uncindexbits = 0; | |
int uncimagebits[2] = { 0 }; | |
int counts[3] = { 0 }; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch); | |
for (int x=0; x<blockw; x++) | |
{ | |
int indices[4][4]; | |
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256; | |
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256; | |
unsigned int bits = blocks[x].bits[0] + 256 * ((int)blocks[x].bits[1] + 256 * ((int)blocks[x].bits[2] + 256 * (int)blocks[x].bits[3])); | |
unsigned char blockrgb[4][3]; | |
extractRGB565( blockrgb[0], colour0 ); | |
extractRGB565( blockrgb[1], colour1 ); | |
if ( (colour0 > colour1) || !isdxt1 ) | |
{ | |
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} else | |
{ | |
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
int index = (y * blockw + x)*3; | |
imgchunks[0][index+0] = blockrgb[0][0]; | |
imgchunks[0][index+1] = blockrgb[0][1]; | |
imgchunks[0][index+2] = blockrgb[0][2]; | |
imgchunks[1][index+0] = blockrgb[1][0]; | |
imgchunks[1][index+1] = blockrgb[1][1]; | |
imgchunks[1][index+2] = blockrgb[1][2]; | |
{ | |
int upy = (y-1); | |
int leftx = (x-1); | |
int upindex = (upy * blockw + x) * 3; | |
int leftindex = (y * blockw + leftx) * 3; | |
int diagindex = (upy * blockw + leftx) * 3; | |
int curindex = (y * blockw + x) * 3; | |
for (int r=0; r<2; r++) | |
{ | |
long rcstartbits = rciindicesEnc.total_bits; | |
int error = 0; | |
for (int c=0; c<3; c++) | |
{ | |
int up = upy >= 0 ? imgchunks[r][upindex+c] : 0; | |
int left = leftx >= 0 ? imgchunks[r][leftindex+c] : 0; | |
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex+c] : 0; | |
int actual = imgchunks[r][curindex+c]; | |
int bits = c == 1 ? 6 : 5; | |
up >>= (8-bits); | |
left >>= (8-bits); | |
diag >>= (8-bits); | |
actual >>= (8-bits); | |
int method; | |
int predict = jpeglsPredictor( up, left, diag, method ); | |
//int predict = predictGreen( up, left, diag, method ); | |
predict += error; | |
if ( predict < 0 ) | |
{ | |
predict = 0; | |
} | |
if ( predict >= (1<<bits) ) | |
{ | |
predict = (1<<bits)-1; | |
} | |
int diff = predict - actual; | |
int zzdiff = ZigZag( diff ); | |
error = -diff; | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[method][r][c], zzdiff); | |
uncimagebits[r] += 16; | |
} | |
long rcendbits = rciindicesEnc.total_bits; | |
rcencodeimagebits[r] += rcendbits - rcstartbits; | |
} | |
} | |
long rcstartbits = rciindicesEnc.total_bits; | |
#if 1 | |
int errorR = 0; | |
int errorG = 0; | |
int errorB = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[3] = { 0, 0, 0 }; | |
int upy = (y*4+i-1); | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)) * 3; | |
int leftindex = ((y*4+i) * (blockw*4) +leftx) * 3; | |
int diagindex = (upy * (blockw*4) + leftx) * 3; | |
int curindex = ((y*4+i) * (blockw*4) + (x*4+j)) * 3; | |
unsigned char* left = leftx >= 0 ? &decompressed[leftindex] : zeros; | |
unsigned char* up = upy >= 0 ? &decompressed[upindex] : left;//zeros; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? &decompressed[diagindex] : up;//zeros; | |
int actualIndex = indices[i][j]; | |
int methodr, methodg, methodb; | |
int pr = predictGreen( up[0], left[0], diag[0], methodr ); | |
int pg = predictGreen( up[1], left[1], diag[1], methodg ); | |
int pb = predictGreen( up[2], left[2], diag[2], methodb ); | |
int pindex = findClosestG( blockrgb, pg ); | |
int methodR, methodG, methodB ; | |
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR ); | |
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG ); | |
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB ); | |
predictR += errorR; | |
predictG += errorG; | |
predictB += errorB; | |
int pindex2 = findClosestRGB( blockrgb, pr, pg, pb ); | |
int pindex3 = findClosestRGB( blockrgb, predictR, predictG, predictB ); | |
int method = methodg; | |
method = ((methodR * 3 + methodG)*3 + methodB);// % 6; | |
assert( method < (3*3*3) ); | |
pindex = pindex3; | |
counts[0] += pindex == actualIndex; | |
counts[1] += pindex2 == actualIndex; | |
counts[2] += pindex3 == actualIndex; | |
float diffr = ((float)blockrgb[actualIndex][0] - (float)blockrgb[pindex][0]); | |
float diffg = ((float)blockrgb[actualIndex][1] - (float)blockrgb[pindex][1]); | |
float diffb = ((float)blockrgb[actualIndex][2] - (float)blockrgb[pindex][2]); | |
//errorR = diffr;//blockrgb[actualIndex][0] - predictR; | |
//errorG = diffg;//blockrgb[actualIndex][1] - predictG; | |
//errorB = diffb;//blockrgb[actualIndex][2] - predictB; | |
//if ( i || j ) | |
//{ | |
// errorR = blockrgb[actualIndex][0] - predictR; | |
// errorG = blockrgb[actualIndex][1] - predictG; | |
// errorB = blockrgb[actualIndex][2] - predictB; | |
//} | |
float dist = sqrtf( diffr * diffr + diffg * diffg + diffb * diffb ); | |
if ( (((int)dist)>>3) <= 0.f ) | |
{ | |
//actualIndex = pindex; | |
} | |
int diff = pindex - actualIndex; | |
int zzdiff = ZigZag( diff ); | |
int decindex = ((y*4+i) * (blockw*4) + (x*4+j)); | |
// predindices[decindex] = zzdiff * 16; | |
rc_encode_symbol (&rciindicesEnc, &rciindicesModel[method][pindex], actualIndex); | |
decompressed[curindex+0] = blockrgb[actualIndex][0]; | |
decompressed[curindex+1] = blockrgb[actualIndex][1]; | |
decompressed[curindex+2] = blockrgb[actualIndex][2]; | |
} | |
} | |
#else | |
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[0] ); | |
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[1] ); | |
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[2] ); | |
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[3] ); | |
#endif | |
uncindexbits += 2 * 16; | |
long rcendbits = rciindicesEnc.total_bits; | |
rcencodeindexbits += rcendbits - rcstartbits; | |
int rll = runLength( blocks, x, blockw ); | |
rc_encode_symbol (&rciindicesEnc, &rcrllModel, rll); | |
for (int r=0; r<rll; r++) | |
{ | |
memcpy( &imgchunks[0][index+(r+1)*3], &imgchunks[0][index+0], 3 ); | |
memcpy( &imgchunks[1][index+(r+1)*3], &imgchunks[1][index+0], 3 ); | |
for (int j=0; j<4; j++) | |
{ | |
int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4) * 3; | |
int curindex = ((y*4+j) * (blockw*4) + (x*4)) * 3; | |
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*3 ); | |
} | |
} | |
x += rll; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
rc_encoder_done (&rciindicesEnc); | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_done (&rciindicesModel[i][0]); | |
rc_model_done (&rciindicesModel[i][1]); | |
rc_model_done (&rciindicesModel[i][2]); | |
rc_model_done (&rciindicesModel[i][3]); | |
} | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<3; c++) | |
{ | |
rc_model_done( &rccolmodel[0][j][c] ); | |
rc_model_done( &rccolmodel[1][j][c] ); | |
rc_model_done( &rccolmodel[2][j][c] ); | |
rc_model_done( &rccolmodel[3][j][c] ); | |
rc_model_done( &rccolmodel[4][j][c] ); | |
rc_model_done( &rccolmodel[5][j][c] ); | |
} | |
} | |
//printf( "index %f k (%.2f%%) (%.2f%% of original)\n", rcencodeindexbits / (8.f*1024.f), (rcencodeindexbits*100.f)/(rcencodeindexbits), (rcencodeindexbits*100.f)/(uncindexbits) ); | |
printf( "index %f k (%.2f%%) (%.2f%% of original)\n", rcencodeindexbits / (8.f*1024.f), (rcencodeindexbits*100.f)/(rcencodeindexbits+rcencodeimagebits[0]+rcencodeimagebits[1]), (rcencodeindexbits*100.f)/(uncindexbits) ); | |
printf( "rgb0 %f k (%.2f%%) (%.2f%% of original)\n", rcencodeimagebits[0] / (8.f*1024.f), (rcencodeimagebits[0]*100.f)/(rcencodeindexbits+rcencodeimagebits[0]+rcencodeimagebits[1]), (rcencodeimagebits[0]*100.f)/(uncimagebits[0]) ); | |
printf( "rgb1 %f k (%.2f%%) (%.2f%% of original)\n", rcencodeimagebits[1] / (8.f*1024.f), (rcencodeimagebits[1]*100.f)/(rcencodeindexbits+rcencodeimagebits[0]+rcencodeimagebits[1]), (rcencodeimagebits[1]*100.f)/(uncimagebits[1]) ); | |
fclose( f ); | |
} | |
struct rgba | |
{ | |
union | |
{ | |
struct | |
{ | |
unsigned char r, g, b, a; | |
}; | |
unsigned char c[4]; | |
}; | |
}; | |
void extractBC1BlockData( unsigned char cols[4][3], int indices[4][4], dxtrgbblock const *block, bool isBC1 ) | |
{ | |
unsigned short colour0 = block->c0[0] + block->c0[1] * 256; | |
unsigned short colour1 = block->c1[0] + block->c1[1] * 256; | |
unsigned int bits = block->bits[0] + 256 * ((unsigned int)block->bits[1] + 256 * ((unsigned int)block->bits[2] + 256 * (unsigned int)block->bits[3])); | |
extractRGB565( cols[0], colour0 ); | |
extractRGB565( cols[1], colour1 ); | |
if ( (colour0 > colour1) || !isBC1 ) | |
{ | |
generate4ColourSet( cols[2], cols[3], cols[0], cols[1] ); | |
} else | |
{ | |
generate3ColourSet( cols[2], cols[3], cols[0], cols[1] ); | |
} | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
} | |
static void generate6AlphaSet( unsigned char *a, unsigned char alpha_0, unsigned char alpha_1 ) | |
{ | |
a[0] = alpha_0; | |
a[1] = alpha_1; | |
a[2] = (6*alpha_0)/7 + (1*alpha_1)/7; // bit code 010 | |
a[3] = (5*alpha_0)/7 + (2*alpha_1)/7; // bit code 011 | |
a[4] = (4*alpha_0)/7 + (3*alpha_1)/7; // bit code 100 | |
a[5] = (3*alpha_0)/7 + (4*alpha_1)/7; // bit code 101 | |
a[6] = (2*alpha_0)/7 + (5*alpha_1)/7; // bit code 110 | |
a[7] = (1*alpha_0)/7 + (6*alpha_1)/7; // bit code 111 | |
} | |
static void generate4AlphaSet( unsigned char *a, unsigned char alpha_0, unsigned char alpha_1 ) | |
{ | |
// 4 interpolated alpha values. | |
a[0] = alpha_0; | |
a[1] = alpha_1; | |
a[2] = (4*alpha_0)/5 + (1*alpha_1)/5; // bit code 010 | |
a[3] = (3*alpha_0)/5 + (2*alpha_1)/5; // bit code 011 | |
a[4] = (2*alpha_0)/5 + (3*alpha_1)/5; // bit code 100 | |
a[5] = (1*alpha_0)/5 + (4*alpha_1)/5; // bit code 101 | |
a[6] = 0; // bit code 110 | |
a[7] = 255; // bit code 111 | |
} | |
void extractBC3BlockData( unsigned char alpha[8], int indices[4][4], bc3block const *block ) | |
{ | |
unsigned __int64 bits; | |
if ( block == NULL ) | |
{ | |
generate4AlphaSet( alpha, 0, 5 ); | |
bits = 255 + 256 * ((unsigned __int64)255 + | |
256 * ((unsigned __int64)255 + | |
256 * ((unsigned __int64)255 + | |
256 * ((unsigned __int64)255 + | |
256 * ((unsigned __int64)255 | |
))))); | |
} | |
else | |
{ | |
if ( block->a[0] > block->a[1] ) | |
{ | |
generate6AlphaSet( alpha, block->a[0], block->a[1] ); | |
} | |
else | |
{ | |
generate4AlphaSet( alpha, block->a[0], block->a[1] ); | |
} | |
bits = block->bits[0] + 256 * ((unsigned __int64)block->bits[1] + | |
256 * ((unsigned __int64)block->bits[2] + | |
256 * ((unsigned __int64)block->bits[3] + | |
256 * ((unsigned __int64)block->bits[4] + | |
256 * ((unsigned __int64)block->bits[5] | |
))))); | |
} | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
} | |
inline int QuantizeGradient( int g ) | |
{ | |
const int T1 = 3; | |
const int T2 = 7; | |
const int T3 = 21; | |
const int NR = 0; | |
int Q; | |
if (g <= -T3) Q=-4; | |
else if (g <= -T2) Q=-3; | |
else if (g <= -T1) Q=-2; | |
else if (g < -NR) Q=-1; | |
else if (g <= NR) Q= 0; | |
else if (g < T1) Q= 1; | |
else if (g < T2) Q= 2; | |
else if (g < T3) Q= 3; | |
else Q= 4; | |
return Q; | |
} | |
int MergeContext( int &sign, int q1, int q2, int q3 ) | |
{ | |
if ( q1 < 0 | |
|| (q1 == 0 && q2 < 0) | |
|| (q1 == 0 && q2 == 0 && q3 < 0) ) { | |
q1=-q1; | |
q2=-q2; | |
q3=-q3; | |
sign=-1; // signifies -ve | |
} | |
else { | |
sign=1; // signifies +ve | |
} | |
int q; | |
if (q1 == 0) { | |
if (q2 == 0) { | |
q=360+q3; // fills 360..364 | |
} | |
else { // Q2 is 1 to 4 | |
q=324+(q2-1)*9+(q3+4); // fills 324..359 | |
} | |
} | |
else { // Q1 is 1 to 4 | |
q=(q1-1)*81+(q2+4)*9+(q3+4); // fills 0..323 | |
} | |
return q; | |
} | |
static int clockAdd( int a, int b, int numBits ) | |
{ | |
return (a+b) & ((1<<numBits)-1); | |
} | |
static int clockDiff( int a, int b, int numBits ) | |
{ | |
return ((a+(1<<numBits))-b) & ((1<<numBits)-1); | |
} | |
void compress_bc3_lcct( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
static rgba imgchunks[2][(4096/4) * 2 ] = {0}; | |
static rgba decompressed[4096 * 8] = {0}; | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
rc_context rciindicesEnc; | |
rc_encoder_init( &rciindicesEnc, f ); | |
rc_model rc_c_iindicesModel[3*3*3][4]; | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 ); | |
} | |
rc_model rc_a_iindicesModel[3][8]; | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 ); | |
} | |
rc_model rcrllModel; | |
rc_model_init( &rcrllModel, 8, NULL, 1 ); | |
rc_model rcTestModel; | |
rc_model_init( &rcTestModel, 256, NULL, 1 ); | |
rc_model rccolmodel[6][2][4]; | |
int initialfreq[256*2+1]; | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
int bits = predictionbits[c]; | |
for (int i=0; i<(1<<bits); i++) | |
{ | |
int mid = (1<<bits)/2; | |
int dist = i < mid ? i : ((1<<bits)-i-1); | |
initialfreq[i] = ((1<<bits)/(dist+1))+1; | |
} | |
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 ); | |
} | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
dxt5block *blocks = (dxt5block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch); | |
for (int x=0; x<blockw; x++) | |
{ | |
int indicesrgb[4][4]; | |
unsigned char blockrgb[4][3]; | |
extractBC1BlockData( blockrgb, indicesrgb, &blocks[x].rgb, false ); | |
int indicesa[4][4]; | |
unsigned char blocka[8]; | |
extractBC3BlockData( blocka, indicesa, &blocks[x].a ); | |
int index = ((y%2) * blockw + x); | |
imgchunks[0][index].r = blockrgb[0][0]; | |
imgchunks[0][index].g = blockrgb[0][1]; | |
imgchunks[0][index].b = blockrgb[0][2]; | |
imgchunks[0][index].a = blocka[0]; | |
imgchunks[1][index].r = blockrgb[1][0]; | |
imgchunks[1][index].g = blockrgb[1][1]; | |
imgchunks[1][index].b = blockrgb[1][2]; | |
imgchunks[1][index].a = blocka[1]; | |
// block end point encode | |
{ | |
int cury = (y) % 2; | |
int upy = (y-1) % 2; | |
int leftx = (x-1); | |
int upindex = (upy * blockw + x); | |
int leftindex = (cury * blockw + leftx); | |
int diagindex = (upy * blockw + leftx); | |
int curindex = (cury * blockw + x); | |
int error = 0; | |
for (int r=0; r<2; r++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0; | |
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0; | |
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0; | |
int actual = imgchunks[r][curindex].c[c]; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual); | |
#endif | |
int bits = predictionbits[c]; | |
up >>= (8-bits); | |
left >>= (8-bits); | |
diag >>= (8-bits); | |
actual >>= (8-bits); | |
int method; | |
int predict = jpeglsPredictor( up, left, diag, method ); | |
predict += error; | |
if ( predict < 0 ) | |
predict = 0; | |
if ( predict >= (1<<bits) ) | |
predict = (1<<bits)-1; | |
int diff = predict - actual; | |
int zzdiff = clockDiff( actual, predict , bits ); | |
int test = clockAdd( predict, zzdiff, bits ); | |
assert( test == actual ); | |
error = -diff; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predict); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual); | |
#endif | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[method][r][c], zzdiff); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], c); | |
#endif | |
} | |
} | |
unsigned short colour0 = ((unsigned short)(imgchunks[0][curindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[0][curindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[0][curindex].c[2]>>3)); | |
unsigned short colour1 = ((unsigned short)(imgchunks[1][curindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[1][curindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[1][curindex].c[2]>>3)); | |
assert( (colour0&0xff) == blocks[x].rgb.c0[0] ); | |
assert( ((colour0>>8)&0xff) == blocks[x].rgb.c0[1] ); | |
assert( (colour1&0xff) == blocks[x].rgb.c1[0] ); | |
assert( ((colour1>>8)&0xff) == blocks[x].rgb.c1[1] ); | |
} | |
if ( 1 ) | |
{ | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c0[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c0[1]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c1[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c1[1]); | |
#endif | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros; | |
int actualIndex = indicesrgb[i][j]; | |
int methodR, methodG, methodB ; | |
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR ); | |
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG ); | |
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB ); | |
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB ); | |
int method = ((methodR * 3 + methodG)*3 + methodB); | |
assert( method < (3*3*3) ); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], methodR); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predictR); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], pindex); | |
#endif | |
rc_encode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex], actualIndex); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], i); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], j); | |
#endif | |
decompressed[curindex].r = blockrgb[actualIndex][0]; | |
decompressed[curindex].g = blockrgb[actualIndex][1]; | |
decompressed[curindex].b = blockrgb[actualIndex][2]; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].r); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].g); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].b); | |
#endif | |
} | |
} | |
} | |
if ( 1 ) | |
{ | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up; | |
int actualIndex = indicesa[i][j]; | |
int method; | |
int predict = jpeglsPredictor( up[3], left[3], diag[3], method ); | |
int pindex = findClosestA( blocka, predict ); | |
rc_encode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex], actualIndex); | |
decompressed[curindex].a = blocka[actualIndex]; | |
} | |
} | |
} | |
if ( 1 ) | |
{ | |
int rll = runLength( blocks, x, blockw ); | |
rc_encode_symbol (&rciindicesEnc, &rcrllModel, rll); | |
for (int r=0; r<rll; r++) | |
{ | |
memcpy( &imgchunks[0][index+(r+1)], &imgchunks[0][index+0], 4 ); | |
memcpy( &imgchunks[1][index+(r+1)], &imgchunks[1][index+0], 4 ); | |
for (int j=0; j<4; j++) | |
{ | |
int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4); | |
int curindex = ((y*4+j) * (blockw*4) + (x*4)); | |
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 ); | |
} | |
} | |
x += rll; | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
rc_encoder_done (&rciindicesEnc); | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_done (&rc_c_iindicesModel[i][0]); | |
rc_model_done (&rc_c_iindicesModel[i][1]); | |
rc_model_done (&rc_c_iindicesModel[i][2]); | |
rc_model_done (&rc_c_iindicesModel[i][3]); | |
} | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_done (&rc_a_iindicesModel[i][0]); | |
rc_model_done (&rc_a_iindicesModel[i][1]); | |
rc_model_done (&rc_a_iindicesModel[i][2]); | |
rc_model_done (&rc_a_iindicesModel[i][3]); | |
rc_model_done (&rc_a_iindicesModel[i][4]); | |
rc_model_done (&rc_a_iindicesModel[i][5]); | |
rc_model_done (&rc_a_iindicesModel[i][6]); | |
rc_model_done (&rc_a_iindicesModel[i][7]); | |
} | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
rc_model_done( &rccolmodel[0][j][c] ); | |
rc_model_done( &rccolmodel[1][j][c] ); | |
rc_model_done( &rccolmodel[2][j][c] ); | |
rc_model_done( &rccolmodel[3][j][c] ); | |
rc_model_done( &rccolmodel[4][j][c] ); | |
rc_model_done( &rccolmodel[5][j][c] ); | |
} | |
} | |
fclose( f ); | |
} | |
void compress_bc1and3_lcct( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
rgba *imgchunks[2];//[(4096/4) * 2 ] = {0}; | |
rgba *decompressed;//[4096 * 8] = {0}; | |
imgchunks[0] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 ); | |
imgchunks[1] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 ); | |
decompressed = (rgba*)malloc( sizeof(rgba) * desc.width * 8 ); | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
rc_context rciindicesEnc; | |
rc_encoder_init( &rciindicesEnc, f ); | |
rc_model rc_c_iindicesModel[3*3*3][4]; | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 ); | |
} | |
rc_model rc_a_iindicesModel[3][8]; | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 ); | |
} | |
rc_model rcrllModel; | |
rc_model_init( &rcrllModel, 8, NULL, 1 ); | |
rc_model rcTestModel; | |
rc_model_init( &rcTestModel, 256, NULL, 1 ); | |
rc_model rccolmodel[6][2][4]; | |
int initialfreq[256*2+1]; | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
int bits = predictionbits[c]; | |
for (int i=0; i<(1<<bits); i++) | |
{ | |
int mid = (1<<bits)/2; | |
int dist = i < mid ? i : ((1<<bits)-i-1); | |
initialfreq[i] = ((1<<bits)/(dist+1))+1; | |
} | |
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 ); | |
} | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
if ( x == 342 ) | |
printf(""); | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
int indicesrgb[4][4]; | |
unsigned char blockrgb[4][3]; | |
extractBC1BlockData( blockrgb, indicesrgb, blockbc1, isdxt1 ); | |
int indicesa[4][4]; | |
unsigned char blocka[8]; | |
extractBC3BlockData( blocka, indicesa, blockbc3a ); | |
int curblocky = (y) % 2; | |
int curblockindex = (curblocky * blockw + x); | |
imgchunks[0][curblockindex].r = blockrgb[0][0]; | |
imgchunks[0][curblockindex].g = blockrgb[0][1]; | |
imgchunks[0][curblockindex].b = blockrgb[0][2]; | |
imgchunks[0][curblockindex].a = blocka[0]; | |
imgchunks[1][curblockindex].r = blockrgb[1][0]; | |
imgchunks[1][curblockindex].g = blockrgb[1][1]; | |
imgchunks[1][curblockindex].b = blockrgb[1][2]; | |
imgchunks[1][curblockindex].a = blocka[1]; | |
// block end point encode | |
{ | |
int numc = blockbc3a ? 4 : 3; | |
int upy = (y-1) % 2; | |
int leftx = (x-1); | |
int upindex = (upy * blockw + x); | |
int leftindex = (curblocky * blockw + leftx); | |
int diagindex = (upy * blockw + leftx); | |
int error = 0; | |
for (int r=0; r<2; r++) | |
{ | |
for (int c=0; c<numc; c++) | |
{ | |
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0; | |
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0; | |
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0; | |
int actual = imgchunks[r][curblockindex].c[c]; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual); | |
#endif | |
int bits = predictionbits[c]; | |
up >>= (8-bits); | |
left >>= (8-bits); | |
diag >>= (8-bits); | |
actual >>= (8-bits); | |
int method; | |
int predict = jpeglsPredictor( up, left, diag, method ); | |
predict += error; | |
if ( predict < 0 ) | |
predict = 0; | |
if ( predict >= (1<<bits) ) | |
predict = (1<<bits)-1; | |
int diff = predict - actual; | |
int zzdiff = clockDiff( actual, predict , bits ); | |
int test = clockAdd( predict, zzdiff, bits ); | |
assert( test == actual ); | |
error = -diff; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predict); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual); | |
#endif | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[method][r][c], zzdiff); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], c); | |
#endif | |
} | |
} | |
unsigned short colour0 = ((unsigned short)(imgchunks[0][curblockindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[0][curblockindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[0][curblockindex].c[2]>>3)); | |
unsigned short colour1 = ((unsigned short)(imgchunks[1][curblockindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[1][curblockindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[1][curblockindex].c[2]>>3)); | |
assert( (colour0&0xff) == blockbc1->c0[0] ); | |
assert( ((colour0>>8)&0xff) == blockbc1->c0[1] ); | |
assert( (colour1&0xff) == blockbc1->c1[0] ); | |
assert( ((colour1>>8)&0xff) == blockbc1->c1[1] ); | |
} | |
if ( 1 ) | |
{ | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c0[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c0[1]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c1[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c1[1]); | |
#endif | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros; | |
int actualIndex = indicesrgb[i][j]; | |
int methodR, methodG, methodB ; | |
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR ); | |
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG ); | |
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB ); | |
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB ); | |
int method = ((methodR * 3 + methodG)*3 + methodB); | |
assert( method < (3*3*3) ); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], methodR); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predictR); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], pindex); | |
#endif | |
rc_encode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex], actualIndex); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], i); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], j); | |
#endif | |
decompressed[curindex].r = blockrgb[actualIndex][0]; | |
decompressed[curindex].g = blockrgb[actualIndex][1]; | |
decompressed[curindex].b = blockrgb[actualIndex][2]; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].r); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].g); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].b); | |
#endif | |
} | |
} | |
} | |
if ( blockbc3a ) | |
{ | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc3a->a[0]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc3a->a[1]); | |
#endif | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up; | |
int actualIndex = indicesa[i][j]; | |
int method; | |
int predict = jpeglsPredictor( up[3], left[3], diag[3], method ); | |
int pindex = findClosestA( blocka, predict ); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up[3]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left[3]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag[3]); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], pindex); | |
#endif | |
rc_encode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex], actualIndex); | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], i); | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], j); | |
#endif | |
decompressed[curindex].a = blocka[actualIndex]; | |
#if PARANOID | |
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].a); | |
#endif | |
} | |
} | |
} | |
if ( 1 ) | |
{ | |
int rll = runLength( ((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)), blockSize, x, blockw ); | |
rc_encode_symbol (&rciindicesEnc, &rcrllModel, rll); | |
for (int r=0; r<rll; r++) | |
{ | |
memcpy( &imgchunks[0][curblockindex+(r+1)], &imgchunks[0][curblockindex+0], 4 ); | |
memcpy( &imgchunks[1][curblockindex+(r+1)], &imgchunks[1][curblockindex+0], 4 ); | |
for (int j=0; j<4; j++) | |
{ | |
int dstindex = (((y*4+j)%8) * (blockw*4) + (x+r+1)*4); | |
int curindex = (((y*4+j)%8) * (blockw*4) + (x*4)); | |
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 ); | |
} | |
} | |
x += rll; | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
rc_encoder_done (&rciindicesEnc); | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_done (&rc_c_iindicesModel[i][0]); | |
rc_model_done (&rc_c_iindicesModel[i][1]); | |
rc_model_done (&rc_c_iindicesModel[i][2]); | |
rc_model_done (&rc_c_iindicesModel[i][3]); | |
} | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_done (&rc_a_iindicesModel[i][0]); | |
rc_model_done (&rc_a_iindicesModel[i][1]); | |
rc_model_done (&rc_a_iindicesModel[i][2]); | |
rc_model_done (&rc_a_iindicesModel[i][3]); | |
rc_model_done (&rc_a_iindicesModel[i][4]); | |
rc_model_done (&rc_a_iindicesModel[i][5]); | |
rc_model_done (&rc_a_iindicesModel[i][6]); | |
rc_model_done (&rc_a_iindicesModel[i][7]); | |
} | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
rc_model_done( &rccolmodel[0][j][c] ); | |
rc_model_done( &rccolmodel[1][j][c] ); | |
rc_model_done( &rccolmodel[2][j][c] ); | |
rc_model_done( &rccolmodel[3][j][c] ); | |
rc_model_done( &rccolmodel[4][j][c] ); | |
rc_model_done( &rccolmodel[5][j][c] ); | |
} | |
} | |
free( imgchunks[0] ); | |
free( imgchunks[1] ); | |
free( decompressed ); | |
fclose( f ); | |
} | |
void deltaEncode( unsigned char *stream, int num, int bits ) | |
{ | |
int last = 0; | |
for (int i=0; i<num; i++) | |
{ | |
int diff = clockDiff( stream[i], last, bits ); | |
last = stream[i]; | |
stream[i] = diff; | |
} | |
} | |
void deltaDecode( unsigned char *stream, int num, int bits ) | |
{ | |
int last = 0; | |
for (int i=0; i<num; i++) | |
{ | |
int value = clockAdd( last, stream[i], bits ); | |
stream[i] = value; | |
last = value; | |
} | |
} | |
int fwrite_compressed( const void *data, int len, FILE *f ) | |
{ | |
mz_ulong compressedSize = mz_deflateBound( NULL, len ); | |
unsigned char *comp = (unsigned char*)malloc(compressedSize); | |
int res = mz_compress2( comp, &compressedSize, (const unsigned char*)data, len, MZ_UBER_COMPRESSION ); | |
if ( res != 0 ) | |
{ | |
printf( "failed compress %d\n", res ); | |
} | |
fwrite( comp, compressedSize, 1, f ); | |
free( comp ); | |
return compressedSize; | |
} | |
int fwrite_compressed_zz( const void *data, int len, FILE *f, int numBits=8 ) | |
{ | |
unsigned int compressedSize = mz_deflateBound( NULL, len ); | |
unsigned char *comp = (unsigned char*)malloc(compressedSize); | |
int res = zz_compress( comp, &compressedSize, (const unsigned char*)data, len, numBits ); | |
if ( res != 0 ) | |
{ | |
printf( "failed compress %d\n", res ); | |
} | |
fwrite( comp, compressedSize, 1, f ); | |
free( comp ); | |
return compressedSize; | |
} | |
void* decompress( int expected, const void *data, int len ) | |
{ | |
unsigned char *dst = (unsigned char*)malloc( expected ); | |
mz_ulong pDest_len = expected; | |
int res = mz_uncompress(dst, &pDest_len, (const unsigned char*)data, len); | |
if ( res != 0 ) | |
{ | |
printf( "failed decompress %d\n", res ); | |
} | |
assert( expected == pDest_len ); | |
return dst; | |
} | |
void* decompress_zz( int expected, const void *data, int len, int numBits=8 ) | |
{ | |
unsigned char *dst = (unsigned char*)malloc( expected ); | |
unsigned int pDest_len = expected; | |
int res = zz_decompress(dst, &pDest_len, (const unsigned char*)data, len, numBits ); | |
if ( res != 0 ) | |
{ | |
printf( "failed decompress %d\n", res ); | |
} | |
assert( expected == pDest_len ); | |
return dst; | |
} | |
void compress_bc1and3_i( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > ep_rgb[2]; | |
std::vector< unsigned char > ep_a[2]; | |
std::vector< unsigned char > indices_rgb; | |
std::vector< unsigned char > indices_a; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
ep_rgb[0].push_back( blockbc1->c0[0] ); | |
ep_rgb[0].push_back( blockbc1->c0[1] ); | |
ep_rgb[1].push_back( blockbc1->c1[0] ); | |
ep_rgb[1].push_back( blockbc1->c1[1] ); | |
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3])); | |
int indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) ); | |
} | |
if ( blockbc3a ) | |
{ | |
ep_a[0].push_back( blockbc3a->a[0] ); | |
ep_a[1].push_back( blockbc3a->a[1] ); | |
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] + | |
256 * ((unsigned __int64)blockbc3a->bits[2] + | |
256 * ((unsigned __int64)blockbc3a->bits[3] + | |
256 * ((unsigned __int64)blockbc3a->bits[4] + | |
256 * ((unsigned __int64)blockbc3a->bits[5] | |
))))); | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
unsigned __int64 out_bits = 0; | |
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9); | |
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21); | |
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33); | |
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45); | |
indices_a.push_back( (out_bits>>0) & 0xff ); | |
indices_a.push_back( (out_bits>>8) & 0xff ); | |
indices_a.push_back( (out_bits>>16) & 0xff ); | |
indices_a.push_back( (out_bits>>24) & 0xff ); | |
indices_a.push_back( (out_bits>>32) & 0xff ); | |
indices_a.push_back( (out_bits>>40) & 0xff ); | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
std::vector<unsigned char> all; | |
all.insert( all.end(), ep_rgb[0].begin(), ep_rgb[0].end() ); | |
all.insert( all.end(), ep_rgb[1].begin(), ep_rgb[1].end() ); | |
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() ); | |
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() ); | |
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() ); | |
all.insert( all.end(), indices_a.begin(), indices_a.end() ); | |
fwrite_compressed( &all[0], all.size(), f ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_i( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *ep_rgb[2]; | |
unsigned char *ep_a[2]; | |
unsigned char *indices_rgb; | |
unsigned char *indices_a; | |
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
ep_rgb[0] = &all[0]; | |
ep_rgb[1] = &ep_rgb[0][totalblocks*2]; | |
indices_rgb = &ep_rgb[1][totalblocks*2]; | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
ep_a[0] = &indices_rgb[totalblocks*4]; | |
ep_a[1] = &ep_a[0][totalblocks]; | |
indices_a = &ep_a[1][totalblocks]; | |
} | |
else | |
{ | |
ep_a[0] = 0; | |
ep_a[1] = 0; | |
indices_a = 0; | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockIndex = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
blockbc1->c0[0] = ep_rgb[0][blockIndex*2+0]; | |
blockbc1->c0[1] = ep_rgb[0][blockIndex*2+1]; | |
blockbc1->c1[0] = ep_rgb[1][blockIndex*2+0]; | |
blockbc1->c1[1] = ep_rgb[1][blockIndex*2+1]; | |
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3])); | |
static int remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
int indices[4][4]; | |
unsigned int out_bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*2)) & 3; | |
out_bits |= indices[i][j] << (2*(4*i+j)); | |
} | |
} | |
blockbc1->bits[0] = (out_bits>>0) & 0xff; | |
blockbc1->bits[1] = (out_bits>>8) & 0xff; | |
blockbc1->bits[2] = (out_bits>>16) & 0xff; | |
blockbc1->bits[3] = (out_bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
blockbc3a->a[0] = ep_a[0][blockIndex]; | |
blockbc3a->a[1] = ep_a[1][blockIndex]; | |
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+2] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+3] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+4] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+5] | |
))))); | |
static unsigned __int64 remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
unsigned __int64 out_bits = 0; | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*3)) & 7; | |
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j)); | |
} | |
} | |
blockbc3a->bits[0] = (out_bits>>0) & 0xff; | |
blockbc3a->bits[1] = (out_bits>>8) & 0xff; | |
blockbc3a->bits[2] = (out_bits>>16) & 0xff; | |
blockbc3a->bits[3] = (out_bits>>24) & 0xff; | |
blockbc3a->bits[4] = (out_bits>>32) & 0xff; | |
blockbc3a->bits[5] = (out_bits>>40) & 0xff; | |
} | |
blockIndex++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
free( all ); | |
free( hdr ); | |
} | |
void compress_bc1and3_i2( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > ep_rgb[2][2]; | |
std::vector< unsigned char > ep_a[2]; | |
std::vector< unsigned char > indices_rgb; | |
std::vector< unsigned char > indices_a; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
ep_rgb[0][0].push_back( blockbc1->c0[0] ); | |
ep_rgb[0][1].push_back( blockbc1->c0[1] ); | |
ep_rgb[1][0].push_back( blockbc1->c1[0] ); | |
ep_rgb[1][1].push_back( blockbc1->c1[1] ); | |
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3])); | |
int indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) ); | |
} | |
if ( blockbc3a ) | |
{ | |
ep_a[0].push_back( blockbc3a->a[0] ); | |
ep_a[1].push_back( blockbc3a->a[1] ); | |
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] + | |
256 * ((unsigned __int64)blockbc3a->bits[2] + | |
256 * ((unsigned __int64)blockbc3a->bits[3] + | |
256 * ((unsigned __int64)blockbc3a->bits[4] + | |
256 * ((unsigned __int64)blockbc3a->bits[5] | |
))))); | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
unsigned __int64 out_bits = 0; | |
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9); | |
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21); | |
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33); | |
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45); | |
indices_a.push_back( (out_bits>>0) & 0xff ); | |
indices_a.push_back( (out_bits>>8) & 0xff ); | |
indices_a.push_back( (out_bits>>16) & 0xff ); | |
indices_a.push_back( (out_bits>>24) & 0xff ); | |
indices_a.push_back( (out_bits>>32) & 0xff ); | |
indices_a.push_back( (out_bits>>40) & 0xff ); | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
std::vector<unsigned char> all; | |
all.insert( all.end(), ep_rgb[0][0].begin(), ep_rgb[0][0].end() ); | |
all.insert( all.end(), ep_rgb[0][1].begin(), ep_rgb[0][1].end() ); | |
all.insert( all.end(), ep_rgb[1][0].begin(), ep_rgb[1][0].end() ); | |
all.insert( all.end(), ep_rgb[1][1].begin(), ep_rgb[1][1].end() ); | |
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() ); | |
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() ); | |
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() ); | |
all.insert( all.end(), indices_a.begin(), indices_a.end() ); | |
fwrite_compressed( &all[0], all.size(), f ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_i2( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *ep_rgb[2][2]; | |
unsigned char *ep_a[2]; | |
unsigned char *indices_rgb; | |
unsigned char *indices_a; | |
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
ep_rgb[0][0] = &all[0]; | |
ep_rgb[0][1] = &ep_rgb[0][0][totalblocks]; | |
ep_rgb[1][0] = &ep_rgb[0][1][totalblocks]; | |
ep_rgb[1][1] = &ep_rgb[1][0][totalblocks]; | |
indices_rgb = &ep_rgb[1][1][totalblocks]; | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
ep_a[0] = &indices_rgb[totalblocks*4]; | |
ep_a[1] = &ep_a[0][totalblocks]; | |
indices_a = &ep_a[1][totalblocks]; | |
} | |
else | |
{ | |
ep_a[0] = 0; | |
ep_a[1] = 0; | |
indices_a = 0; | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockIndex = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
blockbc1->c0[0] = ep_rgb[0][0][blockIndex]; | |
blockbc1->c0[1] = ep_rgb[0][1][blockIndex]; | |
blockbc1->c1[0] = ep_rgb[1][0][blockIndex]; | |
blockbc1->c1[1] = ep_rgb[1][1][blockIndex]; | |
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3])); | |
static int remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
int indices[4][4]; | |
unsigned int out_bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*2)) & 3; | |
out_bits |= indices[i][j] << (2*(4*i+j)); | |
} | |
} | |
blockbc1->bits[0] = (out_bits>>0) & 0xff; | |
blockbc1->bits[1] = (out_bits>>8) & 0xff; | |
blockbc1->bits[2] = (out_bits>>16) & 0xff; | |
blockbc1->bits[3] = (out_bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
blockbc3a->a[0] = ep_a[0][blockIndex]; | |
blockbc3a->a[1] = ep_a[1][blockIndex]; | |
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+2] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+3] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+4] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+5] | |
))))); | |
static unsigned __int64 remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
unsigned __int64 out_bits = 0; | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*3)) & 7; | |
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j)); | |
} | |
} | |
blockbc3a->bits[0] = (out_bits>>0) & 0xff; | |
blockbc3a->bits[1] = (out_bits>>8) & 0xff; | |
blockbc3a->bits[2] = (out_bits>>16) & 0xff; | |
blockbc3a->bits[3] = (out_bits>>24) & 0xff; | |
blockbc3a->bits[4] = (out_bits>>32) & 0xff; | |
blockbc3a->bits[5] = (out_bits>>40) & 0xff; | |
} | |
blockIndex++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
free( all ); | |
free( hdr ); | |
} | |
void compress_bc1and3_i3( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > ep_r[2],ep_b[2],ep_g[2]; | |
std::vector< unsigned char > ep_a[2]; | |
std::vector< unsigned char > indices_rgb; | |
std::vector< unsigned char > indices_a; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
unsigned short colour0 = blockbc1->c0[0] + blockbc1->c0[1] * 256; | |
unsigned short colour1 = blockbc1->c1[0] + blockbc1->c1[1] * 256; | |
unsigned char rgb[2][3]; | |
rgb[0][0] = (colour0 >> ( 5 + 6 )) & ((1<<5)-1); | |
rgb[0][1] = (colour0 >> ( 5 )) & ((1<<6)-1); | |
rgb[0][2] = (colour0 >> ( 0 )) & ((1<<5)-1); | |
rgb[1][0] = (colour1 >> ( 5 + 6 )) & ((1<<5)-1); | |
rgb[1][1] = (colour1 >> ( 5 )) & ((1<<6)-1); | |
rgb[1][2] = (colour1 >> ( 0 )) & ((1<<5)-1); | |
ep_r[0].push_back( rgb[0][0] ); | |
ep_g[0].push_back( rgb[0][1] ); | |
ep_b[0].push_back( rgb[0][2] ); | |
ep_r[1].push_back( rgb[1][0] ); | |
ep_g[1].push_back( rgb[1][1] ); | |
ep_b[1].push_back( rgb[1][2] ); | |
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3])); | |
int indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) ); | |
} | |
if ( blockbc3a ) | |
{ | |
ep_a[0].push_back( blockbc3a->a[0] ); | |
ep_a[1].push_back( blockbc3a->a[1] ); | |
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] + | |
256 * ((unsigned __int64)blockbc3a->bits[2] + | |
256 * ((unsigned __int64)blockbc3a->bits[3] + | |
256 * ((unsigned __int64)blockbc3a->bits[4] + | |
256 * ((unsigned __int64)blockbc3a->bits[5] | |
))))); | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
unsigned __int64 out_bits = 0; | |
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9); | |
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21); | |
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33); | |
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45); | |
indices_a.push_back( (out_bits>>0) & 0xff ); | |
indices_a.push_back( (out_bits>>8) & 0xff ); | |
indices_a.push_back( (out_bits>>16) & 0xff ); | |
indices_a.push_back( (out_bits>>24) & 0xff ); | |
indices_a.push_back( (out_bits>>32) & 0xff ); | |
indices_a.push_back( (out_bits>>40) & 0xff ); | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
std::vector< unsigned char > all5bit; | |
all5bit.insert( all5bit.end(), ep_r[0].begin(), ep_r[0].end() ); | |
all5bit.insert( all5bit.end(), ep_r[1].begin(), ep_r[1].end() ); | |
all5bit.insert( all5bit.end(), ep_b[0].begin(), ep_b[0].end() ); | |
all5bit.insert( all5bit.end(), ep_b[1].begin(), ep_b[1].end() ); | |
std::vector< unsigned char > all6bit; | |
all6bit.insert( all6bit.end(), ep_g[0].begin(), ep_g[0].end() ); | |
all6bit.insert( all6bit.end(), ep_g[1].begin(), ep_g[1].end() ); | |
std::vector< unsigned char > all8bit; | |
all8bit.insert( all8bit.end(), indices_rgb.begin(), indices_rgb.end() ); | |
all8bit.insert( all8bit.end(), ep_a[0].begin(), ep_a[0].end() ); | |
all8bit.insert( all8bit.end(), ep_a[1].begin(), ep_a[1].end() ); | |
all8bit.insert( all8bit.end(), indices_a.begin(), indices_a.end() ); | |
fwrite_compressed_zz( &all5bit[0], all5bit.size(), f, 5 ); | |
fwrite_compressed_zz( &all6bit[0], all6bit.size(), f, 6 ); | |
fwrite_compressed_zz( &all8bit[0], all8bit.size(), f, 8 ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_i3( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *ep_rgb[2]; | |
unsigned char *ep_a[2]; | |
unsigned char *indices_rgb; | |
unsigned char *indices_a; | |
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
ep_rgb[0] = &all[0]; | |
ep_rgb[1] = &ep_rgb[0][totalblocks*2]; | |
indices_rgb = &ep_rgb[1][totalblocks*2]; | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
ep_a[0] = &indices_rgb[totalblocks*4]; | |
ep_a[1] = &ep_a[0][totalblocks]; | |
indices_a = &ep_a[1][totalblocks]; | |
} | |
else | |
{ | |
ep_a[0] = 0; | |
ep_a[1] = 0; | |
indices_a = 0; | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockIndex = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
blockbc1->c0[0] = ep_rgb[0][blockIndex*2+0]; | |
blockbc1->c0[1] = ep_rgb[0][blockIndex*2+1]; | |
blockbc1->c1[0] = ep_rgb[1][blockIndex*2+0]; | |
blockbc1->c1[1] = ep_rgb[1][blockIndex*2+1]; | |
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3])); | |
static int remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
int indices[4][4]; | |
unsigned int out_bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*2)) & 3; | |
out_bits |= indices[i][j] << (2*(4*i+j)); | |
} | |
} | |
blockbc1->bits[0] = (out_bits>>0) & 0xff; | |
blockbc1->bits[1] = (out_bits>>8) & 0xff; | |
blockbc1->bits[2] = (out_bits>>16) & 0xff; | |
blockbc1->bits[3] = (out_bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
blockbc3a->a[0] = ep_a[0][blockIndex]; | |
blockbc3a->a[1] = ep_a[1][blockIndex]; | |
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+2] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+3] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+4] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+5] | |
))))); | |
static unsigned __int64 remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
unsigned __int64 out_bits = 0; | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*3)) & 7; | |
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j)); | |
} | |
} | |
blockbc3a->bits[0] = (out_bits>>0) & 0xff; | |
blockbc3a->bits[1] = (out_bits>>8) & 0xff; | |
blockbc3a->bits[2] = (out_bits>>16) & 0xff; | |
blockbc3a->bits[3] = (out_bits>>24) & 0xff; | |
blockbc3a->bits[4] = (out_bits>>32) & 0xff; | |
blockbc3a->bits[5] = (out_bits>>40) & 0xff; | |
} | |
blockIndex++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
free( all ); | |
free( hdr ); | |
} | |
void compress_bc1and3_id( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > ep_rgb[2]; | |
std::vector< unsigned char > ep_a[2]; | |
std::vector< unsigned char > indices_rgb; | |
std::vector< unsigned char > indices_a; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
ep_rgb[0].push_back( blockbc1->c0[0] ); | |
ep_rgb[0].push_back( blockbc1->c0[1] ); | |
ep_rgb[1].push_back( blockbc1->c1[0] ); | |
ep_rgb[1].push_back( blockbc1->c1[1] ); | |
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3])); | |
int indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) ); | |
} | |
if ( blockbc3a ) | |
{ | |
ep_a[0].push_back( blockbc3a->a[0] ); | |
ep_a[1].push_back( blockbc3a->a[1] ); | |
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] + | |
256 * ((unsigned __int64)blockbc3a->bits[2] + | |
256 * ((unsigned __int64)blockbc3a->bits[3] + | |
256 * ((unsigned __int64)blockbc3a->bits[4] + | |
256 * ((unsigned __int64)blockbc3a->bits[5] | |
))))); | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
unsigned __int64 out_bits = 0; | |
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9); | |
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21); | |
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33); | |
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45); | |
indices_a.push_back( (out_bits>>0) & 0xff ); | |
indices_a.push_back( (out_bits>>8) & 0xff ); | |
indices_a.push_back( (out_bits>>16) & 0xff ); | |
indices_a.push_back( (out_bits>>24) & 0xff ); | |
indices_a.push_back( (out_bits>>32) & 0xff ); | |
indices_a.push_back( (out_bits>>40) & 0xff ); | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
deltaEncode( &ep_rgb[0][0], ep_rgb[0].size(), 8 ); | |
deltaEncode( &ep_rgb[1][0], ep_rgb[1].size(), 8 ); | |
deltaEncode( &indices_rgb[0], indices_rgb.size(), 8 ); | |
if ( ep_a[0].size() ) | |
deltaEncode( &ep_a[0][0], ep_a[0].size(), 8 ); | |
if ( ep_a[1].size() ) | |
deltaEncode( &ep_a[1][0], ep_a[1].size(), 8 ); | |
if ( indices_a.size() ) | |
deltaEncode( &indices_a[0], indices_a.size(), 8 ); | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
std::vector<unsigned char> all; | |
all.insert( all.end(), ep_rgb[0].begin(), ep_rgb[0].end() ); | |
all.insert( all.end(), ep_rgb[1].begin(), ep_rgb[1].end() ); | |
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() ); | |
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() ); | |
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() ); | |
all.insert( all.end(), indices_a.begin(), indices_a.end() ); | |
fwrite_compressed( &all[0], all.size(), f ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_id( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *ep_rgb[2]; | |
unsigned char *ep_a[2]; | |
unsigned char *indices_rgb; | |
unsigned char *indices_a; | |
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
ep_rgb[0] = &all[0]; | |
ep_rgb[1] = &ep_rgb[0][totalblocks*2]; | |
indices_rgb = &ep_rgb[1][totalblocks*2]; | |
deltaDecode( &ep_rgb[0][0], totalblocks*2, 8 ); | |
deltaDecode( &ep_rgb[1][0], totalblocks*2, 8 ); | |
deltaDecode( &indices_rgb[0], totalblocks*4, 8 ); | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
ep_a[0] = &indices_rgb[totalblocks*4]; | |
ep_a[1] = &ep_a[0][totalblocks]; | |
indices_a = &ep_a[1][totalblocks]; | |
deltaDecode( &ep_a[0][0], totalblocks, 8 ); | |
deltaDecode( &ep_a[1][0], totalblocks, 8 ); | |
deltaDecode( &indices_a[0], totalblocks*6, 8 ); | |
} | |
else | |
{ | |
ep_a[0] = 0; | |
ep_a[1] = 0; | |
indices_a = 0; | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockIndex = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
blockbc1->c0[0] = ep_rgb[0][blockIndex*2+0]; | |
blockbc1->c0[1] = ep_rgb[0][blockIndex*2+1]; | |
blockbc1->c1[0] = ep_rgb[1][blockIndex*2+0]; | |
blockbc1->c1[1] = ep_rgb[1][blockIndex*2+1]; | |
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3])); | |
static int remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
int indices[4][4]; | |
unsigned int out_bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*2)) & 3; | |
out_bits |= indices[i][j] << (2*(4*i+j)); | |
} | |
} | |
blockbc1->bits[0] = (out_bits>>0) & 0xff; | |
blockbc1->bits[1] = (out_bits>>8) & 0xff; | |
blockbc1->bits[2] = (out_bits>>16) & 0xff; | |
blockbc1->bits[3] = (out_bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
blockbc3a->a[0] = ep_a[0][blockIndex]; | |
blockbc3a->a[1] = ep_a[1][blockIndex]; | |
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+2] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+3] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+4] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+5] | |
))))); | |
static unsigned __int64 remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
unsigned __int64 out_bits = 0; | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*3)) & 7; | |
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j)); | |
} | |
} | |
blockbc3a->bits[0] = (out_bits>>0) & 0xff; | |
blockbc3a->bits[1] = (out_bits>>8) & 0xff; | |
blockbc3a->bits[2] = (out_bits>>16) & 0xff; | |
blockbc3a->bits[3] = (out_bits>>24) & 0xff; | |
blockbc3a->bits[4] = (out_bits>>32) & 0xff; | |
blockbc3a->bits[5] = (out_bits>>40) & 0xff; | |
} | |
blockIndex++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
free( all ); | |
free( hdr ); | |
} | |
void compress_bc1and3_i2d( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > ep_rgb[2][2]; | |
std::vector< unsigned char > ep_a[2]; | |
std::vector< unsigned char > indices_rgb; | |
std::vector< unsigned char > indices_a; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
ep_rgb[0][0].push_back( blockbc1->c0[0] ); | |
ep_rgb[0][1].push_back( blockbc1->c0[1] ); | |
ep_rgb[1][0].push_back( blockbc1->c1[0] ); | |
ep_rgb[1][1].push_back( blockbc1->c1[1] ); | |
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3])); | |
int indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) ); | |
} | |
if ( blockbc3a ) | |
{ | |
ep_a[0].push_back( blockbc3a->a[0] ); | |
ep_a[1].push_back( blockbc3a->a[1] ); | |
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] + | |
256 * ((unsigned __int64)blockbc3a->bits[2] + | |
256 * ((unsigned __int64)blockbc3a->bits[3] + | |
256 * ((unsigned __int64)blockbc3a->bits[4] + | |
256 * ((unsigned __int64)blockbc3a->bits[5] | |
))))); | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
unsigned __int64 out_bits = 0; | |
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9); | |
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21); | |
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33); | |
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45); | |
indices_a.push_back( (out_bits>>0) & 0xff ); | |
indices_a.push_back( (out_bits>>8) & 0xff ); | |
indices_a.push_back( (out_bits>>16) & 0xff ); | |
indices_a.push_back( (out_bits>>24) & 0xff ); | |
indices_a.push_back( (out_bits>>32) & 0xff ); | |
indices_a.push_back( (out_bits>>40) & 0xff ); | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
deltaEncode( &ep_rgb[0][0][0], ep_rgb[0][0].size(), 8 ); | |
deltaEncode( &ep_rgb[0][1][0], ep_rgb[0][1].size(), 8 ); | |
deltaEncode( &ep_rgb[1][0][0], ep_rgb[1][0].size(), 8 ); | |
deltaEncode( &ep_rgb[1][1][0], ep_rgb[1][1].size(), 8 ); | |
deltaEncode( &indices_rgb[0], indices_rgb.size(), 8 ); | |
if ( ep_a[0].size() ) | |
deltaEncode( &ep_a[0][0], ep_a[0].size(), 8 ); | |
if ( ep_a[1].size() ) | |
deltaEncode( &ep_a[1][0], ep_a[1].size(), 8 ); | |
if ( indices_a.size() ) | |
deltaEncode( &indices_a[0], indices_a.size(), 8 ); | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
std::vector<unsigned char> all; | |
all.insert( all.end(), ep_rgb[0][0].begin(), ep_rgb[0][0].end() ); | |
all.insert( all.end(), ep_rgb[0][1].begin(), ep_rgb[0][1].end() ); | |
all.insert( all.end(), ep_rgb[1][0].begin(), ep_rgb[1][0].end() ); | |
all.insert( all.end(), ep_rgb[1][1].begin(), ep_rgb[1][1].end() ); | |
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() ); | |
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() ); | |
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() ); | |
all.insert( all.end(), indices_a.begin(), indices_a.end() ); | |
fwrite_compressed( &all[0], all.size(), f ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_i2d( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *ep_rgb[2][2]; | |
unsigned char *ep_a[2]; | |
unsigned char *indices_rgb; | |
unsigned char *indices_a; | |
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
ep_rgb[0][0] = &all[0]; | |
ep_rgb[0][1] = &ep_rgb[0][0][totalblocks]; | |
ep_rgb[1][0] = &ep_rgb[0][1][totalblocks]; | |
ep_rgb[1][1] = &ep_rgb[1][0][totalblocks]; | |
indices_rgb = &ep_rgb[1][1][totalblocks]; | |
deltaDecode( &ep_rgb[0][0][0], totalblocks, 8 ); | |
deltaDecode( &ep_rgb[0][1][0], totalblocks, 8 ); | |
deltaDecode( &ep_rgb[1][0][0], totalblocks, 8 ); | |
deltaDecode( &ep_rgb[1][1][0], totalblocks, 8 ); | |
deltaDecode( &indices_rgb[0], totalblocks*4, 8 ); | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
ep_a[0] = &indices_rgb[totalblocks*4]; | |
ep_a[1] = &ep_a[0][totalblocks]; | |
indices_a = &ep_a[1][totalblocks]; | |
deltaDecode( &ep_a[0][0], totalblocks, 8 ); | |
deltaDecode( &ep_a[1][0], totalblocks, 8 ); | |
deltaDecode( &indices_a[0], totalblocks*6, 8 ); | |
} | |
else | |
{ | |
ep_a[0] = 0; | |
ep_a[1] = 0; | |
indices_a = 0; | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockIndex = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
blockbc1->c0[0] = ep_rgb[0][0][blockIndex]; | |
blockbc1->c0[1] = ep_rgb[0][1][blockIndex]; | |
blockbc1->c1[0] = ep_rgb[1][0][blockIndex]; | |
blockbc1->c1[1] = ep_rgb[1][1][blockIndex]; | |
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3])); | |
static int remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
int indices[4][4]; | |
unsigned int out_bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*2)) & 3; | |
out_bits |= indices[i][j] << (2*(4*i+j)); | |
} | |
} | |
blockbc1->bits[0] = (out_bits>>0) & 0xff; | |
blockbc1->bits[1] = (out_bits>>8) & 0xff; | |
blockbc1->bits[2] = (out_bits>>16) & 0xff; | |
blockbc1->bits[3] = (out_bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
blockbc3a->a[0] = ep_a[0][blockIndex]; | |
blockbc3a->a[1] = ep_a[1][blockIndex]; | |
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+2] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+3] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+4] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+5] | |
))))); | |
static unsigned __int64 remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
unsigned __int64 out_bits = 0; | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*3)) & 7; | |
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j)); | |
} | |
} | |
blockbc3a->bits[0] = (out_bits>>0) & 0xff; | |
blockbc3a->bits[1] = (out_bits>>8) & 0xff; | |
blockbc3a->bits[2] = (out_bits>>16) & 0xff; | |
blockbc3a->bits[3] = (out_bits>>24) & 0xff; | |
blockbc3a->bits[4] = (out_bits>>32) & 0xff; | |
blockbc3a->bits[5] = (out_bits>>40) & 0xff; | |
} | |
blockIndex++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
free( all ); | |
free( hdr ); | |
} | |
void compress_bc1and3_z( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > data; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int pos = data.size(); | |
data.resize( pos + blockw*blockh*blockSize ); | |
memcpy( &data[pos], initData[ml].pSysMem, blockw*blockh*blockSize ); | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
fwrite_compressed( &data[0], data.size(), f ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_z( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
{ | |
int loc = 0; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
memcpy( (void*)initData[ml].pSysMem, &all[loc], (blockw * blockh) * blockSize ); | |
loc += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
free( hdr ); | |
free( all ); | |
} | |
void compress_bc1and3_zz( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > data; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int pos = data.size(); | |
data.resize( pos + blockw*blockh*blockSize ); | |
memcpy( &data[pos], initData[ml].pSysMem, blockw*blockh*blockSize ); | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
fwrite_compressed_zz( &data[0], data.size(), f ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_zz( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
int totalsize = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
totalsize += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *all = (unsigned char *)decompress_zz( totalsize, &hdr[1], len - sizeof(*hdr) ); | |
{ | |
int loc = 0; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
memcpy( (void*)initData[ml].pSysMem, &all[loc], (blockw * blockh) * blockSize ); | |
loc += (blockw * blockh) * blockSize; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
free( hdr ); | |
free( all ); | |
} | |
void rcEncode( rc_context *enc, rc_model *model, unsigned char *stream, int num ) | |
{ | |
for (int i=0; i<num; i++) | |
{ | |
rc_encode_symbol (enc, model, stream[i]); | |
} | |
} | |
void rcDecode( rc_context *enc, rc_model *model, unsigned char *stream, int num ) | |
{ | |
for (int i=0; i<num; i++) | |
{ | |
stream[i] = rc_decode_symbol (enc, model ); | |
} | |
} | |
#if 0 | |
void compress_bc1and3_i2( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
std::vector< unsigned char > ep_r[2]; | |
std::vector< unsigned char > ep_g[2]; | |
std::vector< unsigned char > ep_b[2]; | |
std::vector< unsigned char > ep_a[2]; | |
std::vector< unsigned char > indices_rgb; | |
std::vector< unsigned char > indices_a; | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
unsigned short colour0 = blockbc1->c0[0] + blockbc1->c0[1] * 256; | |
unsigned short colour1 = blockbc1->c1[0] + blockbc1->c1[1] * 256; | |
unsigned char r[2], g[2], b[2]; | |
r[0] = (colour0 >> ( 5 + 6 )) & ((1<<5)-1); | |
g[0] = (colour0 >> ( 5 )) & ((1<<6)-1); | |
b[0] = (colour0 >> ( 0 )) & ((1<<5)-1); | |
r[1] = (colour1 >> ( 5 + 6 )) & ((1<<5)-1); | |
g[1] = (colour1 >> ( 5 )) & ((1<<6)-1); | |
b[1] = (colour1 >> ( 0 )) & ((1<<5)-1); | |
ep_r[0].push_back( r[0] ); | |
ep_g[0].push_back( g[0] ); | |
ep_b[0].push_back( b[0] ); | |
ep_r[1].push_back( r[1] ); | |
ep_g[1].push_back( g[1] ); | |
ep_b[1].push_back( b[1] ); | |
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3])); | |
int indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (2*(4*i+j))) & 3; | |
} | |
} | |
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) ); | |
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) ); | |
} | |
if ( blockbc3a ) | |
{ | |
ep_a[0].push_back( blockbc3a->a[0] ); | |
ep_a[1].push_back( blockbc3a->a[1] ); | |
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] + | |
256 * ((unsigned __int64)blockbc3a->bits[2] + | |
256 * ((unsigned __int64)blockbc3a->bits[3] + | |
256 * ((unsigned __int64)blockbc3a->bits[4] + | |
256 * ((unsigned __int64)blockbc3a->bits[5] | |
))))); | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (3*(4*i+j))) & 7; | |
} | |
} | |
unsigned __int64 out_bits = 0; | |
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9); | |
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21); | |
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33); | |
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45); | |
indices_a.push_back( (out_bits>>0) & 0xff ); | |
indices_a.push_back( (out_bits>>8) & 0xff ); | |
indices_a.push_back( (out_bits>>16) & 0xff ); | |
indices_a.push_back( (out_bits>>24) & 0xff ); | |
indices_a.push_back( (out_bits>>32) & 0xff ); | |
indices_a.push_back( (out_bits>>40) & 0xff ); | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
deltaEncode( &ep_r[0][0], ep_r[0].size(), 5 ); | |
deltaEncode( &ep_r[1][0], ep_r[1].size(), 5 ); | |
deltaEncode( &ep_g[0][0], ep_g[0].size(), 6 ); | |
deltaEncode( &ep_g[1][0], ep_g[1].size(), 6 ); | |
deltaEncode( &ep_b[0][0], ep_b[0].size(), 5 ); | |
deltaEncode( &ep_b[1][0], ep_b[1].size(), 5 ); | |
if ( ep_a[0].size() ) | |
deltaEncode( &ep_a[0][0], ep_a[0].size(), 8 ); | |
if ( ep_a[1].size() ) | |
deltaEncode( &ep_a[1][0], ep_a[1].size(), 8 ); | |
FILE *f = fopen( filename, "wb" ); | |
fwrite( &desc, 1, sizeof(DDSLoadDesc), f ); | |
rc_context rcEnc; | |
rc_encoder_init( &rcEnc, f ); | |
rc_model rc_m_r, rc_m_g, rc_m_b, rc_m_a; | |
rc_model rc_m_indices_rgb, rc_m_indices_a; | |
rc_model_init( &rc_m_r, 1<<5, NULL, 1 ); | |
rc_model_init( &rc_m_g, 1<<6, NULL, 1 ); | |
rc_model_init( &rc_m_b, 1<<5, NULL, 1 ); | |
rc_model_init( &rc_m_a, 1<<8, NULL, 1 ); | |
rc_model_init( &rc_m_indices_rgb, 1<<8, NULL, 1 ); | |
rc_model_init( &rc_m_indices_a, 1<<8, NULL, 1 ); | |
if ( ep_r[0].size() ) | |
rcEncode( &rcEnc, &rc_m_r, &ep_r[0][0], ep_r[0].size() ); | |
if ( ep_r[1].size() ) | |
rcEncode( &rcEnc, &rc_m_r, &ep_r[1][0], ep_r[1].size() ); | |
if ( ep_g[0].size() ) | |
rcEncode( &rcEnc, &rc_m_g, &ep_g[0][0], ep_g[0].size() ); | |
if ( ep_g[1].size() ) | |
rcEncode( &rcEnc, &rc_m_g, &ep_g[1][0], ep_g[1].size() ); | |
if ( ep_b[0].size() ) | |
rcEncode( &rcEnc, &rc_m_b, &ep_b[0][0], ep_b[0].size() ); | |
if ( ep_b[1].size() ) | |
rcEncode( &rcEnc, &rc_m_b, &ep_b[1][0], ep_b[1].size() ); | |
if ( indices_rgb.size() ) | |
rcEncode( &rcEnc, &rc_m_indices_rgb, &indices_rgb[0], indices_rgb.size() ); | |
if ( ep_a[0].size() ) | |
rcEncode( &rcEnc, &rc_m_a, &ep_a[0][0], ep_a[0].size() ); | |
if ( ep_a[1].size() ) | |
rcEncode( &rcEnc, &rc_m_a, &ep_a[1][0], ep_a[1].size() ); | |
if ( indices_a.size() ) | |
rcEncode( &rcEnc, &rc_m_indices_a, &indices_a[0], indices_a.size() ); | |
rc_encoder_done (&rcEnc); | |
rc_model_done( &rc_m_r ); | |
rc_model_done( &rc_m_g ); | |
rc_model_done( &rc_m_b ); | |
rc_model_done( &rc_m_a ); | |
rc_model_done( &rc_m_indices_rgb ); | |
rc_model_done( &rc_m_indices_a ); | |
fclose( f ); | |
} | |
void decompress_bc1and3_i2( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
int totalblocks = 0; | |
{ | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
totalblocks += blockw * blockh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
unsigned char *ep_r[2]; | |
unsigned char *ep_g[2]; | |
unsigned char *ep_b[2]; | |
unsigned char *ep_a[2]; | |
unsigned char *indices_rgb; | |
unsigned char *indices_a; | |
ep_r[0] = (unsigned char*)&hdr[1]; | |
ep_r[1] = &ep_r[0][totalblocks]; | |
ep_g[0] = &ep_r[1][totalblocks]; | |
ep_g[1] = &ep_g[0][totalblocks]; | |
ep_b[0] = &ep_g[1][totalblocks]; | |
ep_b[1] = &ep_b[0][totalblocks]; | |
indices_rgb = &ep_b[1][totalblocks]; | |
deltaDecode( &ep_r[0][0], totalblocks, 5 ); | |
deltaDecode( &ep_r[1][0], totalblocks, 5 ); | |
deltaDecode( &ep_g[0][0], totalblocks, 6 ); | |
deltaDecode( &ep_g[1][0], totalblocks, 6 ); | |
deltaDecode( &ep_b[0][0], totalblocks, 5 ); | |
deltaDecode( &ep_b[1][0], totalblocks, 5 ); | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
ep_a[0] = &indices_rgb[totalblocks*4]; | |
ep_a[1] = &ep_a[0][totalblocks]; | |
deltaDecode( &ep_a[0][0], totalblocks, 8 ); | |
deltaDecode( &ep_a[1][0], totalblocks, 8 ); | |
indices_a = &ep_a[1][totalblocks]; | |
} | |
else | |
{ | |
ep_a[0] = 0; | |
ep_a[1] = 0; | |
indices_a = 0; | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockIndex = 0; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isdxt1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isdxt1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
if ( blockbc1 ) | |
{ | |
unsigned short colour0 = (ep_r[0][blockIndex]) << (5+6) | | |
(ep_g[0][blockIndex]) << (5) | | |
(ep_b[0][blockIndex]); | |
unsigned short colour1 = (ep_r[1][blockIndex]) << (5+6) | | |
(ep_g[1][blockIndex]) << (5) | | |
(ep_b[1][blockIndex]); | |
blockbc1->c0[0] = colour0 & 0xff; | |
blockbc1->c0[1] = colour0 / 256; | |
blockbc1->c1[0] = colour1 & 0xff; | |
blockbc1->c1[1] = colour1 / 256; | |
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3])); | |
static int remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
int indices[4][4]; | |
unsigned int out_bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*2)) & 3; | |
out_bits |= indices[i][j] << (2*(4*i+j)); | |
} | |
} | |
blockbc1->bits[0] = (out_bits>>0) & 0xff; | |
blockbc1->bits[1] = (out_bits>>8) & 0xff; | |
blockbc1->bits[2] = (out_bits>>16) & 0xff; | |
blockbc1->bits[3] = (out_bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
blockbc3a->a[0] = ep_a[0][blockIndex]; | |
blockbc3a->a[1] = ep_a[1][blockIndex]; | |
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+2] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+3] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+4] + | |
256 * ((unsigned __int64)indices_a[blockIndex*6+5] | |
))))); | |
static unsigned __int64 remap[4][4] = | |
{ | |
{ 0, 1, 4, 5 }, | |
{ 2, 3, 6, 7 }, | |
{ 8, 9, 12, 13 }, | |
{ 10, 11, 14, 15 }, | |
}; | |
unsigned __int64 out_bits = 0; | |
unsigned __int64 indices[4][4]; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
indices[i][j] = (bits >> (remap[i][j]*3)) & 7; | |
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j)); | |
} | |
} | |
blockbc3a->bits[0] = (out_bits>>0) & 0xff; | |
blockbc3a->bits[1] = (out_bits>>8) & 0xff; | |
blockbc3a->bits[2] = (out_bits>>16) & 0xff; | |
blockbc3a->bits[3] = (out_bits>>24) & 0xff; | |
blockbc3a->bits[4] = (out_bits>>32) & 0xff; | |
blockbc3a->bits[5] = (out_bits>>40) & 0xff; | |
} | |
blockIndex++; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
free( hdr ); | |
} | |
#endif | |
void decompress_bc1_lcct( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
unsigned char decompressed[ 4096 * 8 * 3 ]; | |
unsigned char imgchunks[2][(4096/4) * 2 * 3]; | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
assert( desc.width <= 4096 ); | |
rc_context rciindicesEnc; | |
rc_decoder_init( &rciindicesEnc, (unsigned char*)&hdr[1] ); | |
rc_model rciindicesModel[3*3*3][4]; | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_init( &rciindicesModel[i][0], 4, iFreq0, 1 ); | |
rc_model_init( &rciindicesModel[i][1], 4, iFreq1, 1 ); | |
rc_model_init( &rciindicesModel[i][2], 4, iFreq2, 1 ); | |
rc_model_init( &rciindicesModel[i][3], 4, iFreq3, 1 ); | |
} | |
rc_model rcrllModel; | |
rc_model_init( &rcrllModel, 8, NULL, 1 ); | |
rc_model rcTestModel; | |
rc_model_init( &rcTestModel, 256, NULL, 1 ); | |
rc_model rccolmodel[6][2][3]; | |
int initialfreq[256*2]; | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<3; c++) | |
{ | |
int bits = c == 1 ? 6 : 5; | |
for (int i = 0; i<((1<<bits)*2)+1; i++) | |
{ | |
initialfreq[i] = 1+((1<<bits)/(((i+1)/2)+1)); | |
} | |
rc_model_init( &rccolmodel[0][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[1][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[2][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[3][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[4][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
rc_model_init( &rccolmodel[5][j][c], ((1<<bits)*2)+1, initialfreq, 1 ); | |
} | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * sizeof(dxtrgbblock) ); | |
initData[ml].SysMemPitch = blockw * sizeof(dxtrgbblock); | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
crnlib::timer t; | |
t.start(); | |
curw = desc.width; | |
curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch); | |
for (int x=0; x<blockw; x++) | |
{ | |
{ | |
int upy = (y-1); | |
int leftx = (x-1); | |
int upindex = ((upy&1) * blockw + x) * 3; | |
int leftindex = ((y&1) * blockw + leftx) * 3; | |
int diagindex = ((upy&1) * blockw + leftx) * 3; | |
int curindex = ((y&1) * blockw + x) * 3; | |
for (int r=0; r<2; r++) | |
{ | |
int error = 0; | |
for (int c=0; c<3; c++) | |
{ | |
int up = (upy >= 0) ? imgchunks[r][upindex+c] : 0; | |
int left = (leftx >= 0) ? imgchunks[r][leftindex+c] : 0; | |
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex+c] : 0; | |
int bits = (c == 1) ? 6 : 5; | |
up >>= (8-bits); | |
left >>= (8-bits); | |
diag >>= (8-bits); | |
int method; | |
int predict = jpeglsPredictor( up, left, diag, method ); | |
predict += error; | |
if ( predict < 0 ) | |
{ | |
predict = 0; | |
} | |
if ( predict >= (1<<bits) ) | |
{ | |
predict = (1<<bits)-1; | |
} | |
int zzdiff = rc_decode_symbol (&rciindicesEnc, &rccolmodel[method][r][c]); | |
int diff = UnZigZag( zzdiff ); | |
int actual = predict - diff; | |
error = -diff; | |
actual = (actual << (8-bits)) | (actual >> (bits-(8-bits))); | |
imgchunks[r][curindex+c] = actual; | |
} | |
} | |
unsigned short colour0 = (imgchunks[0][curindex+0]>>3) << (5+6) | | |
(imgchunks[0][curindex+1]>>2) << (5) | | |
(imgchunks[0][curindex+2]>>3); | |
unsigned short colour1 = (imgchunks[1][curindex+0]>>3) << (5+6) | | |
(imgchunks[1][curindex+1]>>2) << (5) | | |
(imgchunks[1][curindex+2]>>3); | |
blocks[x].c0[0] = colour0 & 0xff; | |
blocks[x].c0[1] = colour0 / 256; | |
blocks[x].c1[0] = colour1 & 0xff; | |
blocks[x].c1[1] = colour1 / 256; | |
} | |
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256; | |
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256; | |
unsigned char blockrgb[4][3]; | |
extractRGB565( blockrgb[0], colour0 ); | |
extractRGB565( blockrgb[1], colour1 ); | |
if ( (colour0 > colour1) || !isdxt1 ) | |
{ | |
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} else | |
{ | |
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} | |
#if 1 | |
int errorR = 0; | |
int errorG = 0; | |
int errorB = 0; | |
int indices[4][4]; | |
unsigned int bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zero[] = { 0,0,0 }; | |
int upy = (y*4+i-1); | |
int leftx = (x*4+j-1); | |
int upindex = ((upy&7) * (blockw*4) + (x*4+j)) * 3; | |
int leftindex = (((y*4+i)&7) * (blockw*4) +leftx) * 3; | |
int diagindex = ((upy&7) * (blockw*4) + leftx) * 3; | |
int curindex = (((y*4+i)&7) * (blockw*4) + (x*4+j)) * 3; | |
unsigned char * left = leftx >= 0 ? &decompressed[leftindex] : zero; | |
unsigned char * up = upy >= 0 ? &decompressed[upindex] : left; | |
unsigned char * diag = (upy >= 0 && leftx >= 0) ? &decompressed[diagindex] : up; | |
int methodr, methodg, methodb; | |
int pr = predictGreen( up[0], left[0], diag[0], methodr ); | |
int pg = predictGreen( up[1], left[1], diag[1], methodg ); | |
int pb = predictGreen( up[2], left[2], diag[2], methodb ); | |
int pindex = findClosestG( blockrgb, pg ); | |
int methodR, methodG, methodB ; | |
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR ); | |
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG ); | |
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB ); | |
predictR += errorR; | |
predictG += errorG; | |
predictB += errorB; | |
int pindex2 = findClosestRGB( blockrgb, pr, pg, pb ); | |
int pindex3 = findClosestRGB( blockrgb, predictR, predictG, predictB ); | |
int method = methodg; | |
method = ((methodR*3 + methodG)*3 + methodB); | |
assert( method < (3*3*3) ); | |
pindex = pindex3; | |
/* | |
int method; | |
int pg = predictGreen( up[1], left[1], diag[1], method ); | |
int pindex = findClosestG( blockrgb, pg );*/ | |
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rciindicesModel[method][pindex]); | |
bits |= actualIndex << (2*(4*i+j)); | |
float diffr = ((float)blockrgb[actualIndex][0] - (float)blockrgb[pindex][0]); | |
float diffg = ((float)blockrgb[actualIndex][1] - (float)blockrgb[pindex][1]); | |
float diffb = ((float)blockrgb[actualIndex][2] - (float)blockrgb[pindex][2]); | |
//errorR = diffr;//blockrgb[actualIndex][0] - predictR; | |
//errorG = diffg;//blockrgb[actualIndex][1] - predictG; | |
//errorB = diffb;//blockrgb[actualIndex][2] - predictB; | |
//if ( i || j ) | |
//{ | |
// errorR = blockrgb[actualIndex][0] - predictR; | |
// errorG = blockrgb[actualIndex][1] - predictG; | |
// errorB = blockrgb[actualIndex][2] - predictB; | |
//} | |
indices[i][j] = actualIndex; | |
decompressed[curindex+0] = blockrgb[indices[i][j]][0]; | |
decompressed[curindex+1] = blockrgb[indices[i][j]][1]; | |
decompressed[curindex+2] = blockrgb[indices[i][j]][2]; | |
} | |
} | |
blocks[x].bits[0] = bits & 0xff; | |
blocks[x].bits[1] = (bits>>8) & 0xff; | |
blocks[x].bits[2] = (bits>>16) & 0xff; | |
blocks[x].bits[3] = (bits>>24) & 0xff; | |
#else | |
blocks[x].bits[0] = rc_decode_symbol( &rciindicesEnc, &rcTestModel ); | |
blocks[x].bits[1] = rc_decode_symbol( &rciindicesEnc, &rcTestModel ); | |
blocks[x].bits[2] = rc_decode_symbol( &rciindicesEnc, &rcTestModel ); | |
blocks[x].bits[3] = rc_decode_symbol( &rciindicesEnc, &rcTestModel ); | |
#endif | |
int rll = rc_decode_symbol( &rciindicesEnc, &rcrllModel ); | |
int index = ((y&1) * blockw + x)*3; | |
for (int r=0; r<rll; r++) | |
{ | |
memcpy( &blocks[x+r+1], &blocks[x], sizeof(dxtrgbblock) ); | |
memcpy( &imgchunks[0][index+(r+1)*3], &imgchunks[0][index+0], 3 ); | |
memcpy( &imgchunks[1][index+(r+1)*3], &imgchunks[1][index+0], 3 ); | |
for (int j=0; j<4; j++) | |
{ | |
int dstindex = (((y*4+j)&7) * (blockw*4) + (x+r+1)*4) * 3; | |
int curindex = (((y*4+j)&7) * (blockw*4) + (x*4)) * 3; | |
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*3 ); | |
} | |
} | |
x += rll; | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
t.stop(); | |
printf( "%d ms to decompress\n", t.get_elapsed_ms() ); | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_done (&rciindicesModel[i][0]); | |
rc_model_done (&rciindicesModel[i][1]); | |
rc_model_done (&rciindicesModel[i][2]); | |
rc_model_done (&rciindicesModel[i][3]); | |
} | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<3; c++) | |
{ | |
rc_model_done( &rccolmodel[0][j][c] ); | |
rc_model_done( &rccolmodel[1][j][c] ); | |
rc_model_done( &rccolmodel[2][j][c] ); | |
rc_model_done( &rccolmodel[3][j][c] ); | |
rc_model_done( &rccolmodel[4][j][c] ); | |
rc_model_done( &rccolmodel[5][j][c] ); | |
} | |
} | |
free( hdr ); | |
} | |
void decompress_bc3_lcct( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
static rgba imgchunks[2][(4096/4) * 2 ] = {0}; | |
static rgba decompressed[4096 * 8] = {0}; | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
rc_context rciindicesEnc; | |
rc_decoder_init( &rciindicesEnc, (unsigned char*)&hdr[1] ); | |
rc_model rc_c_iindicesModel[3*3*3][4]; | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 ); | |
} | |
rc_model rc_a_iindicesModel[3][8]; | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 ); | |
} | |
rc_model rcrllModel; | |
rc_model_init( &rcrllModel, 8, NULL, 1 ); | |
rc_model rccolmodel[6][2][4]; | |
int initialfreq[256*2+1]; | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
int bits = predictionbits[c]; | |
for (int i=0; i<(1<<bits); i++) | |
{ | |
int mid = (1<<bits)/2; | |
int dist = i < mid ? i : ((1<<bits)-i-1); | |
initialfreq[i] = ((1<<bits)/(dist+1))+1; | |
} | |
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 ); | |
} | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isdxt1 = true; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * sizeof(dxt5block) ); | |
initData[ml].SysMemPitch = blockw * sizeof(dxt5block); | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
curw = desc.width; | |
curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isbc1 = false; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
for (int y=0; y<blockh; y++) | |
{ | |
dxt5block *blocks = (dxt5block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch); | |
for (int x=0; x<blockw; x++) | |
{ | |
unsigned char blockrgb[4][3]; | |
unsigned char blocka[8]; | |
// block end point encode | |
{ | |
int cury = (y) % 2; | |
int upy = (y-1) % 2; | |
int leftx = (x-1); | |
int upindex = (upy * blockw + x); | |
int leftindex = (cury * blockw + leftx); | |
int diagindex = (upy * blockw + leftx); | |
int curindex = (cury * blockw + x); | |
int error = 0; | |
for (int r=0; r<2; r++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0; | |
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0; | |
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0; | |
int bits = predictionbits[c]; | |
up >>= (8-bits); | |
left >>= (8-bits); | |
diag >>= (8-bits); | |
int method; | |
int predict = jpeglsPredictor( up, left, diag, method ); | |
predict += error; | |
if ( predict < 0 ) | |
predict = 0; | |
if ( predict >= (1<<bits) ) | |
predict = (1<<bits)-1; | |
#if PARANOID | |
int testactualf = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testup = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testup == up ); | |
int testleft = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testleft == left ); | |
int testdiag = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testdiag == diag ); | |
int testmethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testmethod == method ); | |
int testpredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testpredict == predict ); | |
int testactual = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
#endif | |
int zzdiff = rc_decode_symbol (&rciindicesEnc, &rccolmodel[method][r][c]); | |
#if PARANOID | |
int test = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( test == c ); | |
#endif | |
int actual = clockAdd( predict, zzdiff, bits ); | |
#if PARANOID | |
assert( testactual == actual ); | |
#endif | |
int diff = predict - actual; | |
error = -diff; | |
actual = (actual << (8-bits)) | (actual >> (bits-(8-bits))); | |
#if PARANOID | |
assert( testactualf == actual ); | |
#endif | |
imgchunks[r][curindex].c[c] = actual; | |
} | |
} | |
unsigned short colour0 = ((unsigned short)(imgchunks[0][curindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[0][curindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[0][curindex].c[2]>>3)); | |
unsigned short colour1 = ((unsigned short)(imgchunks[1][curindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[1][curindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[1][curindex].c[2]>>3)); | |
blocks[x].rgb.c0[0] = colour0 & 0xff; | |
blocks[x].rgb.c0[1] = colour0 / 256; | |
blocks[x].rgb.c1[0] = colour1 & 0xff; | |
blocks[x].rgb.c1[1] = colour1 / 256; | |
blocks[x].a.a[0] = imgchunks[0][curindex].a; | |
blocks[x].a.a[1] = imgchunks[1][curindex].a; | |
extractRGB565( blockrgb[0], colour0 ); | |
extractRGB565( blockrgb[1], colour1 ); | |
if ( (colour0 > colour1) || !isbc1 ) | |
{ | |
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} else | |
{ | |
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} | |
blocka[0] = blocks[x].a.a[0]; | |
blocka[1] = blocks[x].a.a[1]; | |
if ( blocka[0] > blocka[1] ) | |
{ | |
generate6AlphaSet( blocka, blocka[0], blocka[1] ); | |
} | |
else | |
{ | |
generate4AlphaSet( blocka, blocka[0], blocka[1] ); | |
} | |
} | |
if ( 1 ) | |
{ | |
#if PARANOID | |
int testc00 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testc01 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testc10 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testc11 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testc00 == blocks[x].rgb.c0[0] ); | |
assert( testc01 == blocks[x].rgb.c0[1] ); | |
assert( testc10 == blocks[x].rgb.c1[0] ); | |
assert( testc11 == blocks[x].rgb.c1[1] ); | |
#endif | |
unsigned int bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros; | |
int methodR, methodG, methodB ; | |
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR ); | |
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG ); | |
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB ); | |
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB ); | |
int method = ((methodR * 3 + methodG)*3 + methodB); | |
assert( method < (3*3*3) ); | |
#if PARANOID | |
int testUpR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testUpR == up[0] ); | |
int testLeftR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testLeftR == left[0] ); | |
int testDiagR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testDiagR == diag[0] ); | |
int testMethodR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testMethodR == methodR ); | |
int testPredictR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testPredictR == predictR ); | |
int testMethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testMethod == method ); | |
int testPredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testPredict == pindex ); | |
#endif | |
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex] ); | |
#if PARANOID | |
int testi = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testi == i ); | |
int testj = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testj == j ); | |
int testr = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testg = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testb = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testr == blockrgb[actualIndex][0] ); | |
assert( testg == blockrgb[actualIndex][1] ); | |
assert( testb == blockrgb[actualIndex][2] ); | |
#endif | |
bits |= actualIndex << (2*(4*i+j)); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
decompressed[curindex].r = blockrgb[actualIndex][0]; | |
decompressed[curindex].g = blockrgb[actualIndex][1]; | |
decompressed[curindex].b = blockrgb[actualIndex][2]; | |
} | |
} | |
blocks[x].rgb.bits[0] = bits & 0xff; | |
blocks[x].rgb.bits[1] = (bits>>8) & 0xff; | |
blocks[x].rgb.bits[2] = (bits>>16) & 0xff; | |
blocks[x].rgb.bits[3] = (bits>>24) & 0xff; | |
} | |
if ( 1 ) | |
{ | |
unsigned __int64 bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up; | |
int method; | |
int predict = jpeglsPredictor( up[3], left[3], diag[3], method ); | |
int pindex = findClosestA( blocka, predict ); | |
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex] ); | |
bits |= (unsigned __int64)actualIndex << (3*(4*i+j)); | |
int curindex = ((y*4+i) * (blockw*4) + (x*4+j)); | |
decompressed[curindex].a = blocka[actualIndex]; | |
} | |
} | |
blocks[x].a.bits[0] = bits & 0xff; | |
blocks[x].a.bits[1] = (bits>>8) & 0xff; | |
blocks[x].a.bits[2] = (bits>>16) & 0xff; | |
blocks[x].a.bits[3] = (bits>>24) & 0xff; | |
blocks[x].a.bits[4] = (bits>>32) & 0xff; | |
blocks[x].a.bits[5] = (bits>>40) & 0xff; | |
} | |
if ( 1 ) | |
{ | |
int index = (y * blockw + x); | |
int rll = rc_decode_symbol (&rciindicesEnc, &rcrllModel); | |
for (int r=0; r<rll; r++) | |
{ | |
memcpy( &blocks[x+r+1], &blocks[x], sizeof(blocks[0]) ); | |
memcpy( &imgchunks[0][index+(r+1)], &imgchunks[0][index+0], 4 ); | |
memcpy( &imgchunks[1][index+(r+1)], &imgchunks[1][index+0], 4 ); | |
for (int j=0; j<4; j++) | |
{ | |
int dstindex = (((y*4+j)%8) * (blockw*4) + (x+r+1)*4); | |
int curindex = (((y*4+j)%8) * (blockw*4) + (x*4)); | |
// int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4); | |
// int curindex = ((y*4+j) * (blockw*4) + (x*4)); | |
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 ); | |
} | |
} | |
x += rll; | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_done (&rc_c_iindicesModel[i][0]); | |
rc_model_done (&rc_c_iindicesModel[i][1]); | |
rc_model_done (&rc_c_iindicesModel[i][2]); | |
rc_model_done (&rc_c_iindicesModel[i][3]); | |
} | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_done (&rc_a_iindicesModel[i][0]); | |
rc_model_done (&rc_a_iindicesModel[i][1]); | |
rc_model_done (&rc_a_iindicesModel[i][2]); | |
rc_model_done (&rc_a_iindicesModel[i][3]); | |
rc_model_done (&rc_a_iindicesModel[i][4]); | |
rc_model_done (&rc_a_iindicesModel[i][5]); | |
rc_model_done (&rc_a_iindicesModel[i][6]); | |
rc_model_done (&rc_a_iindicesModel[i][7]); | |
} | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
rc_model_done( &rccolmodel[0][j][c] ); | |
rc_model_done( &rccolmodel[1][j][c] ); | |
rc_model_done( &rccolmodel[2][j][c] ); | |
rc_model_done( &rccolmodel[3][j][c] ); | |
rc_model_done( &rccolmodel[4][j][c] ); | |
rc_model_done( &rccolmodel[5][j][c] ); | |
} | |
} | |
} | |
void decompress_bc1and3_lcct( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ) | |
{ | |
rgba *imgchunks[2];//[(4096/4) * 2 ] = {0}; | |
rgba *decompressed;//[4096 * 8] = {0}; | |
const int predictionbits[4] = { 5, 6, 5, 8 }; | |
int len; | |
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len ); | |
desc = *hdr; | |
imgchunks[0] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 ); | |
imgchunks[1] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 ); | |
decompressed = (rgba*)malloc( sizeof(rgba) * desc.width * 8 ); | |
rc_context rciindicesEnc; | |
rc_decoder_init( &rciindicesEnc, (unsigned char*)&hdr[1] ); | |
rc_model rc_c_iindicesModel[3*3*3][4]; | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 ); | |
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 ); | |
} | |
rc_model rc_a_iindicesModel[3][8]; | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 ); | |
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 ); | |
} | |
rc_model rcrllModel; | |
rc_model_init( &rcrllModel, 8, NULL, 1 ); | |
rc_model rccolmodel[6][2][4]; | |
int initialfreq[256*2+1]; | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
int bits = predictionbits[c]; | |
for (int i=0; i<(1<<bits); i++) | |
{ | |
int mid = (1<<bits)/2; | |
int dist = i < mid ? i : ((1<<bits)-i-1); | |
initialfreq[i] = ((1<<bits)/(dist+1))+1; | |
} | |
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 ); | |
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 ); | |
} | |
} | |
int curw = desc.width; | |
int curh = desc.height; | |
curw = desc.width; | |
curh = desc.height; | |
for (int ml=0; ml<desc.mips; ml++) | |
{ | |
bool isbc1 = (desc.format == DXGI_FORMAT_BC1_UNORM); | |
int blockSize = isbc1 ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
initData[ml].pSysMem = malloc( blockw * blockh * blockSize ); | |
initData[ml].SysMemPitch = blockw * blockSize; | |
for (int y=0; y<blockh; y++) | |
{ | |
for (int x=0; x<blockw; x++) | |
{ | |
if ( x == 342 ) | |
printf(""); | |
dxtrgbblock *blockbc1; | |
bc3block *blockbc3a; | |
if ( isbc1 ) | |
{ | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc3a = NULL; | |
} | |
else | |
{ | |
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8); | |
} | |
unsigned char blockrgb[4][3]; | |
unsigned char blocka[8]; | |
int curblocky = (y) % 2; | |
int curblockindex = (curblocky * blockw + x); | |
// block end point encode | |
{ | |
int numc = blockbc3a ? 4 : 3; | |
int upy = (y-1) % 2; | |
int leftx = (x-1); | |
int upindex = (upy * blockw + x); | |
int leftindex = (curblocky * blockw + leftx); | |
int diagindex = (upy * blockw + leftx); | |
int error = 0; | |
for (int r=0; r<2; r++) | |
{ | |
for (int c=0; c<numc; c++) | |
{ | |
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0; | |
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0; | |
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0; | |
int bits = predictionbits[c]; | |
up >>= (8-bits); | |
left >>= (8-bits); | |
diag >>= (8-bits); | |
int method; | |
int predict = jpeglsPredictor( up, left, diag, method ); | |
predict += error; | |
if ( predict < 0 ) | |
predict = 0; | |
if ( predict >= (1<<bits) ) | |
predict = (1<<bits)-1; | |
#if PARANOID | |
int testactualf = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testup = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testup == up ); | |
int testleft = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testleft == left ); | |
int testdiag = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testdiag == diag ); | |
int testmethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testmethod == method ); | |
int testpredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testpredict == predict ); | |
int testactual = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
#endif | |
int zzdiff = rc_decode_symbol (&rciindicesEnc, &rccolmodel[method][r][c]); | |
#if PARANOID | |
int test = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( test == c ); | |
#endif | |
int actual = clockAdd( predict, zzdiff, bits ); | |
#if PARANOID | |
assert( testactual == actual ); | |
#endif | |
int diff = predict - actual; | |
error = -diff; | |
actual = (actual << (8-bits)) | (actual >> (bits-(8-bits))); | |
#if PARANOID | |
assert( testactualf == actual ); | |
#endif | |
imgchunks[r][curblockindex].c[c] = actual; | |
} | |
} | |
} | |
if ( blockbc1 ) | |
{ | |
unsigned short colour0 = ((unsigned short)(imgchunks[0][curblockindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[0][curblockindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[0][curblockindex].c[2]>>3)); | |
unsigned short colour1 = ((unsigned short)(imgchunks[1][curblockindex].c[0]>>3) << (5+6)) | | |
((unsigned short)(imgchunks[1][curblockindex].c[1]>>2) << (5)) | | |
((unsigned short)(imgchunks[1][curblockindex].c[2]>>3)); | |
blockbc1->c0[0] = colour0 & 0xff; | |
blockbc1->c0[1] = colour0 / 256; | |
blockbc1->c1[0] = colour1 & 0xff; | |
blockbc1->c1[1] = colour1 / 256; | |
extractRGB565( blockrgb[0], colour0 ); | |
extractRGB565( blockrgb[1], colour1 ); | |
if ( (colour0 > colour1) || (!isbc1) ) | |
{ | |
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} else | |
{ | |
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] ); | |
} | |
#if PARANOID | |
int testc00 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testc01 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testc10 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testc11 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testc00 == blockbc1->c0[0] ); | |
assert( testc01 == blockbc1->c0[1] ); | |
assert( testc10 == blockbc1->c1[0] ); | |
assert( testc11 == blockbc1->c1[1] ); | |
#endif | |
unsigned int bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros; | |
int methodR, methodG, methodB ; | |
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR ); | |
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG ); | |
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB ); | |
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB ); | |
int method = ((methodR * 3 + methodG)*3 + methodB); | |
assert( method < (3*3*3) ); | |
#if PARANOID | |
int testUpR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testUpR == up[0] ); | |
int testLeftR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testLeftR == left[0] ); | |
int testDiagR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testDiagR == diag[0] ); | |
int testMethodR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testMethodR == methodR ); | |
int testPredictR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testPredictR == predictR ); | |
int testMethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testMethod == method ); | |
int testPredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testPredict == pindex ); | |
#endif | |
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex] ); | |
#if PARANOID | |
int testi = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testi == i ); | |
int testj = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testj == j ); | |
int testr = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testg = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testb = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testr == blockrgb[actualIndex][0] ); | |
assert( testg == blockrgb[actualIndex][1] ); | |
assert( testb == blockrgb[actualIndex][2] ); | |
#endif | |
bits |= actualIndex << (2*(4*i+j)); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
decompressed[curindex].r = blockrgb[actualIndex][0]; | |
decompressed[curindex].g = blockrgb[actualIndex][1]; | |
decompressed[curindex].b = blockrgb[actualIndex][2]; | |
} | |
} | |
blockbc1->bits[0] = bits & 0xff; | |
blockbc1->bits[1] = (bits>>8) & 0xff; | |
blockbc1->bits[2] = (bits>>16) & 0xff; | |
blockbc1->bits[3] = (bits>>24) & 0xff; | |
} | |
if ( blockbc3a ) | |
{ | |
#if PARANOID | |
int testa0 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testa1 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testa0 == imgchunks[0][curblockindex].a ); | |
assert( testa1 == imgchunks[1][curblockindex].a ); | |
#endif | |
blockbc3a->a[0] = imgchunks[0][curblockindex].a; | |
blockbc3a->a[1] = imgchunks[1][curblockindex].a; | |
blocka[0] = imgchunks[0][curblockindex].a; | |
blocka[1] = imgchunks[1][curblockindex].a; | |
if ( blocka[0] > blocka[1] ) | |
{ | |
generate6AlphaSet( blocka, blocka[0], blocka[1] ); | |
} | |
else | |
{ | |
generate4AlphaSet( blocka, blocka[0], blocka[1] ); | |
} | |
unsigned __int64 bits = 0; | |
for (int i=0; i<4; i++) | |
{ | |
for (int j=0; j<4; j++) | |
{ | |
unsigned char zeros[4] = { 0, 0, 0, 0 }; | |
int cury = (y*4+i) % 8; | |
int upy = (y*4+i-1) % 8; | |
int leftx = (x*4+j-1); | |
int upindex = (upy * (blockw*4) + (x*4+j)); | |
int leftindex = (cury * (blockw*4) +leftx); | |
int diagindex = (upy * (blockw*4) + leftx); | |
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros; | |
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left; | |
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up; | |
int method; | |
int predict = jpeglsPredictor( up[3], left[3], diag[3], method ); | |
int pindex = findClosestA( blocka, predict ); | |
#if PARANOID | |
int testup = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testleft = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testdiag = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testmethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testpindex = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testup == up[3] ); | |
assert( testleft == left[3] ); | |
assert( testdiag == diag[3] ); | |
assert( testmethod == method ); | |
assert( testpindex == pindex ); | |
#endif | |
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex] ); | |
#if PARANOID | |
int testi = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
int testj = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testi == i ); | |
assert( testj == j ); | |
#endif | |
bits |= (unsigned __int64)actualIndex << (3*(4*i+j)); | |
int curindex = (cury * (blockw*4) + (x*4+j)); | |
decompressed[curindex].a = blocka[actualIndex]; | |
#if PARANOID | |
int testa = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]); | |
assert( testa == decompressed[curindex].a ); | |
#endif | |
} | |
} | |
blockbc3a->bits[0] = bits & 0xff; | |
blockbc3a->bits[1] = (bits>>8) & 0xff; | |
blockbc3a->bits[2] = (bits>>16) & 0xff; | |
blockbc3a->bits[3] = (bits>>24) & 0xff; | |
blockbc3a->bits[4] = (bits>>32) & 0xff; | |
blockbc3a->bits[5] = (bits>>40) & 0xff; | |
} | |
if ( 1 ) | |
{ | |
int rll = rc_decode_symbol (&rciindicesEnc, &rcrllModel); | |
for (int r=0; r<rll; r++) | |
{ | |
char *src = ((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)); | |
char *dst = ((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + ((x+r+1) * blockSize)); | |
memcpy( dst, src, blockSize ); | |
memcpy( &imgchunks[0][curblockindex+(r+1)], &imgchunks[0][curblockindex+0], 4 ); | |
memcpy( &imgchunks[1][curblockindex+(r+1)], &imgchunks[1][curblockindex+0], 4 ); | |
for (int j=0; j<4; j++) | |
{ | |
int dstindex = (((y*4+j)%8) * (blockw*4) + (x+r+1)*4); | |
int curindex = (((y*4+j)%8) * (blockw*4) + (x*4)); | |
// int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4); | |
// int curindex = ((y*4+j) * (blockw*4) + (x*4)); | |
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 ); | |
} | |
} | |
x += rll; | |
} | |
} | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
for (int i=0; i<(3*3*3); i++) | |
{ | |
rc_model_done (&rc_c_iindicesModel[i][0]); | |
rc_model_done (&rc_c_iindicesModel[i][1]); | |
rc_model_done (&rc_c_iindicesModel[i][2]); | |
rc_model_done (&rc_c_iindicesModel[i][3]); | |
} | |
for (int i=0; i<(3); i++) | |
{ | |
rc_model_done (&rc_a_iindicesModel[i][0]); | |
rc_model_done (&rc_a_iindicesModel[i][1]); | |
rc_model_done (&rc_a_iindicesModel[i][2]); | |
rc_model_done (&rc_a_iindicesModel[i][3]); | |
rc_model_done (&rc_a_iindicesModel[i][4]); | |
rc_model_done (&rc_a_iindicesModel[i][5]); | |
rc_model_done (&rc_a_iindicesModel[i][6]); | |
rc_model_done (&rc_a_iindicesModel[i][7]); | |
} | |
for (int j=0; j<2; j++) | |
{ | |
for (int c=0; c<4; c++) | |
{ | |
rc_model_done( &rccolmodel[0][j][c] ); | |
rc_model_done( &rccolmodel[1][j][c] ); | |
rc_model_done( &rccolmodel[2][j][c] ); | |
rc_model_done( &rccolmodel[3][j][c] ); | |
rc_model_done( &rccolmodel[4][j][c] ); | |
rc_model_done( &rccolmodel[5][j][c] ); | |
} | |
} | |
free( imgchunks[0] ); | |
free( imgchunks[1] ); | |
free( decompressed ); | |
} | |
static int fileSize( const char *filename ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f ) | |
{ | |
fseek( f, 0, SEEK_END ); | |
int len = ftell( f ); | |
fclose( f ); | |
return len; | |
} | |
return 0; | |
} | |
#include <string> | |
#include <vector> | |
#include <io.h> | |
#include <algorithm> | |
char fixseparator( char c ) | |
{ | |
return ( c == '/' ) ? '\\' : c; | |
} | |
void findFiles( std::vector< std::string > &files, const char *pattern ) | |
{ | |
std::string path = pattern; | |
std::transform( path.begin(), path.end(), path.begin(), fixseparator ); | |
std::string::size_type pos = path.find_last_of( '\\' ); | |
if ( pos != std::string::npos ) | |
{ | |
path = path.substr( 0, pos ); | |
} | |
else | |
{ | |
path = ".\\"; | |
} | |
_finddata_t fi; | |
intptr_t fh = _findfirst( pattern, &fi ); | |
if ( fh != -1 ) | |
{ | |
do | |
{ | |
files.push_back( path + "\\" + fi.name ); | |
} | |
while ( _findnext( fh, &fi ) == 0 ); | |
_findclose( fh ); | |
} | |
} | |
void readlist( std::vector< std::string > &files, const char *listfile ) | |
{ | |
FILE *f = fopen( listfile, "rb" ); | |
if ( f ) | |
{ | |
char line[1024]; | |
while (fgets(line, sizeof(line), f )) | |
{ | |
char *tok = strtok( line, "\n\r" ); | |
if ( tok ) | |
{ | |
files.push_back( tok ); | |
} | |
} | |
fclose( f ); | |
} | |
} | |
void WriteDDS( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA *data ) | |
{ | |
FILE *f = fopen( filename, "wb" ); | |
if ( f ) | |
{ | |
DWORD magic = DDS_MAGIC; | |
DDS_HEADER hdr = { 0 }; | |
hdr.dwSize = sizeof(DDS_HEADER); | |
hdr.dwWidth = desc.width; | |
hdr.dwHeight = desc.height; | |
hdr.dwMipMapCount = desc.mips; | |
hdr.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; | |
hdr.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE; | |
hdr.ddspf = (desc.format == DXGI_FORMAT_BC3_UNORM) ? DDSPF_DXT5 : DDSPF_DXT1; | |
fwrite( &magic, 1, sizeof(magic), f ); | |
fwrite( &hdr, 1, sizeof(hdr), f ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int blockSize = (desc.format == DXGI_FORMAT_BC3_UNORM) ? 16 : 8; | |
for (int i=0; i<desc.mips; i++) | |
{ | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int size = blockw * blockh * blockSize; | |
fwrite( data[i].pSysMem, 1, size, f ); | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
fclose( f ); | |
} | |
} | |
std::string GetFile( const char *filename ) | |
{ | |
std::string path = filename; | |
std::transform( path.begin(), path.end(), path.begin(), fixseparator ); | |
std::string::size_type pos = path.find_last_of( '\\' ); | |
if ( pos != std::string::npos ) | |
{ | |
path = path.substr( pos ); | |
} | |
pos = path.find_last_of( '.' ); | |
if ( pos != std::string::npos ) | |
{ | |
path = path.substr( 0, pos ); | |
} | |
return path; | |
} | |
std::string GetDir( const char *filename ) | |
{ | |
std::string path = filename; | |
std::transform( path.begin(), path.end(), path.begin(), fixseparator ); | |
std::string::size_type pos = path.find_last_of( '\\' ); | |
if ( pos != std::string::npos ) | |
{ | |
path = path.substr( 0, pos ); | |
} | |
return path; | |
} | |
typedef void (*compress_f)( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData ); | |
typedef void (*decompress_f)( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData ); | |
struct compressiontest | |
{ | |
const char *name; | |
const char *ext; | |
compress_f comp; | |
decompress_f decomp; | |
}; | |
compressiontest compression_methods[] = | |
{ | |
{ "deflatezz", "_fmtzz.zz", compress_bc1and3_zz, decompress_bc1and3_zz }, | |
{ "reorder+deflate", "_fmtz.rd", compress_bc1and3_i, decompress_bc1and3_i }, | |
//{ "reorder3+deflatezz", "_fmtz.r3zz", compress_bc1and3_i3, decompress_bc1and3_i3 }, | |
{ "reorder2+deflate", "_fmtz.r2d", compress_bc1and3_i2, decompress_bc1and3_i2 }, | |
{ "reorder+delta+deflate", "_fmtrd.rdd", compress_bc1and3_id, decompress_bc1and3_id }, | |
{ "reorder2+delta+deflate", "_fmtrd.r2dd", compress_bc1and3_i2d, decompress_bc1and3_i2d }, | |
{ "deflate", "_fmtz.z", compress_bc1and3_z, decompress_bc1and3_z }, | |
{ "LCT", "_fmtlct.lct", compress_bc1and3_lcct, decompress_bc1and3_lcct }, | |
{ NULL, NULL, NULL, NULL }, | |
}; | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
FILE *rep = fopen( "report.csv", "wb" ); | |
std::vector< std::string > files; | |
findFiles( files, argv[1] ); | |
//readlist( files, argv[1] ); | |
for ( unsigned int f=0; f<files.size(); f++) | |
{ | |
printf( "%s:\n", files[f].c_str() ); | |
int len; | |
void *m = readFile( files[f].c_str(), len ); | |
if ( m == NULL ) | |
{ | |
continue; | |
} | |
DDSLoadDesc desc; | |
D3D11_SUBRESOURCE_DATA initData[20]; | |
HRESULT hr = CreateDDSTextureFromMemory( initData, (BYTE*)m, len, &desc, false ); | |
printf( "%d x %d : %d mips : %d\n", desc.width, desc.height, desc.mips, desc.format ); | |
if ( desc.width < 4 && desc.height < 4 ) | |
continue; | |
/* if ( desc.format == DXGI_FORMAT_BC1_UNORM ) | |
{ | |
//kmeanstest( desc, initData ); | |
//std::string fileoutkm = files[f] + ".kmout.dds"; | |
//WriteDDS( fileoutkm.c_str(), desc, initData ); | |
std::string lltfile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.llt"; | |
compress_bc1_lcct( lltfile.c_str(), desc, initData ); | |
DDSLoadDesc desc2; | |
D3D11_SUBRESOURCE_DATA initData2[20]; | |
decompress_bc1_lcct( lltfile.c_str(), desc2, initData2 ); | |
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.dds"; | |
WriteDDS( fileout.c_str(), desc2, initData2 ); | |
int fs = fileSize( lltfile.c_str() ); | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * sizeof(dxtrgbblock) ); | |
if ( res ) | |
{ | |
printf( "failed to decompress correctly\n"); | |
} | |
//assert( res == 0 ); | |
totalPixels += curw*curh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
free( (void*)initData2[i].pSysMem ); | |
} | |
float bpp = (fs*8.f) / totalPixels; | |
printf( "%d bytes %f bpp\n", fs, bpp); | |
} | |
else*/ | |
if ( (desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM) && 1 ) | |
{ | |
if ( rep ) | |
{ | |
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d",//, %d, %d, %.2f\n", | |
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3", | |
desc.width, desc.height, desc.mips ); | |
//fs_src, fs_dst, bpp ); | |
} | |
compressiontest *ct = compression_methods; | |
while ( ct->name ) | |
{ | |
std::string ifile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + std::string( ct->ext ); | |
ct->comp( ifile.c_str(), desc, initData ); | |
DDSLoadDesc desc2; | |
D3D11_SUBRESOURCE_DATA initData2[20]; | |
ct->decomp( ifile.c_str(), desc2, initData2 ); | |
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + std::string( ct->ext ) + ".dds"; | |
WriteDDS( fileout.c_str(), desc2, initData2 ); | |
int fs_src = fileSize( fileout.c_str() ); | |
int fs_dst = fileSize( ifile.c_str() ); | |
{ | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize ); | |
if ( res ) | |
{ | |
printf( "failed to decompress correctly\n"); | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
totalPixels += curw*curh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
free( (void*)initData2[i].pSysMem ); | |
} | |
float bpp = (fs_dst*8.f) / totalPixels; | |
printf( "%d bytes %f bpp\n", fs_dst, bpp); | |
if ( rep ) | |
{ | |
fprintf( rep, ", %d, %d, %.2f", | |
fs_src, fs_dst, bpp ); | |
} | |
ct++; | |
} | |
if ( rep ) | |
{ | |
fprintf( rep, "\n" ); | |
} | |
} | |
else | |
if ( (desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM) && 1 ) | |
{ | |
std::string ifile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtz.z"; | |
compress_bc1and3_z( ifile.c_str(), desc, initData ); | |
DDSLoadDesc desc2; | |
D3D11_SUBRESOURCE_DATA initData2[20]; | |
decompress_bc1and3_z( ifile.c_str(), desc2, initData2 ); | |
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtz.dds"; | |
WriteDDS( fileout.c_str(), desc2, initData2 ); | |
int fs_src = fileSize( fileout.c_str() ); | |
int fs_dst = fileSize( ifile.c_str() ); | |
{ | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize ); | |
if ( res ) | |
{ | |
printf( "failed to decompress correctly\n"); | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
totalPixels += curw*curh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
free( (void*)initData2[i].pSysMem ); | |
} | |
float bpp = (fs_dst*8.f) / totalPixels; | |
printf( "%d bytes %f bpp\n", fs_dst, bpp); | |
if ( rep ) | |
{ | |
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d, %d, %d, %.2f\n", | |
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3", | |
desc.width, desc.height, desc.mips, | |
fs_src, fs_dst, bpp ); | |
} | |
} | |
else | |
if ( (desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM) && 1 ) | |
{ | |
std::string ifile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmti.i"; | |
compress_bc1and3_i( ifile.c_str(), desc, initData ); | |
DDSLoadDesc desc2; | |
D3D11_SUBRESOURCE_DATA initData2[20]; | |
decompress_bc1and3_i( ifile.c_str(), desc2, initData2 ); | |
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmti.dds"; | |
WriteDDS( fileout.c_str(), desc2, initData2 ); | |
int fs_src = fileSize( fileout.c_str() ); | |
int fs_dst = fileSize( ifile.c_str() ); | |
{ | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize ); | |
if ( res ) | |
{ | |
printf( "failed to decompress correctly\n"); | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
totalPixels += curw*curh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
free( (void*)initData2[i].pSysMem ); | |
} | |
float bpp = (fs_dst*8.f) / totalPixels; | |
printf( "%d bytes %f bpp\n", fs_dst, bpp); | |
if ( rep ) | |
{ | |
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d, %d, %d, %.2f\n", | |
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3", | |
desc.width, desc.height, desc.mips, | |
fs_src, fs_dst, bpp ); | |
} | |
} | |
else | |
if ( desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
std::string lltfile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.llt"; | |
compress_bc1and3_lcct( lltfile.c_str(), desc, initData ); | |
DDSLoadDesc desc2; | |
D3D11_SUBRESOURCE_DATA initData2[20]; | |
decompress_bc1and3_lcct( lltfile.c_str(), desc2, initData2 ); | |
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.dds"; | |
WriteDDS( fileout.c_str(), desc2, initData2 ); | |
int fs_src = fileSize( fileout.c_str() ); | |
int fs_dst = fileSize( lltfile.c_str() ); | |
{ | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16; | |
int blockw = (curw+3)/4; | |
int blockh = (curh+3)/4; | |
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize ); | |
if ( res ) | |
{ | |
printf( "failed to decompress correctly\n"); | |
} | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
} | |
} | |
assert( desc.height == desc2.height ); | |
assert( desc.width == desc2.width ); | |
assert( desc.mips == desc2.mips ); | |
int curw = desc.width; | |
int curh = desc.height; | |
int totalPixels = 0; | |
for (int i=0; i<desc2.mips; i++) | |
{ | |
totalPixels += curw*curh; | |
curw = curw/2; | |
curh = curh/2; | |
if (curw == 0) | |
curw = 1; | |
if (curh == 0) | |
curh = 1; | |
free( (void*)initData2[i].pSysMem ); | |
} | |
float bpp = (fs_dst*8.f) / totalPixels; | |
printf( "%d bytes %f bpp\n", fs_dst, bpp); | |
if ( rep ) | |
{ | |
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d, %d, %d, %.2f\n", | |
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3", | |
desc.width, desc.height, desc.mips, | |
fs_src, fs_dst, bpp ); | |
} | |
} | |
else | |
if ( desc.format == DXGI_FORMAT_BC3_UNORM ) | |
{ | |
//kmeanstest( desc, initData ); | |
//std::string fileoutkm = files[f] + ".kmout.dds"; | |
//WriteDDS( fileoutkm.c_str(), desc, initData ); | |
std::string lltfile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.llt"; | |
compress_bc3_lcct( lltfile.c_str(), desc, initData ); | |
DDSLoadDesc desc2; | |
D3D11_SUBRESOURCE_DATA initData2[20]; | |
decompress_bc3_lcct( lltfile.c_str(), desc2, initData2 ); | |
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.dds"; | |
WriteDDS( fileout.c_str(), desc2, initData2 ); | |
} | |
free( m ); | |
} | |
if ( rep ) | |
{ | |
fclose( rep ); | |
} | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// simplehttp.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <WinSock2.h> | |
#pragma comment(lib, "ws2_32.lib") | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include "json.h" | |
#include <time.h> | |
#include <map> | |
#include <string> | |
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib | |
#pragma comment (lib, "Ws2_32.lib") | |
#pragma comment (lib, "Mswsock.lib") | |
#pragma comment (lib, "AdvApi32.lib") | |
#define DEFAULT_BUFLEN (512*1024) | |
#define DEFAULT_PORT "27015" | |
std::map< std::string, std::string > traininfo; | |
void dumpmap( const char *filename ) | |
{ | |
FILE *f = fopen( filename, "wb" ); | |
if ( f == NULL ) | |
{ | |
return; | |
} | |
std::map< std::string, std::string >::const_iterator b = traininfo.begin(); | |
while ( b != traininfo.end() ) | |
{ | |
fprintf( f, "\"%s\",\"%s\"\n", b->first.c_str(), b->second.c_str() ); | |
b++; | |
} | |
fclose( f ); | |
} | |
std::string ParseString( char *&cursor ) | |
{ | |
bool inquote = false; | |
std::string out; | |
while ( *cursor ) | |
{ | |
if ( inquote ) | |
{ | |
if ( cursor[0] == '"' ) | |
{ | |
cursor++; | |
break; | |
} | |
else | |
{ | |
out.push_back( cursor[0] ); | |
} | |
} | |
else | |
{ | |
if ( cursor[0] == '"' ) | |
{ | |
cursor++; | |
inquote = true; | |
continue; | |
} | |
else | |
if ( cursor[0] == ',' ) | |
{ | |
out.push_back( cursor[0] ); | |
cursor++; | |
break; | |
} | |
else | |
{ | |
out.push_back( cursor[0] ); | |
} | |
} | |
cursor++; | |
} | |
return out; | |
} | |
void parsecsv( const char *filename ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f == NULL ) | |
{ | |
return; | |
} | |
char line[2048]; | |
while( fgets( line, sizeof(line), f ) ) | |
{ | |
char *cursor = line; | |
std::string key = ParseString( cursor ); | |
std::string comma = ParseString( cursor ); | |
std::string value = ParseString( cursor ); | |
traininfo[key] = value; | |
} | |
fclose( f ); | |
} | |
std::string::size_type find_previous( std::string const &str, std::string const &needle, std::string::size_type pos ) | |
{ | |
if ( pos == std::string::npos ) | |
return std::string::npos; | |
while ( pos >= 0 ) | |
{ | |
if ( str.substr( pos, needle.size() ) == needle ) | |
return pos; | |
pos--; | |
} | |
return std::string::npos; | |
} | |
std::string::size_type matching_div( std::string const &str, std::string::size_type pos ) | |
{ | |
int level = 1; | |
while ( level ) | |
{ | |
std::string::size_type sdiv = str.find( "<div", pos+1 ); | |
std::string::size_type ediv = str.find( "</div", pos+1 ); | |
if ( sdiv < ediv ) | |
{ | |
level++; | |
pos = sdiv; | |
} | |
else | |
{ | |
level--; | |
pos = ediv; | |
} | |
if ( pos > str.size() ) | |
{ | |
pos = std::string::npos; | |
break; | |
} | |
} | |
return pos; | |
} | |
int __cdecl main(int argc, char **argv) | |
{ | |
WSADATA wsaData; | |
SOCKET ConnectSocket = INVALID_SOCKET; | |
struct addrinfo *result = NULL, | |
*ptr = NULL, | |
hints; | |
char *sendbufs[1] = { "GET http://www.theguardian.com/lifeandstyle/2013/sep/06/yotam-ottolenghi-brunch-recipes HTTP/1.1\n" | |
"Host: www.theguardian.com\n" | |
"Connection: close\n" | |
"User-Agent: Web-sniffer/1.0.46 (+http://web-sniffer.net/)\n" | |
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\n" | |
"Cache-Control: no-cache\n" | |
"Accept-Language: de,en;q=0.7,en-us;q=0.3\n" | |
"\n"}; | |
//std::string loc = "http://www.theguardian.com/lifeandstyle/2013/sep/06/yotam-ottolenghi-brunch-recipes"; | |
//std::string loc = "http://www.theguardian.com/lifeandstyle/2011/sep/16/sweet-potato-figs-tuna-fishcake-recipes"; | |
//std::string loc = "http://www.theguardian.com/lifeandstyle/2013/sep/08/roast-lamb-cherry-strawberry-recipes"; | |
//std::string loc = "http://www.theguardian.com/lifeandstyle/2013/sep/06/yotam-ottolenghi-brunch-recipes"; | |
std::string loc = "http://www.theguardian.com/lifeandstyle/2013/aug/23/hugh-fearnley-whittingstall-garlic-recipes"; | |
static char recvbuf[DEFAULT_BUFLEN]; | |
int iResult; | |
int recvbuflen = DEFAULT_BUFLEN; | |
// Initialize Winsock | |
iResult = WSAStartup(MAKEWORD(2,2), &wsaData); | |
if (iResult != 0) { | |
printf("WSAStartup failed with error: %d\n", iResult); | |
return 1; | |
} | |
ZeroMemory( &hints, sizeof(hints) ); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_socktype = SOCK_STREAM; | |
hints.ai_protocol = IPPROTO_TCP; | |
FILE *f = fopen( "hugh_recipes.html", "wb" ); | |
FILE *contentsf = fopen( "hugh_contents.txt", "wb" ); | |
fprintf( f, "<meta charset=\"utf-8\" />\n" ); | |
int sectionid = 0; | |
do | |
{ | |
//iResult = getaddrinfo("www.theguardian.com", "80", &hints, &result); | |
iResult = getaddrinfo("185.31.16.184", "80", &hints, &result); | |
if ( iResult != 0 ) { | |
printf("getaddrinfo failed with error: %d\n", iResult); | |
WSACleanup(); | |
return 1; | |
} | |
for (int index=0; index<1; index++) | |
{ | |
// Attempt to connect to an address until one succeeds | |
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { | |
// Create a SOCKET for connecting to server | |
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, | |
ptr->ai_protocol); | |
if (ConnectSocket == INVALID_SOCKET) { | |
printf("socket failed with error: %ld\n", WSAGetLastError()); | |
WSACleanup(); | |
return 1; | |
} | |
// Connect to server. | |
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); | |
if (iResult == SOCKET_ERROR) { | |
closesocket(ConnectSocket); | |
ConnectSocket = INVALID_SOCKET; | |
continue; | |
} | |
break; | |
} | |
if (ConnectSocket == INVALID_SOCKET) { | |
printf("Unable to connect to server!\n"); | |
WSACleanup(); | |
return 1; | |
} | |
printf( "%s\n", loc.c_str() ); | |
std::string request = "GET " + loc + " HTTP/1.1\n" | |
"Host: www.theguardian.com\n" | |
"Connection: close\n" | |
"User-Agent: Web-sniffer/1.0.46 (+http://web-sniffer.net/)\n" | |
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\n" | |
"Cache-Control: no-cache\n" | |
"Accept-Language: de,en;q=0.7,en-us;q=0.3\n" | |
"\n"; | |
// Send an initial buffer | |
iResult = send( ConnectSocket, request.c_str(), request.size(), 0 ); | |
if (iResult == SOCKET_ERROR) { | |
printf("send failed with error: %d\n", WSAGetLastError()); | |
closesocket(ConnectSocket); | |
WSACleanup(); | |
return 1; | |
} | |
// shutdown the connection since no more data will be sent | |
iResult = shutdown(ConnectSocket, SD_SEND); | |
if (iResult == SOCKET_ERROR) { | |
printf("shutdown failed with error: %d\n", WSAGetLastError()); | |
closesocket(ConnectSocket); | |
WSACleanup(); | |
return 1; | |
} | |
// Receive until the peer closes the connection | |
std::string output; | |
do { | |
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); | |
if ( iResult > 0 ) | |
{ | |
recvbuf[iResult] = 0; | |
output += recvbuf; | |
} | |
else if ( iResult == 0 ) | |
printf("Connection closed\n"); | |
else | |
printf("recv failed with error: %d\n", WSAGetLastError()); | |
} while( iResult > 0 ); | |
closesocket(ConnectSocket); | |
//<meta property="og:description" content=" | |
//std::string::size_type title_start = output.find( "<title>" ) + 7; | |
//std::string::size_type title_end = output.find( "</title>" ); | |
std::string::size_type title_start = output.find( "\"", output.find( "content", output.find( "property=\"og:title\"" ) ) )+1; | |
std::string::size_type title_end = output.find( "\"", title_start ); | |
std::string title = output.substr( title_start, title_end-title_start ); | |
if ( title.find( "Yotam Ottlenghi's" ) == 0 ) | |
{ | |
title = title.substr( sizeof("Yotam Ottlenghi's" ) ); | |
} | |
if ( title.find( "Yotam Ottolenghi's" ) == 0 ) | |
{ | |
title = title.substr( sizeof("Yotam Ottolenghi's" ) ); | |
} | |
if ( title.find( "The new vegetarian:" ) == 0 ) | |
{ | |
title = title.substr( sizeof("The new vegetarian:" ) ); | |
} | |
if ( title == "The new vegetarian" || title == "Yotam Ottolenghi" ) | |
{ | |
title_start = output.find( "\"", output.find( "content", output.find( "property=\"og:description\"" ) ) )+1; | |
title_end = output.find( "\"", title_start ); | |
title = output.substr( title_start, title_end-title_start ); | |
} | |
std::string::size_type article_start = output.find( "article-wrapper" ); | |
if ( article_start == std::string::npos ) | |
{ | |
Sleep( 10000 ); | |
continue; | |
} | |
std::string::size_type article_end = matching_div( output, article_start ); | |
std::string article = output.substr( article_start, article_end-article_start ); | |
std::string::size_type Previous_start = output.find( "Previous" ); | |
if ( Previous_start == std::string::npos ) | |
return 0; | |
Previous_start = find_previous( output, "<a", Previous_start ); | |
std::string::size_type href_start = output.find( "http", Previous_start ); | |
std::string::size_type href_end = output.find( "\"", href_start ); | |
std::string href = output.substr( href_start, href_end-href_start ); | |
loc = href; | |
fprintf( contentsf, "<a href=\"#section%d\">%s</a><br>\n", sectionid, title.c_str() ); | |
fprintf( f, "<section>\n<h1 id=\"#section%d\">%s</h1>\n<div id=\"%s\n</div></section>\n\n\n", sectionid, title.c_str(), article.c_str() ); | |
fflush( contentsf ); | |
fflush( f ); | |
sectionid++; | |
} | |
freeaddrinfo(result); | |
//Sleep( 1000 + ( 5 + rand() % 5 ) ); | |
} while ( true ); | |
WSACleanup(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef char LEXERCHAR; | |
enum | |
{ | |
LT_Int, | |
LT_Float, | |
LT_String, | |
LT_QuotedString, | |
LT_EOF, | |
}; | |
struct LexerToken | |
{ | |
const LEXERCHAR *start; | |
int length; | |
int type; | |
int i; | |
float f; | |
}; | |
struct LexerState | |
{ | |
const LEXERCHAR *text; | |
const LEXERCHAR *end; | |
const LEXERCHAR *cursor; | |
}; | |
enum | |
{ | |
LS_OK, | |
LS_EOF, | |
}; | |
inline static LEXERCHAR lexerNextChar( LexerState *state ) | |
{ | |
if ( state->cursor >= (state->end-1) ) | |
return LEXERCHAR(0); | |
return state->cursor[1]; | |
} | |
inline static LEXERCHAR lexerCurChar( LexerState *state ) | |
{ | |
if ( state->cursor >= state->end ) | |
return LEXERCHAR(0); | |
return state->cursor[0]; | |
} | |
static bool lexerIsAny( LEXERCHAR c, LEXERCHAR *chars ) | |
{ | |
while ( *chars ) | |
{ | |
if ( c == *chars ) | |
return true; | |
chars++; | |
} | |
return false; | |
} | |
bool lexerIsEof( LexerState *state ) | |
{ | |
return state->cursor >= state->end; | |
} | |
static bool lexerIsDigit( LEXERCHAR c ) | |
{ | |
return (c>=LEXERCHAR('0') && c<=LEXERCHAR('9')); | |
} | |
static bool lexerIsAlpha( LEXERCHAR c ) | |
{ | |
return ((c>=LEXERCHAR('a') && c<=LEXERCHAR('z'))) || ((c>=LEXERCHAR('A') && c<=LEXERCHAR('Z'))) || lexerIsAny( c, "_" ); | |
} | |
static bool lexerIsAlphaOrDigit( LEXERCHAR c ) | |
{ | |
return lexerIsAlpha(c) || lexerIsDigit(c); | |
} | |
static bool lexerIsOctalDigit( LEXERCHAR c ) | |
{ | |
return c >= LEXERCHAR('0') && c <= LEXERCHAR('7'); | |
} | |
static bool lexerIsHexDigit( LEXERCHAR c ) | |
{ | |
return (c >= LEXERCHAR('0') && c <= LEXERCHAR('9')) || | |
(c >= LEXERCHAR('a') && c <= LEXERCHAR('f')) || | |
(c >= LEXERCHAR('A') && c <= LEXERCHAR('F')); | |
} | |
static bool lexerIsBinDigit( LEXERCHAR c ) | |
{ | |
return c >= LEXERCHAR('0') && c <= LEXERCHAR('1'); | |
} | |
static bool lexerSkipWS( LexerState *state ) | |
{ | |
const LEXERCHAR *start = state->cursor; | |
while ( state->cursor < state->end && lexerIsAny( lexerCurChar(state), " \t\n\r" ) ) | |
state->cursor++; | |
return state->cursor > start; | |
} | |
static void lexerSkipMultiLineComment( LexerState *state ) | |
{ | |
while ( state->cursor < state->end ) | |
{ | |
if ( lexerCurChar(state) == LEXERCHAR('*') && lexerNextChar(state) == LEXERCHAR('/') ) | |
{ | |
state->cursor+=2; | |
return; | |
} | |
state->cursor++; | |
} | |
} | |
static void lexerSkipSingleLineComment( LexerState *state ) | |
{ | |
while ( state->cursor < state->end ) | |
{ | |
if ( lexerCurChar(state) == LEXERCHAR('\n') ) | |
{ | |
state->cursor++; | |
return; | |
} | |
state->cursor++; | |
} | |
} | |
static int maxExponent = 511; /* Largest possible base 10 exponent. Any | |
* exponent larger than this will already | |
* produce underflow or overflow, so there's | |
* no need to worry about additional digits. | |
*/ | |
static double powersOf10[] = { /* Table giving binary powers of 10. Entry */ | |
10., /* is 10^2^i. Used to convert decimal */ | |
100., /* exponents into floating-point numbers. */ | |
1.0e4, | |
1.0e8, | |
1.0e16, | |
1.0e32, | |
1.0e64, | |
1.0e128, | |
1.0e256 | |
}; | |
/* | |
*---------------------------------------------------------------------- | |
* | |
* strtod -- | |
* | |
* This procedure converts a floating-point number from an ASCII | |
* decimal representation to internal double-precision format. | |
* | |
* Results: | |
* The return value is the double-precision floating-point | |
* representation of the characters in string. If endPtr isn't | |
* NULL, then *endPtr is filled in with the address of the | |
* next character after the last one that was part of the | |
* floating-point number. | |
* | |
* Side effects: | |
* None. | |
* | |
*---------------------------------------------------------------------- | |
*/ | |
double lexerStrtod(const char *string, const char *end) | |
{ | |
int sign, expSign = 0; | |
double fraction, dblExp, *d; | |
register const char *p; | |
register int c; | |
int exp = 0; /* Exponent read from "EX" field. */ | |
int fracExp = 0; /* Exponent that derives from the fractional | |
* part. Under normal circumstatnces, it is | |
* the negative of the number of digits in F. | |
* However, if I is very long, the last digits | |
* of I get dropped (otherwise a long I with a | |
* large negative exponent could cause an | |
* unnecessary overflow on I alone). In this | |
* case, fracExp is incremented one for each | |
* dropped digit. */ | |
int mantSize; /* Number of digits in mantissa. */ | |
int decPt; /* Number of mantissa digits BEFORE decimal | |
* point. */ | |
const char *pExp; /* Temporarily holds location of exponent | |
* in string. */ | |
/* | |
* Strip off leading blanks and check for a sign. | |
*/ | |
p = string; | |
if (*p == '-') | |
{ | |
sign = 1; | |
p += 1; | |
} else | |
{ | |
if (*p == '+') | |
{ | |
p += 1; | |
} | |
sign = 0; | |
} | |
/* | |
* Count the number of digits in the mantissa (including the decimal | |
* point), and also locate the decimal point. | |
*/ | |
decPt = -1; | |
for (mantSize = 0; ; mantSize += 1) | |
{ | |
if ( p >= end ) | |
break; | |
c = *p; | |
if (!isdigit(c)) | |
{ | |
if ((c != '.') || (decPt >= 0)) | |
{ | |
break; | |
} | |
decPt = mantSize; | |
} | |
p += 1; | |
} | |
/* | |
* Now suck up the digits in the mantissa. Use two integers to | |
* collect 9 digits each (this is faster than using floating-point). | |
* If the mantissa has more than 18 digits, ignore the extras, since | |
* they can't affect the value anyway. | |
*/ | |
pExp = p; | |
p -= mantSize; | |
if (decPt < 0) | |
{ | |
decPt = mantSize; | |
} else | |
{ | |
mantSize -= 1; /* One of the digits was the point. */ | |
} | |
if (mantSize > 18) | |
{ | |
fracExp = decPt - 18; | |
mantSize = 18; | |
} else | |
{ | |
fracExp = decPt - mantSize; | |
} | |
if (mantSize == 0) | |
{ | |
fraction = 0.0; | |
p = string; | |
goto done; | |
} else | |
{ | |
int frac1, frac2; | |
frac1 = 0; | |
for ( ; mantSize > 9; mantSize -= 1) | |
{ | |
if ( p >= end ) | |
break; | |
c = *p; | |
p += 1; | |
if (c == '.') | |
{ | |
if ( p >= end ) | |
break; | |
c = *p; | |
p += 1; | |
} | |
frac1 = 10*frac1 + (c - '0'); | |
} | |
frac2 = 0; | |
for (; mantSize > 0; mantSize -= 1) | |
{ | |
if ( p >= end ) | |
break; | |
c = *p; | |
p += 1; | |
if (c == '.') | |
{ | |
if ( p >= end ) | |
break; | |
c = *p; | |
p += 1; | |
} | |
frac2 = 10*frac2 + (c - '0'); | |
} | |
fraction = (1.0e9 * frac1) + frac2; | |
} | |
/* | |
* Skim off the exponent. | |
*/ | |
p = pExp; | |
if (p<end && ((*p == 'E') || (*p == 'e'))) | |
{ | |
p += 1; | |
if (p<end && *p == '-') | |
{ | |
expSign = 1; | |
p += 1; | |
} else | |
{ | |
if (p<end && *p == '+') | |
{ | |
p += 1; | |
} | |
expSign = 0; | |
} | |
if (p<end && !isdigit(LEXERCHAR(*p))) | |
{ | |
p = pExp; | |
goto done; | |
} | |
while (p<end && isdigit(LEXERCHAR(*p))) | |
{ | |
exp = exp * 10 + (*p - '0'); | |
p += 1; | |
} | |
} | |
if (expSign) | |
{ | |
exp = fracExp - exp; | |
} else { | |
exp = fracExp + exp; | |
} | |
/* | |
* Generate a floating-point number that represents the exponent. | |
* Do this by processing the exponent one bit at a time to combine | |
* many powers of 2 of 10. Then combine the exponent with the | |
* fraction. | |
*/ | |
if (exp < 0) | |
{ | |
expSign = 1; | |
exp = -exp; | |
} else | |
{ | |
expSign = 0; | |
} | |
if (exp > maxExponent) | |
{ | |
exp = maxExponent; | |
errno = ERANGE; | |
} | |
dblExp = 1.0; | |
for (d = powersOf10; exp != 0; exp >>= 1, d += 1) | |
{ | |
if (exp & 01) | |
{ | |
dblExp *= *d; | |
} | |
} | |
if (expSign) | |
{ | |
fraction /= dblExp; | |
} else | |
{ | |
fraction *= dblExp; | |
} | |
done: | |
if (sign) | |
{ | |
return -fraction; | |
} | |
return fraction; | |
} | |
static bool lexerGetNumber( LexerToken *token, LexerState *state ) | |
{ | |
if ( !lexerIsDigit( lexerCurChar(state) ) ) | |
return false; | |
token->type = LT_Int; | |
if ( lexerCurChar(state) == LEXERCHAR('0') ) | |
{ | |
if ( lexerIsAny( lexerNextChar(state), "xX" ) ) | |
{ | |
state->cursor += 2; | |
int i = 0; | |
while ( lexerIsHexDigit( lexerCurChar(state) ) ) | |
{ | |
i *= 16; | |
if ( lexerCurChar(state) >= LEXERCHAR('0') && lexerCurChar(state) <= LEXERCHAR('9') ) | |
i += lexerCurChar(state) - LEXERCHAR('0'); | |
if ( lexerCurChar(state) >= LEXERCHAR('a') && lexerCurChar(state) <= LEXERCHAR('f') ) | |
i += (lexerCurChar(state) - LEXERCHAR('a')) + 10; | |
if ( lexerCurChar(state) >= LEXERCHAR('A') && lexerCurChar(state) <= LEXERCHAR('F') ) | |
i += (lexerCurChar(state) - LEXERCHAR('A')) + 10; | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
token->i = i; | |
token->f = i; | |
return true; | |
} | |
if ( lexerIsAny( lexerNextChar(state), "bB" ) ) | |
{ | |
state->cursor += 2; | |
int i = 0; | |
while ( lexerIsBinDigit( lexerCurChar(state) ) ) | |
{ | |
i *= 2; | |
if ( lexerCurChar(state) >= LEXERCHAR('0') && lexerCurChar(state) <= LEXERCHAR('1') ) | |
i += lexerCurChar(state) - LEXERCHAR('0'); | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
token->i = i; | |
token->f = i; | |
return true; | |
} | |
if ( lexerIsOctalDigit( lexerNextChar(state) ) ) | |
{ | |
int i = 0; | |
while ( lexerIsOctalDigit( lexerCurChar(state) ) ) | |
{ | |
i *= 8; | |
if ( lexerCurChar(state) >= LEXERCHAR('0') && lexerCurChar(state) <= LEXERCHAR('7') ) | |
i += lexerCurChar(state) - LEXERCHAR('0'); | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
token->i = i; | |
token->f = i; | |
return true; | |
} | |
if ( lexerNextChar(state) != '.' ) | |
{ | |
token->i = 0; | |
token->f = 0; | |
state->cursor++; | |
token->length = state->cursor - token->start; | |
return true; | |
} | |
} | |
int i = 0; | |
while ( lexerIsDigit( lexerCurChar(state) ) ) | |
{ | |
i*=10; | |
i += lexerCurChar(state) - LEXERCHAR('0'); | |
state->cursor++; | |
} | |
token->i = i; | |
token->f = i; | |
if ( lexerCurChar(state) == LEXERCHAR('.') ) | |
{ | |
token->type = LT_Float; | |
state->cursor++; | |
while ( lexerIsDigit( lexerCurChar(state) ) ) | |
{ | |
state->cursor++; | |
} | |
if ( lexerIsAny( lexerCurChar(state), "eE" ) ) | |
{ | |
token->type = LT_Float; | |
state->cursor++; | |
if ( lexerCurChar(state) == LEXERCHAR('-') ) | |
{ | |
state->cursor++; | |
} | |
while ( lexerIsDigit( lexerCurChar(state) ) ) | |
{ | |
state->cursor++; | |
} | |
} | |
token->f = lexerStrtod( token->start, state->cursor ); | |
token->i = token->f; | |
} | |
token->length = state->cursor - token->start; | |
return true; | |
} | |
int lexerGetToken( LexerToken *token, LexerState *state ) | |
{ | |
if ( lexerIsEof( state ) ) | |
{ | |
token->start = NULL; | |
token->length = 0; | |
token->type = LT_EOF; | |
return LS_EOF; | |
} | |
while ( 1 ) | |
{ | |
if ( lexerSkipWS( state ) ) | |
continue; | |
if ( lexerCurChar( state ) == LEXERCHAR( '/' ) && lexerNextChar( state ) == LEXERCHAR( '*' ) ) | |
{ | |
lexerSkipMultiLineComment( state ); | |
continue; | |
} | |
if ( lexerCurChar( state ) == LEXERCHAR( '/' ) && lexerNextChar( state ) == LEXERCHAR( '/' ) ) | |
{ | |
lexerSkipSingleLineComment( state ); | |
continue; | |
} | |
break; | |
} | |
if ( lexerCurChar( state ) == LEXERCHAR( '+' ) || lexerCurChar( state ) == LEXERCHAR( '-' ) ) | |
{ | |
token->start = state->cursor; | |
token->length = 1; | |
state->cursor++; | |
if ( lexerGetNumber( token, state ) ) | |
{ | |
return LS_OK; | |
} | |
else | |
{ | |
token->type = LT_String; | |
return LS_OK; | |
} | |
} | |
token->start = state->cursor; | |
token->type = LT_String; | |
if ( lexerGetNumber( token, state ) ) | |
{ | |
return LS_OK; | |
} | |
else | |
if ( lexerCurChar(state) == LEXERCHAR('\"') ) | |
{ | |
state->cursor++; | |
token->start = state->cursor; | |
token->type = LT_QuotedString; | |
while ( lexerCurChar(state) != LEXERCHAR('\"') ) | |
{ | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
state->cursor++; | |
return LS_OK; | |
} | |
else | |
if ( lexerCurChar(state) == LEXERCHAR('$') && lexerIsAlpha( lexerNextChar(state) ) ) | |
{ | |
token->start = state->cursor; | |
token->type = LT_String; | |
state->cursor++; | |
while ( lexerIsAlphaOrDigit( lexerCurChar(state) ) ) | |
{ | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
return LS_OK; | |
} | |
else | |
if ( lexerCurChar(state) == LEXERCHAR('%') && lexerIsAlpha( lexerNextChar(state) ) ) | |
{ | |
token->start = state->cursor; | |
token->type = LT_String; | |
state->cursor++; | |
while ( lexerIsAlphaOrDigit( lexerCurChar(state) ) ) | |
{ | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
return LS_OK; | |
} | |
else | |
if ( lexerIsAlpha( lexerCurChar(state) ) ) | |
{ | |
token->start = state->cursor; | |
token->type = LT_String; | |
state->cursor++; | |
while ( lexerIsAlphaOrDigit( lexerCurChar(state) ) ) | |
{ | |
state->cursor++; | |
} | |
token->length = state->cursor - token->start; | |
return LS_OK; | |
} | |
else | |
{ | |
token->start = state->cursor; | |
token->type = LT_String; | |
state->cursor++; | |
token->length = state->cursor - token->start; | |
return LS_OK; | |
} | |
} | |
int lexerGetLineNumber( LexerState *state ) | |
{ | |
int line = 0; | |
const LEXERCHAR *c = state->text; | |
while ( c < state->cursor ) | |
{ | |
line += (*c == LEXERCHAR('\n')) ? 1 : 0; | |
c++; | |
} | |
return line; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// simplehttp.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <WinSock2.h> | |
#pragma comment(lib, "ws2_32.lib") | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include "json.h" | |
#include <time.h> | |
#include <map> | |
#include <string> | |
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib | |
#pragma comment (lib, "Ws2_32.lib") | |
#pragma comment (lib, "Mswsock.lib") | |
#pragma comment (lib, "AdvApi32.lib") | |
#define DEFAULT_BUFLEN (512*1024) | |
#define DEFAULT_PORT "27015" | |
std::map< std::string, std::string > traininfo; | |
void dumpmap( const char *filename ) | |
{ | |
FILE *f = fopen( filename, "wb" ); | |
if ( f == NULL ) | |
{ | |
return; | |
} | |
std::map< std::string, std::string >::const_iterator b = traininfo.begin(); | |
while ( b != traininfo.end() ) | |
{ | |
fprintf( f, "\"%s\",\"%s\"\n", b->first.c_str(), b->second.c_str() ); | |
b++; | |
} | |
fclose( f ); | |
} | |
std::string ParseString( char *&cursor ) | |
{ | |
bool inquote = false; | |
std::string out; | |
while ( *cursor ) | |
{ | |
if ( inquote ) | |
{ | |
if ( cursor[0] == '"' ) | |
{ | |
cursor++; | |
break; | |
} | |
else | |
{ | |
out.push_back( cursor[0] ); | |
} | |
} | |
else | |
{ | |
if ( cursor[0] == '"' ) | |
{ | |
cursor++; | |
inquote = true; | |
continue; | |
} | |
else | |
if ( cursor[0] == ',' ) | |
{ | |
out.push_back( cursor[0] ); | |
cursor++; | |
break; | |
} | |
else | |
{ | |
out.push_back( cursor[0] ); | |
} | |
} | |
cursor++; | |
} | |
return out; | |
} | |
void parsecsv( const char *filename ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f == NULL ) | |
{ | |
return; | |
} | |
char line[2048]; | |
while( fgets( line, sizeof(line), f ) ) | |
{ | |
char *cursor = line; | |
std::string key = ParseString( cursor ); | |
std::string comma = ParseString( cursor ); | |
std::string value = ParseString( cursor ); | |
traininfo[key] = value; | |
} | |
fclose( f ); | |
} | |
int __cdecl main(int argc, char **argv) | |
{ | |
WSADATA wsaData; | |
SOCKET ConnectSocket = INVALID_SOCKET; | |
struct addrinfo *result = NULL, | |
*ptr = NULL, | |
hints; | |
// char *sendbufs[2] = { "GET http://ojp.nationalrail.co.uk/service/ldb/liveTrainsJson?departing=false&liveTrainsFrom=VIC&liveTrainsTo=WMA&serviceId=\n\n", | |
// "GET http://ojp.nationalrail.co.uk/service/ldb/liveTrainsJson?departing=false&liveTrainsFrom=WMA&liveTrainsTo=VIC&serviceId=\n\n" }; | |
char *sendbufs[2] = { "GET http://connect.garmin.com/proxy/activity-service-1.1/gpx/activity/267265456?full=true", "GET http://connect.garmin.com/proxy/activity-service-1.1/gpx/activity/267265456?full=true" }; | |
static char recvbuf[DEFAULT_BUFLEN]; | |
int iResult; | |
int recvbuflen = DEFAULT_BUFLEN; | |
// Initialize Winsock | |
iResult = WSAStartup(MAKEWORD(2,2), &wsaData); | |
if (iResult != 0) { | |
printf("WSAStartup failed with error: %d\n", iResult); | |
return 1; | |
} | |
{ | |
SOCKET Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); | |
if (Socket == INVALID_SOCKET) { | |
printf("socket failed with error: %ld\n", WSAGetLastError()); | |
WSACleanup(); | |
return 1; | |
} | |
SOCKADDR_IN SockAddr; | |
SockAddr.sin_port=htons(38300); | |
SockAddr.sin_family=AF_INET; | |
SockAddr.sin_addr.S_un.S_un_b.s_b1 = 127; | |
SockAddr.sin_addr.S_un.S_un_b.s_b2 = 0; | |
SockAddr.sin_addr.S_un.S_un_b.s_b3 = 0; | |
SockAddr.sin_addr.S_un.S_un_b.s_b4 = 1; | |
// Connect to server. | |
iResult = connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)); | |
if (iResult == SOCKET_ERROR) { | |
closesocket(ConnectSocket); | |
return -1; | |
} | |
int flag = 1; | |
int result = setsockopt(ConnectSocket, /* socket affected */ | |
IPPROTO_TCP, /* set option at TCP level */ | |
TCP_NODELAY, /* name of option */ | |
(char *) &flag, /* the cast is historical cruft */ | |
sizeof(int)); /* length of option value */ | |
//setsockopt( ConnectSocket, SOL_SOCKET, so_sendbuf | |
char *buffer = new char [1280*800*4]; | |
char *bufferBlack = new char [1280*800*4]; | |
memset( buffer, 0xff, 1280*800*4 ); | |
memset( bufferBlack, 0, 1280*800*4 ); | |
int alt = 0; | |
while ( 1 ) | |
{ | |
int nDataLength=recv(Socket,buffer,1000,0); | |
if ( buffer < 0 ) | |
break; | |
//buffer[nDataLength] = 0; | |
int out = send(Socket,alt ? buffer : bufferBlack,1280*800*4,0); | |
alt = 1-alt; | |
printf( "%d\n", out ); | |
} | |
return 0; | |
} | |
ZeroMemory( &hints, sizeof(hints) ); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_socktype = SOCK_STREAM; | |
hints.ai_protocol = IPPROTO_TCP; | |
SYSTEMTIME lastct; | |
GetLocalTime( &lastct ); | |
lastct.wDayOfWeek--; | |
parsecsv( "trains.csv" ); | |
do | |
{ | |
SYSTEMTIME ct; | |
GetLocalTime( &ct ); | |
if ( lastct.wDayOfWeek != ct.wDayOfWeek ) | |
{ | |
char backup[256]; | |
sprintf( backup, "trains_%04d%02d%02d.csv", lastct.wYear, lastct.wMonth, lastct.wDay ); | |
CopyFileA( "trains.csv", backup, TRUE ); | |
} | |
lastct = ct; | |
if ( ct.wDayOfWeek < 1 || ct.wDayOfWeek > 5 ) | |
{ | |
//Sleep( 5 * 60 * 1000 ); | |
//continue; | |
} | |
if ( !((ct.wHour >= 5 && ct.wHour < 8 ) || (ct.wHour >= 13 && ct.wHour <20)) ) | |
{ | |
//Sleep( 5 * 60 * 1000 ); | |
//continue; | |
} | |
// Resolve the server address and port | |
//iResult = getaddrinfo("ojp.nationalrail.co.uk", "80", &hints, &result); | |
iResult = getaddrinfo("connect.garmin.com", "80", &hints, &result); | |
if ( iResult != 0 ) { | |
printf("getaddrinfo failed with error: %d\n", iResult); | |
WSACleanup(); | |
return 1; | |
} | |
for (int index=0; index<2; index++) | |
{ | |
// Attempt to connect to an address until one succeeds | |
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { | |
// Create a SOCKET for connecting to server | |
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, | |
ptr->ai_protocol); | |
if (ConnectSocket == INVALID_SOCKET) { | |
printf("socket failed with error: %ld\n", WSAGetLastError()); | |
WSACleanup(); | |
return 1; | |
} | |
// Connect to server. | |
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); | |
if (iResult == SOCKET_ERROR) { | |
closesocket(ConnectSocket); | |
ConnectSocket = INVALID_SOCKET; | |
continue; | |
} | |
break; | |
} | |
if (ConnectSocket == INVALID_SOCKET) { | |
printf("Unable to connect to server!\n"); | |
WSACleanup(); | |
return 1; | |
} | |
// Send an initial buffer | |
iResult = send( ConnectSocket, sendbufs[index], (int)strlen(sendbufs[index]), 0 ); | |
if (iResult == SOCKET_ERROR) { | |
printf("send failed with error: %d\n", WSAGetLastError()); | |
closesocket(ConnectSocket); | |
WSACleanup(); | |
return 1; | |
} | |
// shutdown the connection since no more data will be sent | |
iResult = shutdown(ConnectSocket, SD_SEND); | |
if (iResult == SOCKET_ERROR) { | |
printf("shutdown failed with error: %d\n", WSAGetLastError()); | |
closesocket(ConnectSocket); | |
WSACleanup(); | |
return 1; | |
} | |
// Receive until the peer closes the connection | |
do { | |
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); | |
if ( iResult > 0 ) | |
recvbuf[iResult] = 0; | |
else if ( iResult == 0 ) | |
printf("Connection closed\n"); | |
else | |
printf("recv failed with error: %d\n", WSAGetLastError()); | |
} while( iResult > 0 ); | |
if ( recvbuflen ) | |
{ | |
json_value *jv = json_parse( recvbuf ); | |
if ( jv ) | |
{ | |
json_value const &trains = (*jv)["trains"]; | |
char timefmt[128]; | |
sprintf( timefmt, "%04d%02d%02d", ct.wYear, ct.wMonth, ct.wDay ); | |
for (unsigned int i=0; i<trains.u.array.length; i++) | |
{ | |
json_value const &train = trains[i]; | |
json_value const &flags = train[0]; | |
json_value const &duetime = train[1]; | |
json_value const &origin = train[2]; | |
json_value const &delay = train[3]; | |
std::string trainId = std::string(timefmt) + std::string(":") + std::string( duetime ) + std::string(":") + std::string( origin ); | |
std::string d = std::string( flags ) + std::string( " : " ) + std::string( delay ); | |
traininfo[trainId] = d; | |
} | |
json_value_free( jv ); | |
} | |
printf(""); | |
} | |
dumpmap( "trains.csv" ); | |
// cleanup | |
closesocket(ConnectSocket); | |
} | |
freeaddrinfo(result); | |
Sleep( 1000 * 60 * ( 5 + rand() % 5 ) ); | |
} while ( true ); | |
WSACleanup(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// mybc7.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#define STB_DXT_IMPLEMENTATION | |
#include "stb_dxt.h" | |
#include "stb_image.h" | |
#include <algorithm> | |
#include "crn_win32_timer.h" | |
static int shapes_two[64*16] = | |
{ | |
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, | |
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, | |
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, | |
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, | |
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, | |
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, | |
0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, | |
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, | |
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, | |
0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, | |
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, | |
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, | |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, | |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, | |
1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, | |
1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, | |
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, | |
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, | |
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, | |
0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, | |
0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, | |
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, | |
0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, | |
0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, | |
0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, | |
0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, | |
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, | |
1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, | |
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, | |
0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, | |
0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, | |
0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, | |
0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, | |
0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, | |
1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, | |
0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, | |
1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, | |
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, | |
0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, | |
1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, | |
1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, | |
0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, | |
1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, | |
1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, | |
0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, | |
0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, | |
0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, | |
0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, | |
1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, | |
1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, | |
0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, | |
0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, | |
1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, | |
1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, | |
1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, | |
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, | |
1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, | |
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, | |
0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, | |
}; | |
static int shapes_three[64*16] = | |
{ | |
0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, | |
0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 0, 0, 2, 2, | |
0, 2, 2, 1, 2, 2, 1, 1, 2, 2, 1, 1, 0, 0, 1, 1, | |
2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 0, 1, 1, 1, | |
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1, | |
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1, | |
1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, | |
1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, | |
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 2, | |
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 1, 2, | |
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, | |
0, 1, 1, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, | |
0, 1, 1, 2, 0, 1, 2, 2, 0, 1, 1, 2, 2, 0, 0, 1, | |
0, 1, 1, 2, 0, 1, 2, 2, 1, 1, 2, 2, 2, 2, 0, 0, | |
0, 1, 1, 2, 0, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, | |
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, | |
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 2, 2, | |
0, 1, 1, 2, 2, 0, 0, 1, 1, 1, 2, 2, 0, 0, 2, 2, | |
1, 1, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, 1, 1, 1, 1, | |
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, | |
0, 2, 2, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 2, 1, 0, | |
0, 2, 2, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 2, 1, 0, | |
0, 1, 2, 2, 0, 0, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0, | |
0, 1, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 0, 1, 1, 0, | |
0, 0, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 1, | |
0, 0, 0, 0, 2, 2, 2, 2, 0, 1, 1, 0, 1, 2, 2, 1, | |
0, 0, 2, 2, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, | |
1, 1, 0, 2, 0, 1, 1, 0, 0, 1, 2, 2, 2, 0, 0, 0, | |
1, 1, 0, 2, 2, 0, 0, 2, 0, 1, 2, 2, 2, 2, 1, 1, | |
0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, 2, 1, | |
0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 1, 1, 0, 1, 2, 0, | |
0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 1, 2, 0, | |
1, 1, 2, 2, 0, 0, 1, 2, 0, 0, 2, 2, 0, 1, 2, 0, | |
1, 2, 2, 2, 0, 0, 1, 1, 0, 2, 2, 2, 0, 1, 2, 0, | |
0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 1, | |
1, 1, 1, 1, 1, 2, 0, 1, 2, 0, 1, 2, 2, 2, 0, 0, | |
2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 0, 1, 1, 1, 2, 2, | |
0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 1, | |
0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2, 2, | |
1, 1, 2, 2, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 2, 2, | |
2, 2, 0, 0, 2, 2, 2, 2, 2, 1, 2, 1, 0, 0, 2, 2, | |
0, 0, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, | |
0, 0, 2, 2, 0, 2, 2, 0, 0, 1, 0, 1, 0, 0, 0, 0, | |
0, 0, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, | |
0, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 1, 2, 1, | |
0, 0, 1, 1, 1, 2, 2, 1, 0, 1, 0, 1, 2, 1, 2, 1, | |
0, 1, 0, 1, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, | |
0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, | |
0, 1, 0, 1, 0, 2, 2, 2, 0, 0, 0, 2, 2, 1, 1, 2, | |
2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, | |
0, 2, 2, 2, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0, | |
0, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0, | |
0, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 0, 2, 1, 1, 2, | |
0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 2, | |
0, 1, 1, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, | |
0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, | |
2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, | |
2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 1, 1, 2, | |
0, 0, 0, 2, 0, 2, 2, 2, 0, 1, 0, 1, 0, 1, 1, 1, | |
0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, | |
0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, | |
0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, | |
}; | |
#define REGION(s,x,y,si) s[((si)&3)*4+((si)>>2)*64+(x)+(y)*16] | |
static int shapeindex_to_compressed_indices_3[64*3] = | |
{ | |
0, 3,15, 0, 3, 8, 0,15, 8, 0,15, 3, | |
0, 8,15, 0, 3,15, 0,15, 3, 0,15, 8, | |
0, 8,15, 0, 8,15, 0, 6,15, 0, 6,15, | |
0, 6,15, 0, 5,15, 0, 3,15, 0, 3, 8, | |
0, 3,15, 0, 3, 8, 0, 8,15, 0,15, 3, | |
0, 3,15, 0, 3, 8, 0, 6,15, 0,10, 8, | |
0, 5, 3, 0, 8,15, 0, 8, 6, 0, 6,10, | |
0, 8,15, 0, 5,15, 0,15,10, 0,15, 8, | |
0, 8,15, 0,15, 3, 0, 3,15, 0, 5,10, | |
0, 6,10, 0,10, 8, 0, 8, 9, 0,15,10, | |
0,15, 6, 0, 3,15, 0,15, 8, 0, 5,15, | |
0,15, 3, 0,15, 6, 0,15, 6, 0,15, 8, | |
0, 3,15, 0,15, 3, 0, 5,15, 0, 5,15, | |
0, 5,15, 0, 8,15, 0, 5,15, 0,10,15, | |
0, 5,15, 0,10,15, 0, 8,15, 0,13,15, | |
0,15, 3, 0,12,15, 0, 3,15, 0, 3, 8 | |
}; | |
static int shapeindex_to_compressed_indices_2[64*3] = | |
{ | |
0,15,0, 0,15,0, 0,15,0, 0,15,0, | |
0,15,0, 0,15,0, 0,15,0, 0,15,0, | |
0,15,0, 0,15,0, 0,15,0, 0,15,0, | |
0,15,0, 0,15,0, 0,15,0, 0,15,0, | |
0,15,0, 0, 2,0, 0, 8,0, 0, 2,0, | |
0, 2,0, 0, 8,0, 0, 8,0, 0,15,0, | |
0, 2,0, 0, 8,0, 0, 2,0, 0, 2,0, | |
0, 8,0, 0, 8,0, 0, 2,0, 0, 2,0, | |
0,15,0, 0,15,0, 0, 6,0, 0, 8,0, | |
0, 2,0, 0, 8,0, 0,15,0, 0,15,0, | |
0, 2,0, 0, 8,0, 0, 2,0, 0, 2,0, | |
0, 2,0, 0,15,0, 0,15,0, 0, 6,0, | |
0, 6,0, 0, 2,0, 0, 6,0, 0, 8,0, | |
0,15,0, 0,15,0, 0, 2,0, 0, 2,0, | |
0,15,0, 0,15,0, 0,15,0, 0,15,0, | |
0,15,0, 0, 2,0, 0, 2,0, 0,15,0 | |
}; | |
#define SHAPEINDEX_TO_COMPRESSED_INDICES(s,si,region) s[(si)*3+(region)] | |
static void stb__FromNBit(unsigned char *out, unsigned int v, int bits) | |
{ | |
int rv = (v >> (bits*2)) & ((1<<bits)-1); | |
int gv = (v >> (bits*1)) & ((1<<bits)-1); | |
int bv = (v >> (bits*0)) & ((1<<bits)-1); | |
out[0] = (rv<<(8-bits))|(rv>>(bits-(8-bits))); | |
out[1] = (gv<<(8-bits))|(gv>>(bits-(8-bits))); | |
out[2] = (bv<<(8-bits))|(bv>>(bits-(8-bits))); | |
out[3] = 0; | |
} | |
static unsigned int stb__AsNBit(int r, int g, int b, int bits) | |
{ | |
return (stb__Mul8Bit(r,((1<<bits)-1)) << (bits*2)) + (stb__Mul8Bit(g,((1<<bits)-1)) << (bits*1)) + stb__Mul8Bit(b,((1<<bits)-1)); | |
} | |
static void stb__OptimizeColorsBlock(unsigned char *block, unsigned int pmax32[3], unsigned int pmin32[3], int *shapes, int shapeIndex, int regions, int bits, int *reorder, int numChannels ) | |
{ | |
static const int nIterPower = 4; | |
int mind[3] = {0x7fffffff,0x7fffffff,0x7fffffff}; | |
int maxd[3] = {-0x7fffffff,-0x7fffffff,-0x7fffffff}; | |
unsigned char *minp[3], *maxp[3]; | |
double magn[3]; | |
int v_r[3],v_g[3],v_b[3],v_a[3]; | |
float covf[3][10],vfr[3],vfg[3],vfb[3],vfa[3]; | |
// determine color distribution | |
int cov[3][10]; | |
int mu[3][4],min[3][4],max[3][4]; | |
int ch,i,iter; | |
for(ch=0;ch<numChannels;ch++) | |
{ | |
const unsigned char *bp = ((const unsigned char *) block) + reorder[ch]; | |
int muv[3] = {0,0,0}; | |
int minv[3] = {256,256,256}; | |
int maxv[3] = {0,0,0}; | |
for(i=0;i<64;i+=4) | |
{ | |
int r = REGION(shapes,((i/4)%4),((i/4)/4),shapeIndex); | |
muv[r] += bp[i]; | |
if (bp[i] < minv[r]) minv[r] = bp[i]; | |
else if (bp[i] > maxv[r]) maxv[r] = bp[i]; | |
} | |
for (int r=0; r<regions; r++) | |
{ | |
mu[r][ch] = (muv[r] + 8) >> 4; | |
min[r][ch] = minv[r]; | |
max[r][ch] = maxv[r]; | |
} | |
} | |
// determine covariance matrix | |
for (int r=0; r<regions; r++) | |
for (i=0;i<10;i++) | |
cov[r][i] = 0; | |
for (i=0;i<16;i++) | |
{ | |
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex); | |
int r = block[i*4+reorder[0]] - mu[rgn][0]; | |
int g = block[i*4+reorder[1]] - mu[rgn][1]; | |
int b = block[i*4+reorder[2]] - mu[rgn][2]; | |
int a = block[i*4+reorder[3]] - mu[rgn][3]; | |
cov[rgn][0] += r*r; | |
cov[rgn][1] += r*g; | |
cov[rgn][2] += r*b; | |
cov[rgn][3] += r*a; | |
cov[rgn][4] += g*g; | |
cov[rgn][5] += g*b; | |
cov[rgn][6] += g*a; | |
cov[rgn][7] += b*b; | |
cov[rgn][8] += b*a; | |
cov[rgn][9] += a*a; | |
} | |
if ( numChannels != 4 ) | |
{ | |
for (int r=0; r<regions; r++) | |
{ | |
cov[r][3] = 0; | |
cov[r][6] = 0; | |
cov[r][8] = 0; | |
cov[r][9] = 0; | |
} | |
} | |
// convert covariance matrix to float, find principal axis via power iter | |
for (int r=0; r<regions; r++) | |
for(i=0;i<10;i++) | |
covf[r][i] = cov[r][i] / 255.0f; | |
for (int r=0; r<regions; r++) | |
{ | |
vfr[r] = (float) (max[r][0] - min[r][0]); | |
vfg[r] = (float) (max[r][1] - min[r][1]); | |
vfb[r] = (float) (max[r][2] - min[r][2]); | |
vfa[r] = (float) (max[r][3] - min[r][3]); | |
} | |
for (int rgn=0; rgn<regions; rgn++) | |
{ | |
for(iter=0;iter<nIterPower;iter++) | |
{ | |
float r = vfr[rgn]*covf[rgn][0] + vfg[rgn]*covf[rgn][1] + vfb[rgn]*covf[rgn][2] + vfa[rgn]*covf[rgn][3]; | |
float g = vfr[rgn]*covf[rgn][1] + vfg[rgn]*covf[rgn][4] + vfb[rgn]*covf[rgn][5] + vfa[rgn]*covf[rgn][6]; | |
float b = vfr[rgn]*covf[rgn][2] + vfg[rgn]*covf[rgn][5] + vfb[rgn]*covf[rgn][7] + vfa[rgn]*covf[rgn][8]; | |
float a = vfr[rgn]*covf[rgn][3] + vfg[rgn]*covf[rgn][6] + vfb[rgn]*covf[rgn][8] + vfa[rgn]*covf[rgn][9]; | |
vfr[rgn] = r; | |
vfg[rgn] = g; | |
vfb[rgn] = b; | |
vfa[rgn] = (numChannels != 4) ? 0.f : a; | |
} | |
magn[rgn] = fabs(vfr[rgn]); | |
if (fabs(vfg[rgn]) > magn[rgn]) magn[rgn] = fabs(vfg[rgn]); | |
if (fabs(vfb[rgn]) > magn[rgn]) magn[rgn] = fabs(vfb[rgn]); | |
if (fabs(vfa[rgn]) > magn[rgn]) magn[rgn] = fabs(vfa[rgn]); | |
if(magn[rgn] < 4.0f) { // too small, default to luminance | |
v_r[rgn] = 299; // JPEG YCbCr luma coefs, scaled by 1000. | |
v_g[rgn] = 587; | |
v_b[rgn] = 114; | |
v_a[rgn] = (numChannels != 4) ? 0 : 255; | |
} else { | |
magn[rgn] = 512.0 / magn[rgn]; | |
v_r[rgn] = (int) (vfr[rgn] * magn[rgn]); | |
v_g[rgn] = (int) (vfg[rgn] * magn[rgn]); | |
v_b[rgn] = (int) (vfb[rgn] * magn[rgn]); | |
v_a[rgn] = (numChannels != 4) ? 0 : (int) (vfa[rgn] * magn[rgn]); | |
} | |
} | |
// Pick colors at extreme points | |
for(i=0;i<16;i++) | |
{ | |
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex); | |
int dot = block[i*4+reorder[0]]*v_r[rgn] + block[i*4+reorder[1]]*v_g[rgn] + block[i*4+reorder[2]]*v_b[rgn] + block[i*4+reorder[3]]*v_a[rgn]; | |
if (dot < mind[rgn]) { | |
mind[rgn] = dot; | |
minp[rgn] = block+i*4; | |
} | |
if (dot > maxd[rgn]) { | |
maxd[rgn] = dot; | |
maxp[rgn] = block+i*4; | |
} | |
} | |
for (int rgn=0; rgn<regions; rgn++) | |
{ | |
pmax32[rgn] = stb__AsNBit(maxp[rgn][reorder[0]],maxp[rgn][reorder[1]],maxp[rgn][reorder[2]],bits); | |
pmin32[rgn] = stb__AsNBit(minp[rgn][reorder[0]],minp[rgn][reorder[1]],minp[rgn][reorder[2]],bits); | |
} | |
} | |
void grabTile( unsigned char *tile, unsigned char *image, int x, int y, int w, int h, int n ) | |
{ | |
for (int oy=0; oy<4; oy++) | |
{ | |
int iy = y+oy; | |
if ( iy >= h ) | |
iy = h-1; | |
for (int ox=0; ox<4; ox++) | |
{ | |
int ix = x+ox; | |
if ( ix >= w ) | |
ix = w-1; | |
for (int c=0; c<4; c++) | |
{ | |
if ( c < n ) | |
{ | |
*tile++ = image[(iy*w+ix)*n+c]; | |
} | |
else | |
{ | |
*tile++ = 255; | |
} | |
} | |
} | |
} | |
} | |
static int stb__Lerp( int a, int b, int nom, int denom ) | |
{ | |
return a + stb__Mul8Bit(b-a, (nom*255)/denom); | |
} | |
static inline int clampi( int v, int mn, int mx ) | |
{ | |
return v<mn ? mn : v > mx ? mx : v; | |
} | |
#include <assert.h> | |
void stb__MatchIndices( int indices[16], unsigned char const interp_colours[3][8][4], int *remapindices, int numIndices, int regions, int *shapes, int shapeIndex, unsigned char const tile[4*4*4] ) | |
{ | |
int dirr[3]; | |
int dirg[3]; | |
int dirb[3]; | |
for (int rgn=0; rgn<regions; rgn++) | |
{ | |
dirr[rgn] = interp_colours[rgn][1][0] - interp_colours[rgn][0][0]; | |
dirg[rgn] = interp_colours[rgn][1][1] - interp_colours[rgn][0][1]; | |
dirb[rgn] = interp_colours[rgn][1][2] - interp_colours[rgn][0][2]; | |
} | |
int dots[16]; | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex); | |
dots[i] = tile[i*4+0]*dirr[rgn] + tile[i*4+1]*dirg[rgn] + tile[i*4+2]*dirb[rgn]; | |
} | |
int stops[3][8]; | |
for (int rgn=0; rgn<regions; rgn++) | |
{ | |
for (int i=0; i<numIndices; i++) | |
{ | |
stops[rgn][i] = interp_colours[rgn][i][0]*dirr[rgn] + interp_colours[rgn][i][1]*dirg[rgn] + interp_colours[rgn][i][2]*dirb[rgn]; | |
} | |
} | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex); | |
int totalDist = abs(stops[rgn][1] - stops[rgn][0]); | |
int dist = abs(dots[i] - stops[rgn][0]); | |
indices[i] = totalDist ? remapindices[clampi((numIndices*dist+(numIndices/2))/totalDist, 0, numIndices)] : 0;; | |
} | |
} | |
class BitPacker | |
{ | |
int bitPos; | |
unsigned char *bytes; | |
public: | |
BitPacker( void *data ) : bitPos(0), bytes( (unsigned char*)data ) | |
{ | |
} | |
inline void WriteBit( bool t ) | |
{ | |
int bytePos = bitPos / 8; | |
int bit = t ? (1<<(bitPos%8)) : 0; | |
bytes[bytePos] = (bytes[bytePos]&(~(1<<(bitPos%8)))) | bit; | |
bitPos++; | |
} | |
inline void WriteBits( unsigned int v, int num ) | |
{ | |
#if 1 | |
int bytePos = bitPos / 8; | |
while ( num ) | |
{ | |
int emptyBits = 8 - (bitPos%8); | |
int offset = (bitPos%8); | |
if ( emptyBits > num ) | |
emptyBits = num; | |
int mask = ((1<<emptyBits)-1) << offset; | |
bytes[bytePos] = (bytes[bytePos]&(~mask)) | ((v<<offset) & mask); | |
v >>= emptyBits; | |
num -= emptyBits; | |
bitPos += emptyBits; | |
bytePos++; | |
} | |
#else | |
for (int i=0; i<num; i++) | |
{ | |
WriteBit( v & (1<<i) ? true : false ); | |
} | |
#endif | |
} | |
}; | |
void stb__SwapIndices( int indices[16], int indicesBits, unsigned char interp_colours[3][8][4], int *compressed, int *shape, int regions, int shapeIndex ) | |
{ | |
int highBit = 1<<(indicesBits-1); | |
int highestIndex = (1<<(indicesBits))-1; | |
bool flip[3] = { false, false, false }; | |
bool needToFlip = false; | |
for (int rgn=0; rgn<regions; rgn++) | |
{ | |
int index = SHAPEINDEX_TO_COMPRESSED_INDICES(compressed,shapeIndex,rgn); | |
if ( indices[index] & highBit ) | |
{ | |
flip[rgn] = true; | |
needToFlip = true; | |
std::swap( interp_colours[rgn][0][0], interp_colours[rgn][1][0] ); | |
std::swap( interp_colours[rgn][0][1], interp_colours[rgn][1][1] ); | |
std::swap( interp_colours[rgn][0][2], interp_colours[rgn][1][2] ); | |
std::swap( interp_colours[rgn][0][3], interp_colours[rgn][1][3] ); | |
} | |
} | |
if ( needToFlip ) | |
{ | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(shape,(i%4),(i/4),shapeIndex); | |
if ( flip[rgn] ) | |
{ | |
indices[i] = highestIndex - indices[i]; | |
} | |
} | |
} | |
} | |
void compress_mode0( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex ) | |
{ | |
unsigned int pmax32[3]; | |
unsigned int pmin32[3]; | |
int reorder[] = { 0, 1, 2, 3 }; | |
stb__OptimizeColorsBlock( tile, pmax32, pmin32, shapes_three, shapeIndex, 3, 4, reorder, 3 ); | |
unsigned char interp_colours[3][8][4]; | |
stb__FromNBit( interp_colours[0][0], pmax32[0], 4 ); | |
stb__FromNBit( interp_colours[1][0], pmax32[1], 4 ); | |
stb__FromNBit( interp_colours[2][0], pmax32[2], 4 ); | |
stb__FromNBit( interp_colours[0][1], pmin32[0], 4 ); | |
stb__FromNBit( interp_colours[1][1], pmin32[1], 4 ); | |
stb__FromNBit( interp_colours[2][1], pmin32[2], 4 ); | |
for (int r=0; r<3; r++) | |
{ | |
for (int i=0; i<6; i++) | |
{ | |
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, 7 ); | |
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, 7 ); | |
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, 7 ); | |
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, 7 ); | |
} | |
} | |
int indices[16]; | |
int remapindices[8] = { 0, 2, 3, 4, 5, 6, 7, 1 }; | |
stb__MatchIndices( indices, interp_colours, remapindices, 8, 3, shapes_three, shapeIndex, tile ); | |
stb__SwapIndices( indices, 3, interp_colours, shapeindex_to_compressed_indices_3, shapes_three, 3, shapeIndex ); | |
BitPacker packer( output ); | |
packer.WriteBit( true ); // mode 0 | |
packer.WriteBits( shapeIndex, 4 ); // shape | |
// r | |
packer.WriteBits( interp_colours[0][0][0]>>4, 4 ); | |
packer.WriteBits( interp_colours[0][1][0]>>4, 4 ); | |
packer.WriteBits( interp_colours[1][0][0]>>4, 4 ); | |
packer.WriteBits( interp_colours[1][1][0]>>4, 4 ); | |
packer.WriteBits( interp_colours[2][0][0]>>4, 4 ); | |
packer.WriteBits( interp_colours[2][1][0]>>4, 4 ); | |
// g | |
packer.WriteBits( interp_colours[0][0][1]>>4, 4 ); | |
packer.WriteBits( interp_colours[0][1][1]>>4, 4 ); | |
packer.WriteBits( interp_colours[1][0][1]>>4, 4 ); | |
packer.WriteBits( interp_colours[1][1][1]>>4, 4 ); | |
packer.WriteBits( interp_colours[2][0][1]>>4, 4 ); | |
packer.WriteBits( interp_colours[2][1][1]>>4, 4 ); | |
// b | |
packer.WriteBits( interp_colours[0][0][2]>>4, 4 ); | |
packer.WriteBits( interp_colours[0][1][2]>>4, 4 ); | |
packer.WriteBits( interp_colours[1][0][2]>>4, 4 ); | |
packer.WriteBits( interp_colours[1][1][2]>>4, 4 ); | |
packer.WriteBits( interp_colours[2][0][2]>>4, 4 ); | |
packer.WriteBits( interp_colours[2][1][2]>>4, 4 ); | |
// last bits | |
packer.WriteBits( 0, 6 ); | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(shapes_three,(i%4),(i/4),0); | |
bool first = false; | |
for (int j=0; j<3; j++) | |
{ | |
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(shapeindex_to_compressed_indices_3,shapeIndex,j) == i); | |
} | |
packer.WriteBits( indices[i], first ? 2 : 3 ); | |
} | |
} | |
void compress_mode1( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex ) | |
{ | |
unsigned int pmax32[3]; | |
unsigned int pmin32[3]; | |
int reorder[] = { 0, 1, 2, 3 }; | |
stb__OptimizeColorsBlock( tile, pmax32, pmin32, shapes_two, shapeIndex, 2, 6, reorder, 3 ); | |
unsigned char interp_colours[3][8][4]; | |
stb__FromNBit( interp_colours[0][0], pmax32[0], 6 ); | |
stb__FromNBit( interp_colours[1][0], pmax32[1], 6 ); | |
stb__FromNBit( interp_colours[0][1], pmin32[0], 6 ); | |
stb__FromNBit( interp_colours[1][1], pmin32[1], 6 ); | |
for (int r=0; r<2; r++) | |
{ | |
for (int i=0; i<6; i++) | |
{ | |
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, 7 ); | |
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, 7 ); | |
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, 7 ); | |
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, 7 ); | |
} | |
} | |
int indices[16]; | |
int remapindices[8] = { 0, 2, 3, 4, 5, 6, 7, 1 }; | |
stb__MatchIndices( indices, interp_colours, remapindices, 8, 2, shapes_two, shapeIndex, tile ); | |
stb__SwapIndices( indices, 3, interp_colours, shapeindex_to_compressed_indices_2, shapes_two, 2, shapeIndex ); | |
BitPacker packer( output ); | |
packer.WriteBit( false ); | |
packer.WriteBit( true ); // mode 01 | |
packer.WriteBits( shapeIndex, 6 ); // shape | |
// r | |
packer.WriteBits( interp_colours[0][0][0]>>2, 6 ); | |
packer.WriteBits( interp_colours[0][1][0]>>2, 6 ); | |
packer.WriteBits( interp_colours[1][0][0]>>2, 6 ); | |
packer.WriteBits( interp_colours[1][1][0]>>2, 6 ); | |
// g | |
packer.WriteBits( interp_colours[0][0][1]>>2, 6 ); | |
packer.WriteBits( interp_colours[0][1][1]>>2, 6 ); | |
packer.WriteBits( interp_colours[1][0][1]>>2, 6 ); | |
packer.WriteBits( interp_colours[1][1][1]>>2, 6 ); | |
// b | |
packer.WriteBits( interp_colours[0][0][2]>>2, 6 ); | |
packer.WriteBits( interp_colours[0][1][2]>>2, 6 ); | |
packer.WriteBits( interp_colours[1][0][2]>>2, 6 ); | |
packer.WriteBits( interp_colours[1][1][2]>>2, 6 ); | |
// last bits | |
packer.WriteBits( 0, 2 ); | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(shapes_two,(i%4),(i/4),0); | |
bool first = false; | |
for (int j=0; j<2; j++) | |
{ | |
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(shapeindex_to_compressed_indices_2,shapeIndex,j) == i); | |
} | |
packer.WriteBits( indices[i], first ? 2 : 3 ); | |
} | |
} | |
void compress_mode2( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex ) | |
{ | |
unsigned int pmax32[3]; | |
unsigned int pmin32[3]; | |
int reorder[] = { 0, 1, 2, 3 }; | |
stb__OptimizeColorsBlock( tile, pmax32, pmin32, shapes_three, shapeIndex, 3, 5, reorder, 3 ); | |
unsigned char interp_colours[3][8][4]; | |
stb__FromNBit( interp_colours[0][0], pmax32[0], 5 ); | |
stb__FromNBit( interp_colours[1][0], pmax32[1], 5 ); | |
stb__FromNBit( interp_colours[2][0], pmax32[2], 5 ); | |
stb__FromNBit( interp_colours[0][1], pmin32[0], 5 ); | |
stb__FromNBit( interp_colours[1][1], pmin32[1], 5 ); | |
stb__FromNBit( interp_colours[2][1], pmin32[2], 5 ); | |
for (int r=0; r<2; r++) | |
{ | |
for (int i=0; i<2; i++) | |
{ | |
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, 3 ); | |
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, 3 ); | |
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, 3 ); | |
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, 3 ); | |
} | |
} | |
int indices[16]; | |
int remapindices[4] = { 0, 2, 3, 1 }; | |
stb__MatchIndices( indices, interp_colours, remapindices, 4, 3, shapes_three, shapeIndex, tile ); | |
stb__SwapIndices( indices, 2, interp_colours, shapeindex_to_compressed_indices_3, shapes_three, 3, shapeIndex ); | |
BitPacker packer( output ); | |
packer.WriteBit( false ); | |
packer.WriteBit( false ); | |
packer.WriteBit( true ); // mode 001 | |
packer.WriteBits( shapeIndex, 6 ); // shape | |
// r | |
packer.WriteBits( interp_colours[0][0][0]>>2, 5 ); | |
packer.WriteBits( interp_colours[0][1][0]>>2, 5 ); | |
packer.WriteBits( interp_colours[1][0][0]>>2, 5 ); | |
packer.WriteBits( interp_colours[1][1][0]>>2, 5 ); | |
packer.WriteBits( interp_colours[2][0][0]>>2, 5 ); | |
packer.WriteBits( interp_colours[2][1][0]>>2, 5 ); | |
// g | |
packer.WriteBits( interp_colours[0][0][1]>>2, 5 ); | |
packer.WriteBits( interp_colours[0][1][1]>>2, 5 ); | |
packer.WriteBits( interp_colours[1][0][1]>>2, 5 ); | |
packer.WriteBits( interp_colours[1][1][1]>>2, 5 ); | |
packer.WriteBits( interp_colours[2][0][1]>>2, 5 ); | |
packer.WriteBits( interp_colours[2][1][1]>>2, 5 ); | |
// b | |
packer.WriteBits( interp_colours[0][0][2]>>2, 5 ); | |
packer.WriteBits( interp_colours[0][1][2]>>2, 5 ); | |
packer.WriteBits( interp_colours[1][0][2]>>2, 5 ); | |
packer.WriteBits( interp_colours[1][1][2]>>2, 5 ); | |
packer.WriteBits( interp_colours[2][0][2]>>2, 5 ); | |
packer.WriteBits( interp_colours[2][1][2]>>2, 5 ); | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(shapes_three,(i%4),(i/4),0); | |
bool first = false; | |
for (int j=0; j<3; j++) | |
{ | |
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(shapeindex_to_compressed_indices_3,shapeIndex,j) == i); | |
} | |
packer.WriteBits( indices[i], first ? 1 : 2 ); | |
} | |
} | |
struct compress_info | |
{ | |
int block; | |
int blockBits; | |
int *shape; | |
int *shapeindex_to_compressed_indices; | |
int numShapes; | |
int shapeBits; | |
int numPbits; | |
int endPointBits; | |
int indexBits; | |
}; | |
void compress_mode_generic( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex, compress_info *info ) | |
{ | |
unsigned int pmax32[3]; | |
unsigned int pmin32[3]; | |
int reorder[] = { 0, 1, 2, 3 }; | |
stb__OptimizeColorsBlock( tile, pmax32, pmin32, info->shape, shapeIndex, info->numShapes, info->endPointBits, reorder, 3 ); | |
unsigned char interp_colours[3][8][4]; | |
for (int i=0; i<info->numShapes; i++) | |
{ | |
stb__FromNBit( interp_colours[i][0], pmax32[i], info->endPointBits ); | |
stb__FromNBit( interp_colours[i][1], pmin32[i], info->endPointBits ); | |
} | |
int numIndices = 1<<info->indexBits; | |
for (int r=0; r<info->numShapes; r++) | |
{ | |
for (int i=0; i<numIndices; i++) | |
{ | |
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, numIndices ); | |
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, numIndices ); | |
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, numIndices ); | |
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, numIndices ); | |
} | |
} | |
int indices[16]; | |
int remapindices_2[8] = { 0, 2, 3, 1 }; | |
int remapindices_3[8] = { 0, 2, 3, 4, 5, 6, 7, 1 }; | |
int *remapindices = NULL; | |
if ( numIndices == 2 ) | |
remapindices = remapindices_2; | |
if ( numIndices == 3 ) | |
remapindices = remapindices_3; | |
stb__MatchIndices( indices, interp_colours, remapindices, numIndices, info->numShapes, info->shape, shapeIndex, tile ); | |
stb__SwapIndices( indices, info->indexBits, interp_colours, info->shapeindex_to_compressed_indices, info->shape, info->numShapes, shapeIndex ); | |
BitPacker packer( output ); | |
packer.WriteBits( info->block, info->blockBits ); // mode | |
packer.WriteBits( shapeIndex, info->shapeBits ); // shape | |
// r | |
for (int r=0; r<info->numShapes; r++) | |
{ | |
packer.WriteBits( interp_colours[r][0][0]>>(8-info->endPointBits), info->endPointBits ); | |
packer.WriteBits( interp_colours[r][1][0]>>(8-info->endPointBits), info->endPointBits ); | |
} | |
// g | |
for (int r=0; r<info->numShapes; r++) | |
{ | |
packer.WriteBits( interp_colours[r][0][1]>>(8-info->endPointBits), info->endPointBits ); | |
packer.WriteBits( interp_colours[r][1][1]>>(8-info->endPointBits), info->endPointBits ); | |
} | |
// b | |
for (int r=0; r<info->numShapes; r++) | |
{ | |
packer.WriteBits( interp_colours[r][0][2]>>(8-info->endPointBits), info->endPointBits ); | |
packer.WriteBits( interp_colours[r][1][2]>>(8-info->endPointBits), info->endPointBits ); | |
} | |
// last bits | |
if ( info->numPbits ) | |
packer.WriteBits( 0, info->numPbits ); | |
for (int i=0; i<16; i++) | |
{ | |
int rgn = REGION(info->shape,(i%4),(i/4),0); | |
bool first = false; | |
for (int j=0; j<info->numShapes; j++) | |
{ | |
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(info->shapeindex_to_compressed_indices,shapeIndex,j) == i); | |
} | |
packer.WriteBits( indices[i], first ? (info->indexBits-1) : info->indexBits ); | |
} | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
int w,h,n; | |
unsigned char *data = stbi_load("hun-dirt-color_input.png", &w, &h, &n, 0); | |
int mips = 1; | |
int format = 0; | |
FILE *f = fopen( "c:\\bc7.tex", "wb" ); | |
fwrite( &w, 4, 1, f ); | |
fwrite( &h, 4, 1, f ); | |
fwrite( &mips, 4, 1, f ); | |
fwrite( &format, 4, 1, f ); | |
unsigned char *blocks = (unsigned char*)malloc( (w/4) * (h/4) * 16 ); | |
unsigned char *blocks_cursor = blocks; | |
crnlib::timer t; | |
t.start(); | |
for (int y=0; y<h; y+=4) | |
{ | |
for (int x=0; x<w; x+=4) | |
{ | |
unsigned char tile[4*4*4]; | |
grabTile( tile, data, x, y, w, h, n ); | |
if ( format == 0 ) | |
{ | |
compress_mode3( blocks_cursor, tile, 1 ); | |
blocks_cursor+=16; | |
} | |
else | |
{ | |
stb_compress_dxt_block( blocks_cursor, tile, 0, 0 ); | |
blocks_cursor+=8; | |
} | |
} | |
} | |
t.stop(); | |
int ms = t.get_elapsed_ms(); | |
fwrite( blocks, (w/4) * (h/4) * (format == 0 ? 16 : 8), 1, f ); | |
fclose( f ); | |
printf( "%d\n", ms ); | |
// 1 | |
// 16 + 64 + 64 + 64 + 8 + 4 + 1 + 64 = 285 | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// opengex.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <vector> | |
#include <list> | |
#include <string> | |
#include <map> | |
#include <assert.h> | |
#include "lexer.h" | |
//#include "stb_c_lexer.h" | |
struct structure | |
{ | |
LexerToken name; | |
virtual ~structure() {} | |
}; | |
struct datatype : public structure | |
{ | |
int stride; | |
}; | |
template <class T> | |
struct typeddatatype : public datatype | |
{ | |
std::vector<T> items; | |
}; | |
struct prop | |
{ | |
//std::string ident; | |
LexerToken ident; | |
virtual ~prop() {} | |
}; | |
template <class T> | |
struct typedprop : public prop | |
{ | |
T data; | |
}; | |
struct identifier : public structure | |
{ | |
LexerToken ident; | |
// std::string ident; | |
std::vector< prop* > props; | |
std::vector< structure* > children; | |
}; | |
struct reflink | |
{ | |
LexerToken name; | |
//std::string name; | |
structure *ref; | |
}; | |
void readtextfile( std::string &out, const std::string &filename ) | |
{ | |
FILE *f = fopen( filename.c_str(), "rb" ); | |
if ( !f ) | |
return; | |
fseek( f, 0, SEEK_END ); | |
int len = ftell( f ); | |
fseek( f, 0, SEEK_SET ); | |
out.resize( len ); | |
fread( &out[0], 1, len, f ); | |
fclose( f ); | |
} | |
#if 0 | |
void skipws( std::string const &script, std::string::size_type &cursor ) | |
{ | |
cursor = script.find_first_not_of( " \t\n\r", cursor ); | |
} | |
void skiplinecomment( std::string const &script, std::string::size_type &cursor ) | |
{ | |
cursor = script.find_first_of( "\n", cursor ); | |
} | |
void skipmultilinecomment( std::string const &script, std::string::size_type &cursor ) | |
{ | |
cursor = script.find( "*/", cursor ); | |
if ( cursor != std::string::npos ) | |
cursor += 2; | |
if ( cursor >= script.size() ) | |
cursor = std::string::npos; | |
} | |
std::string getquotedstring( std::string const &script, std::string::size_type &cursor ) | |
{ | |
std::string::size_type start = cursor; | |
cursor++; | |
if ( cursor >= script.size() ) | |
{ | |
cursor = std::string::npos; | |
return ""; | |
} | |
while ( 1 ) | |
{ | |
cursor = script.find_first_of( '\"', cursor ); | |
if ( cursor == std::string::npos ) | |
{ | |
return script.substr( start ); | |
} | |
if ( cursor && script[cursor-1]=='\\' ) | |
{ | |
cursor++; | |
if ( cursor >= script.size() ) | |
{ | |
cursor = std::string::npos; | |
return ""; | |
} | |
continue; | |
} | |
cursor++; | |
if ( cursor >= script.size() ) | |
cursor = std::string::npos; | |
if ( cursor == std::string::npos ) | |
return script.substr( start ); | |
else | |
return script.substr( start, cursor - start ); | |
} | |
} | |
const char *s_SpecialMultiTokens[] = | |
{ | |
"===", "==", | |
"!==", "!=", | |
"<<=", "<=" | |
">>=", ">=", | |
"&&", "&=", | |
"|=", "||", | |
"^=", | |
"[[", | |
"]]", | |
NULL | |
}; | |
int getspecialtoken( std::string const &script, std::string::size_type &cursor ) | |
{ | |
if ( script[cursor] == '+' && (script[cursor+1] == '.' || (script[cursor+1] >= '0' && script[cursor+1]<='9')) ) | |
{ | |
std::string::size_type end = script.find_first_not_of( "+.0123456789", cursor ); | |
if ( script[end]=='e' ) | |
{ | |
end = script.find_first_not_of( "-+0123456789", end+1 ); | |
} | |
return end - cursor; | |
} | |
if ( script[cursor] == '-' && (script[cursor+1] == '.' || (script[cursor+1] >= '0' && script[cursor+1]<='9')) ) | |
{ | |
std::string::size_type end = script.find_first_not_of( "-.0123456789", cursor ); | |
if ( script[end]=='e' ) | |
{ | |
end = script.find_first_not_of( "-+0123456789", end+1 ); | |
} | |
return end - cursor; | |
} | |
if ( script[cursor] >= '0' && script[cursor]<='9' ) | |
{ | |
std::string::size_type end = script.find_first_not_of( "-.0123456789", cursor ); | |
if ( script[end]=='e' ) | |
{ | |
end = script.find_first_not_of( "-+0123456789", end+1 ); | |
} | |
return end - cursor; | |
} | |
for ( int item = 0; s_SpecialMultiTokens[item]; item++ ) | |
{ | |
const char *special = s_SpecialMultiTokens[item]; | |
std::string::size_type cur = cursor; | |
int len = 0; | |
while ( *special ) | |
{ | |
if ( *special != script[cur] ) | |
{ | |
len = 0; | |
break; | |
} | |
cur++; | |
if ( cur >= script.size() ) | |
{ | |
len = 0; | |
break; | |
} | |
len++; | |
special++; | |
} | |
if ( len ) | |
return len; | |
} | |
return 1; | |
} | |
std::string gettoken( std::string const &script, std::string::size_type &cursor ) | |
{ | |
while ( 1 ) | |
{ | |
if ( cursor == std::string::npos ) | |
return ""; | |
skipws( script, cursor ); | |
if ( cursor == std::string::npos ) | |
return ""; | |
if ( cursor < (script.size()-1) ) | |
{ | |
if ( script[cursor] == '/' && script[cursor+1] == '/' ) | |
{ | |
skiplinecomment( script, cursor ); | |
continue; | |
} | |
else | |
if ( script[cursor] == '/' && script[cursor+1] == '*' ) | |
{ | |
skipmultilinecomment( script, cursor ); | |
continue; | |
} | |
} | |
if ( script[cursor] == '\"' ) | |
{ | |
return getquotedstring( script, cursor ); | |
} | |
std::string::size_type end = script.find_first_of( "^&!<>()[]{};,*+=-/\"' \t\n\r", cursor ); | |
if ( end == cursor ) | |
{ | |
if ( (cursor+1) >= script.size() ) | |
{ | |
cursor = std::string::npos; | |
return std::string( 1, script[end] ); | |
} | |
else | |
{ | |
int l = getspecialtoken( script, cursor ); | |
cursor += l; | |
if ( cursor >= script.size() ) | |
cursor = std::string::npos; | |
return script.substr( end, l ); | |
} | |
} | |
std::string::size_type start = cursor; | |
if ( script[start] >= '0' && script[start] <= '9' ) | |
{ | |
if ( script[end-1] == 'e' ) | |
{ | |
end = script.find_first_not_of( "-+0123456789", end ); | |
printf(""); | |
} | |
} | |
cursor = end; | |
if ( end == std::string::npos ) | |
return script.substr( start ); | |
else | |
return script.substr( start, end - start ); | |
} | |
} | |
#if 0 | |
static std::string tostring(stb_lexer *lexer) | |
{ | |
char tempbuffer[256]; | |
switch (lexer->token) { | |
case CLEX_id : return lexer->string; break; | |
case CLEX_eq : return "=="; break; | |
case CLEX_noteq : return "!="; break; | |
case CLEX_lesseq : return "<="; break; | |
case CLEX_greatereq : return ">="; break; | |
case CLEX_andand : return "&&"; break; | |
case CLEX_oror : return "||"; break; | |
case CLEX_shl : return "<<"; break; | |
case CLEX_shr : return ">>"; break; | |
case CLEX_plusplus : return "++"; break; | |
case CLEX_minusminus: return "--"; break; | |
case CLEX_arrow : return "->"; break; | |
case CLEX_andeq : return "&="; break; | |
case CLEX_oreq : return "|="; break; | |
case CLEX_xoreq : return "^="; break; | |
case CLEX_pluseq : return "+="; break; | |
case CLEX_minuseq : return "-="; break; | |
case CLEX_muleq : return "*="; break; | |
case CLEX_diveq : return "/="; break; | |
case CLEX_modeq : return "%%="; break; | |
case CLEX_shleq : return "<<="; break; | |
case CLEX_shreq : return ">>="; break; | |
case CLEX_eqarrow : return "=>"; break; | |
case CLEX_dqstring : return std::string("\"") + lexer->string + std::string("\""); break; | |
case CLEX_sqstring : return std::string("'") + lexer->string + std::string("'"); break; | |
case CLEX_charlit : return std::string("'") + lexer->string + std::string("'"); break; | |
case CLEX_intlit : { sprintf(tempbuffer,"%ld", lexer->int_number); return tempbuffer; } break; | |
case CLEX_floatlit : { sprintf(tempbuffer,"%g", lexer->real_number); return tempbuffer; } break; | |
default: | |
if (lexer->token >= 0 && lexer->token < 256) | |
{ | |
tempbuffer[0] = lexer->token; | |
tempbuffer[1] = 0; | |
return tempbuffer; | |
} | |
else { | |
printf("<<<UNKNOWN TOKEN %ld >>>\n", lexer->token); | |
} | |
break; | |
} | |
return ""; | |
} | |
#endif | |
#endif | |
struct ParseInfo | |
{ | |
std::string const &script; | |
std::string::size_type cursor; | |
//int tokenType; | |
std::string token; | |
LexerToken tok; | |
//stb_lexer lexer; | |
//char string_store[16*1024]; | |
LexerState lex; | |
ParseInfo( std::string const &s, std::string::size_type c = 0 ) : script(s), cursor(c) | |
{ | |
lex.cursor = script.c_str(); | |
lex.text = script.c_str(); | |
lex.end = script.c_str() + script.length(); | |
//stb_c_lexer_init(&lexer, s.c_str(), s.c_str()+s.size(), string_store, sizeof(string_store)); | |
} | |
void GetSym() | |
{ | |
if ( lexerGetToken( &tok, &lex ) == LS_OK ) | |
{ | |
token.assign( tok.start, tok.length ); | |
} | |
else | |
{ | |
tok.start=""; | |
token = ""; | |
} | |
} | |
bool Accept(std::string const & s) | |
{ | |
if (s == token) | |
{ | |
GetSym(); | |
return true; | |
} | |
return false; | |
} | |
bool Expect(std::string const & s) | |
{ | |
if (Accept(s)) | |
return 1; | |
int line = 0; | |
std::string::size_type p = 0; | |
while ( p < cursor ) | |
{ | |
line += (script[p] == '\n') ? 1 : 0; | |
p++; | |
} | |
line = lexerGetLineNumber( &lex ); | |
assert( 0 ); | |
//error("expect: unexpected symbol"); | |
return 0; | |
} | |
void Token( std::string &str ) | |
{ | |
std::swap( str, token ); | |
GetSym(); | |
} | |
void Token( LexerToken &t ) | |
{ | |
t = tok; | |
GetSym(); | |
} | |
int TokenAtoi() | |
{ | |
int i = tok.i; | |
GetSym(); | |
return i; | |
} | |
float TokenAtof() | |
{ | |
float f = tok.f; | |
GetSym(); | |
return f; | |
} | |
bool End() | |
{ | |
return lexerIsEof( &lex );//cursor == std::string::npos || cursor >= script.size();//tokenType == CLEX_eof; | |
} | |
}; | |
template <class T> | |
bool ParseDecimalLiteral( T &i, std::string const &v, int ofs = 0 ) | |
{ | |
i = 0; | |
for (unsigned int j=ofs; j<v.size(); j++) | |
{ | |
i*=T(10); | |
if ( v[j]>='0' && v[j]<='9' ) | |
i+=v[j]-'0'; | |
else | |
return false; | |
} | |
return true; | |
} | |
template <class T> | |
bool ParseHexLiteral( T &i, std::string const &v ) | |
{ | |
if ( v.size() < 2 || !(v[0] != '0' && (v[1] != 'x' || v[1] != 'X')) ) | |
return false; | |
i = 0; | |
for (unsigned int j=2; j<v.size(); j++) | |
{ | |
i*=T(2); | |
if ( v[j]>='0' && v[j]<='9' ) | |
{ | |
i+=v[j]-'0'; | |
} else | |
if ( v[j]>='a' && v[j]<='f' ) | |
{ | |
i+=(v[j]-'a')+10; | |
} else | |
if ( v[j]>='A' && v[j]<='F' ) | |
{ | |
i+=(v[j]-'A')+10; | |
} else | |
return false; | |
} | |
return true; | |
} | |
template <class T> | |
bool ParseBinaryLiteral( T &i, std::string const &v ) | |
{ | |
if ( v.size() < 2 || !(v[0] != '0' && (v[1] != 'c' || v[1] != 'B')) ) | |
return false; | |
i = 0; | |
for (unsigned int j=2; j<v.size(); j++) | |
{ | |
i*=T(2); | |
if ( v[j]>='0' && v[j]<='1' ) | |
{ | |
i+=v[j]-'0'; | |
} else | |
return false; | |
} | |
return true; | |
} | |
template <class T> | |
bool ParseCharLiteral( T &i, std::string const &v ) | |
{ | |
if ( v.size() < 2 || !(v[0] != '\'') ) | |
return false; | |
i = 0; | |
assert(0); | |
return true; | |
} | |
template <class T> | |
bool ParseIntegerLiteral( T&i, std::string const &v ) | |
{ | |
bool negate = (v[0] == '-'); | |
int ofs = 0; | |
if ( v[0] == '+' || v[0] == '-' ) | |
ofs++; | |
if ( ParseDecimalLiteral<T>( i, v, ofs ) || | |
ParseHexLiteral<T>( i, v ) || | |
ParseBinaryLiteral<T>( i, v ) || | |
ParseCharLiteral<T>( i, v ) ) | |
{ | |
return true; | |
} | |
return false; | |
} | |
bool ParseBoolLiteral( bool &i, std::string const &v ) | |
{ | |
if ( v == "true" ) | |
{ | |
i=true; | |
return true; | |
} | |
if ( v == "false" ) | |
{ | |
i=false; | |
return true; | |
} | |
return false; | |
} | |
bool ParseFloatLiteral( float &i, std::string const &v ) | |
{ | |
if ( v == "true" ) | |
{ | |
i=true; | |
return true; | |
} | |
if ( v == "false" ) | |
{ | |
i=false; | |
return true; | |
} | |
return false; | |
} | |
template <class T> | |
struct ParseTypeHelper | |
{ | |
bool operator()( T &item, ParseInfo &pinfo ); | |
}; | |
template <> | |
struct ParseTypeHelper<bool> | |
{ | |
bool operator()( bool &item, ParseInfo &pinfo ) | |
{ | |
if ( pinfo.Accept( "true" ) ) | |
{ | |
item = true; | |
} | |
else if ( pinfo.Accept( "false" ) ) | |
{ | |
item = false; | |
} | |
else | |
assert(0); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<char> | |
{ | |
bool operator()( char &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<short> | |
{ | |
bool operator()( short &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<int> | |
{ | |
bool operator()( int &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<__int64> | |
{ | |
bool operator()( __int64 &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<unsigned char> | |
{ | |
bool operator()( unsigned char &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<unsigned short> | |
{ | |
bool operator()( unsigned short &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<unsigned int> | |
{ | |
bool operator()( unsigned int &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<unsigned __int64> | |
{ | |
bool operator()( unsigned __int64 &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtoi(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<float> | |
{ | |
bool operator()( float &item, ParseInfo &pinfo ) | |
{ | |
if ( pinfo.token.size() >= 2 && pinfo.token[0] == '0' && (pinfo.token[1] == 'x' || pinfo.token[1] == 'X') ) | |
{ | |
union | |
{ | |
float f; | |
unsigned int i; | |
} conv; | |
conv.i = pinfo.TokenAtoi(); | |
item = conv.f; | |
} | |
else | |
if ( pinfo.token.size() >= 2 && pinfo.token[0] == '0' && (pinfo.token[1] == 'b' || pinfo.token[1] == 'B') ) | |
{ | |
union | |
{ | |
float f; | |
unsigned int i; | |
} conv; | |
conv.i = pinfo.TokenAtoi(); | |
item = conv.f; | |
} | |
else | |
{ | |
item = (float)pinfo.TokenAtof(); | |
} | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<double> | |
{ | |
bool operator()( double &item, ParseInfo &pinfo ) | |
{ | |
item = pinfo.TokenAtof(); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<std::string> | |
{ | |
bool operator()( std::string &item, ParseInfo &pinfo ) | |
{ | |
pinfo.Token( item ); | |
return true; | |
} | |
}; | |
template <> | |
struct ParseTypeHelper<reflink> | |
{ | |
bool operator()( reflink &item, ParseInfo &pinfo ) | |
{ | |
pinfo.Token( item.name ); | |
item.ref = NULL; | |
return true; | |
} | |
}; | |
template<class T> | |
void ParseType( std::vector<T> &out, ParseInfo &pinfo, int stride ) | |
{ | |
ParseTypeHelper<T> helper; | |
T item; | |
helper( item, pinfo ); | |
out.push_back( item ); | |
for (int i=1; i<stride; i++) | |
{ | |
pinfo.Expect(","); | |
helper( item, pinfo ); | |
out.push_back( item ); | |
} | |
} | |
template<class T> | |
structure *ParseTypedDataType( ParseInfo &pinfo ) | |
{ | |
typeddatatype<T> *dataType = new typeddatatype<T>; | |
dataType->stride = 1; | |
if ( pinfo.Accept( "[" ) ) | |
{ | |
dataType->stride = pinfo.TokenAtoi(); | |
pinfo.Expect( "]" ); | |
} | |
if ( !pinfo.Accept( "{" ) ) | |
{ | |
pinfo.Token( dataType->name ); | |
pinfo.Expect( "{" ); | |
} | |
if ( dataType->stride > 1 ) | |
{ | |
pinfo.Expect( "{" ); | |
ParseType( dataType->items, pinfo, dataType->stride ); | |
pinfo.Expect( "}" ); | |
while ( pinfo.Accept( "," ) ) | |
{ | |
pinfo.Expect( "{" ); | |
ParseType( dataType->items, pinfo, dataType->stride ); | |
pinfo.Expect( "}" ); | |
} | |
} | |
else | |
{ | |
ParseType( dataType->items, pinfo, dataType->stride ); | |
while ( pinfo.Accept( "," ) ) | |
{ | |
ParseType( dataType->items, pinfo, dataType->stride ); | |
} | |
} | |
pinfo.Expect( "}" ); | |
return dataType; | |
} | |
structure *ParseDataType( ParseInfo &pinfo ) | |
{ | |
if ( pinfo.Accept( "bool" ) ) | |
{ | |
return ParseTypedDataType<bool>( pinfo ); | |
} else | |
if ( pinfo.Accept( "int8" ) ) | |
{ | |
return ParseTypedDataType<char>( pinfo ); | |
} else | |
if ( pinfo.Accept( "int16" ) ) | |
{ | |
return ParseTypedDataType<short>( pinfo ); | |
} else | |
if ( pinfo.Accept( "int32" ) ) | |
{ | |
return ParseTypedDataType<int>( pinfo ); | |
} else | |
if ( pinfo.Accept( "int64" ) ) | |
{ | |
return ParseTypedDataType<__int64>( pinfo ); | |
} else | |
if ( pinfo.Accept( "unsigned_int8" ) ) | |
{ | |
return ParseTypedDataType<unsigned char>( pinfo ); | |
} else | |
if ( pinfo.Accept( "unsigned_int16" ) ) | |
{ | |
return ParseTypedDataType<unsigned char>( pinfo ); | |
} else | |
if ( pinfo.Accept( "unsigned_int32" ) ) | |
{ | |
return ParseTypedDataType<unsigned char>( pinfo ); | |
} else | |
if ( pinfo.Accept( "unsigned_int64" ) ) | |
{ | |
return ParseTypedDataType<unsigned char>( pinfo ); | |
} else | |
if ( pinfo.Accept( "float" ) ) | |
{ | |
return ParseTypedDataType<float>( pinfo ); | |
} else | |
if ( pinfo.Accept( "double" ) ) | |
{ | |
return ParseTypedDataType<double>( pinfo ); | |
} else | |
if ( pinfo.Accept( "string" ) ) | |
{ | |
return ParseTypedDataType<std::string>( pinfo ); | |
} else | |
if ( pinfo.Accept( "ref" ) ) | |
{ | |
return ParseTypedDataType<reflink>( pinfo ); | |
} else | |
{ | |
return NULL; | |
} | |
} | |
prop *ParseProperty( ParseInfo &pinfo ) | |
{ | |
//std::string id; | |
LexerToken id; | |
pinfo.Token( id ); | |
pinfo.Expect( "=" ); | |
LexerToken val; | |
pinfo.Token( val ); | |
if ( strncmp( val.start, "true", val.length ) == 0 )//== "true" || val == "false" ) | |
{ | |
typedprop<bool> *p = new typedprop<bool>; | |
p->ident = id; | |
p->data = true; | |
return p; | |
} else | |
if ( strncmp( val.start, "false", val.length ) == 0 )//== "true" || val == "false" ) | |
{ | |
typedprop<bool> *p = new typedprop<bool>; | |
p->ident = id; | |
p->data = false; | |
return p; | |
} else | |
if ( val.start[0] == '%' || val.start[0] == '$' ) | |
{ | |
typedprop<reflink> *p = new typedprop<reflink>; | |
p->ident = id; | |
p->data.name = val; | |
return p; | |
} else | |
if ( val.type == LT_Float ) //val.find( '.' ) != std::string::npos && val.find_first_not_of( "0123456789.-" ) == std::string::npos ) | |
{ | |
typedprop<float> *p = new typedprop<float>; | |
p->ident = id; | |
p->data = val.f;//(float)atof(val.c_str()); | |
return p; | |
} else | |
if ( val.type == LT_Int )//val.find_first_not_of( "-0123456789" ) == std::string::npos ) | |
{ | |
typedprop<int> *p = new typedprop<int>; | |
p->ident = id; | |
p->data = val.i;//atoi(val.c_str()); | |
return p; | |
} | |
structure *s = ParseDataType( pinfo ); | |
if ( s ) | |
{ | |
typedprop<structure*> *p = new typedprop<structure*>; | |
p->ident = id; | |
p->data = s; | |
return p; | |
} | |
else | |
{ | |
//typedprop<std::string> *p = new typedprop<std::string>; | |
typedprop<LexerToken> *p = new typedprop<LexerToken>; | |
p->ident = id; | |
p->data = val; | |
return p; | |
} | |
assert(0); | |
return NULL; | |
} | |
structure *ParseStructure( ParseInfo &pinfo ); | |
structure *ParseIdentifier( ParseInfo &pinfo ) | |
{ | |
identifier *id = new identifier; | |
pinfo.Token( id->ident ); | |
id->name.start = NULL; | |
if ( pinfo.token[0] == '$' ) | |
{ | |
pinfo.Token(id->name); | |
} else | |
if ( pinfo.token[0] == '%' ) | |
{ | |
pinfo.Token(id->name); | |
} | |
if ( pinfo.Accept( "(" ) ) | |
{ | |
if ( !pinfo.Accept( ")" ) ) | |
{ | |
id->props.push_back( ParseProperty( pinfo ) ); | |
while ( pinfo.Accept( "," ) ) | |
{ | |
id->props.push_back( ParseProperty( pinfo ) ); | |
} | |
pinfo.Expect( ")" ); | |
} | |
} | |
pinfo.Expect( "{" ); | |
while ( !pinfo.Accept( "}" ) ) | |
{ | |
id->children.push_back( ParseStructure( pinfo ) ); | |
} | |
return id; | |
} | |
structure *ParseStructure( ParseInfo &pinfo ) | |
{ | |
structure *dataType = ParseDataType( pinfo ); | |
if ( dataType ) | |
return dataType; | |
structure *id = ParseIdentifier( pinfo ); | |
if ( id ) | |
return id; | |
assert(0); | |
return NULL; | |
} | |
structure *ParseDoc( std::string const &doc ) | |
{ | |
identifier *docID = new identifier; | |
ParseInfo pinfo( doc ); | |
pinfo.GetSym(); | |
while ( !pinfo.End() ) | |
{ | |
docID->children.push_back( ParseStructure( pinfo ) ); | |
} | |
return docID; | |
} | |
void GenerateLinks( std::map<std::string,structure*> &reflinks, structure *root ) | |
{ | |
#if 0 | |
if ( root->name.start ) | |
reflinks[root->name] = root; | |
identifier *id = dynamic_cast<identifier*>( root ); | |
if ( id ) | |
{ | |
for (unsigned int i=0; i<id->props.size(); i++) | |
{ | |
typedprop<structure*> *s = dynamic_cast<typedprop<structure*>*>( id->props[i] ); | |
if ( s ) | |
{ | |
GenerateLinks( reflinks, s->data ); | |
} | |
} | |
for (unsigned int i=0; i<id->children.size(); i++) | |
{ | |
GenerateLinks( reflinks, id->children[i] ); | |
} | |
} | |
#endif | |
} | |
void Link( structure *root, std::map<std::string,structure*> const &reflinks ) | |
{ | |
#if 0 | |
typeddatatype<reflink> *tolink = dynamic_cast<typeddatatype<reflink> *>( root ); | |
if ( tolink ) | |
{ | |
for (unsigned int i=0; i<tolink->items.size(); i++) | |
{ | |
std::map<std::string,structure*>::const_iterator f = reflinks.find( tolink->items[i].name ); | |
if ( f != reflinks.cend() ) | |
tolink->items[i].ref = f->second; | |
} | |
} | |
identifier *id = dynamic_cast<identifier*>( root ); | |
if ( id ) | |
{ | |
for (unsigned int i=0; i<id->props.size(); i++) | |
{ | |
typedprop<reflink> *tolink = dynamic_cast<typedprop<reflink> *>( id->props[i] ); | |
if ( tolink ) | |
{ | |
std::map<std::string,structure*>::const_iterator f = reflinks.find( tolink->data.name ); | |
if ( f != reflinks.cend() ) | |
tolink->data.ref = f->second; | |
} | |
typedprop<structure*> *s = dynamic_cast<typedprop<structure*>*>( id->props[i] ); | |
if ( s ) | |
{ | |
Link( s->data, reflinks ); | |
} | |
} | |
for (unsigned int i=0; i<id->children.size(); i++) | |
{ | |
Link( id->children[i], reflinks ); | |
} | |
} | |
#endif | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
std::string doc; | |
readtextfile( doc, "anim.ogex" ); | |
const char *test = "123 1.234 1.234e90 1.234e-90 aA 0xafg 0b10111"; | |
LexerState lex; | |
lex.cursor = test; | |
lex.text = test; | |
lex.end = test + strlen(test); | |
LexerToken tok; | |
while ( lexerGetToken( &tok, &lex ) == LS_OK ) | |
{ | |
} | |
structure *s = ParseDoc( doc ); | |
std::map<std::string,structure*> reflinks; | |
GenerateLinks( reflinks, s ); | |
Link( s, reflinks ); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pose.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <math.h> | |
#include <float.h> | |
#include "escapi.h" | |
#include "stb_image_write.h" | |
template<typename R> | |
struct dual | |
{ | |
R x; | |
R e; | |
dual() : x(0.f), e(0.f) {} | |
dual(R x0, R e0 = R(0)) : x(x0), e(e0) {} | |
}; | |
template<typename R> | |
inline dual<R> operator-(const dual<R> &a) | |
{ | |
return dual<R>(-a.x, -a.e); | |
} | |
template<typename R> | |
inline dual<R> operator+(const dual<R> &a, const dual<R> &b) | |
{ | |
return dual<R>(a.x + b.x, a.e + b.e); | |
} | |
template<typename R> | |
inline dual<R> operator-(const dual<R> &a, const dual<R> &b) | |
{ | |
return dual<R>(a.x - b.x, a.e - b.e); | |
} | |
template<typename R> | |
inline dual<R> operator*(const dual<R> &a, const dual<R> &b) | |
{ | |
return dual<R>(a.x * b.x, a.x * b.e + a.e * b.x); | |
} | |
template<typename R> | |
inline dual<R> operator/(const dual<R> &a, const dual<R> &b) | |
{ | |
return dual<R>(a.x / b.x, (a.x * b.e - a.e * b.x) / (b.x * b.x)); | |
} | |
template<typename R> | |
inline dual<R> sin(const dual<R> &a) | |
{ | |
return dual<R>(sin(a.x), a.e * cos(a.x)); | |
} | |
template<typename R> | |
inline dual<R> cos(const dual<R> &a) | |
{ | |
return dual<R>(cos(a.x), -a.e * sin(a.x)); | |
} | |
template<typename R> | |
inline dual<R> tan(const dual<R> &a) | |
{ | |
R sec = R(1) / cos(a.x); // needs divide by zero check | |
return dual<R>(tan(a.x), -a.e * sec * sec); | |
} | |
struct err_s | |
{ | |
float dir[4][3]; | |
float dist[3+3+3+3]; | |
}; | |
template <class T> | |
T len( const T p0[3], const T p1[3] ) | |
{ | |
T d[3] = { p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2] }; | |
return sqrt(d[0]*d[0]+d[1]*d[1]+d[2]*d[2]); | |
} | |
template <class T> | |
void cp(T o[3], const T i0[3], const T i1[3]) | |
{ | |
o[0] = i0[1]*i1[2] - i0[2]*i1[1]; | |
o[1] = i0[2]*i1[0] - i0[0]*i1[2]; | |
o[2] = i0[0]*i1[1] - i0[1]*i1[0]; | |
} | |
template <class T> | |
T dot(const T i0[3], const T i1[3]) | |
{ | |
return i0[0]*i1[0] + i0[1]*i1[1] + i0[2]*i1[2]; | |
} | |
template <class T> | |
void sub(T o[3], const T i0[3], const T i1[3]) | |
{ | |
o[0] = i0[0] - i1[0]; | |
o[1] = i0[1] - i1[1]; | |
o[2] = i0[2] - i1[2]; | |
} | |
template <class T> | |
void add(T o[3], const T i0[3], const T i1[3]) | |
{ | |
o[0] = i0[0] + i1[0]; | |
o[1] = i0[1] + i1[1]; | |
o[2] = i0[2] + i1[2]; | |
} | |
template <class T> | |
void normalise( T n[3] ) | |
{ | |
float ool = 1.f/sqrtf( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] ); | |
n[0] *= ool; | |
n[1] *= ool; | |
n[2] *= ool; | |
} | |
template <class T> | |
T err( void *data, T *v ) | |
{ | |
err_s *e = (err_s*)data; | |
T toterr = 0.f; | |
int index = 0; | |
T p[4][3] = | |
{ | |
{ e->dir[0][0]*v[0], e->dir[0][1]*v[0], e->dir[0][2]*v[0] }, | |
{ e->dir[1][0]*v[1], e->dir[1][1]*v[1], e->dir[1][2]*v[1] }, | |
{ e->dir[2][0]*v[2], e->dir[2][1]*v[2], e->dir[2][2]*v[2] }, | |
{ e->dir[3][0]*v[3], e->dir[3][1]*v[3], e->dir[3][2]*v[3] } | |
}; | |
T d10[3], d20[3], c[3]; | |
sub( d10, p[1], p[0] ); | |
sub( d20, p[2], p[0] ); | |
cp( c, d10, d20 ); | |
normalise( c ); | |
T d30[3]; | |
sub( d30, p[3], p[0] ); | |
T d = dot( d30, c ); | |
toterr = toterr + d*d; | |
for (int i=0; i<4; i++) | |
{ | |
T *pi = p[i]; | |
for (int j=i+1; j<4; j++) | |
{ | |
T *pj = p[j]; | |
T l = len( pi, pj ); | |
toterr = toterr + (l-e->dist[index])*(l-e->dist[index]); | |
index++; | |
} | |
} | |
return toterr; | |
} | |
#if 1 | |
template <class T> | |
T derr( int &index, void *data, T *v, T delta ) | |
{ | |
index = -1; | |
float maxErr = 0.f; | |
for (int i=0; i<4; i++) | |
{ | |
T dvmn[4] = { v[0], v[1], v[2], v[3] }; | |
T dvmx[4] = { v[0], v[1], v[2], v[3] }; | |
dvmn[i] = dvmn[i] - delta; | |
dvmx[i] = dvmx[i] + delta; | |
float de = (err( data, dvmx ) - err( data, dvmn )) / (delta*2.f); | |
if ( fabsf( de ) > fabsf( maxErr ) ) | |
{ | |
index = i; | |
maxErr = de; | |
} | |
} | |
return maxErr; | |
} | |
#else | |
dual<float> derr( int &index, void *data, dual<float> *v ) | |
{ | |
index = -1; | |
float maxErr = 0.f; | |
for (int i=0; i<4; i++) | |
{ | |
dual<float> dv[4] = { v[0], v[1], v[2], v[3] }; | |
dvmx[i] = dvmx[i] + delta; | |
float de = (err( data, dvmx ) - err( data, dvmn )) / (delta*2.f); | |
if ( fabsf( de ) > fabsf( maxErr ) ) | |
{ | |
index = i; | |
maxErr = de; | |
} | |
} | |
return maxErr; | |
} | |
#endif | |
#include <Windows.h> | |
struct bgra | |
{ | |
unsigned char b, g, r, a; | |
}; | |
void filtergreen( bgra *buffer, int width, int height ) | |
{ | |
for (int y=0; y<height; y++) | |
{ | |
for (int x=0; x<width; x++) | |
{ | |
int index = y*width+x; | |
bgra *pix = &buffer[index]; | |
if ( pix->g > pix->b && pix->g > pix->r ) | |
{ | |
pix->r = 0; | |
pix->b = 0; | |
} else | |
{ | |
pix->r = 0; | |
pix->g = 0; | |
pix->b = 0; | |
} | |
} | |
} | |
} | |
int count( bgra *buffer, int l, int t, int r, int b, int w, int h ) | |
{ | |
int c = 0; | |
for (int y=t; y<=b; y++) | |
{ | |
if ( y < 0 || y >= h ) | |
continue; | |
for (int x=l; x<=r; x++) | |
{ | |
if ( x < 0 || x >= w ) | |
continue; | |
int index = y*w+x; | |
bgra *pix = &buffer[index]; | |
if ( (pix->r || pix->g || pix->b) ) | |
c++; | |
} | |
} | |
return c; | |
} | |
void filtersmallclumps( bgra *out, bgra *buffer, int width, int height, int r, int s ) | |
{ | |
for (int y=0; y<height; y++) | |
{ | |
for (int x=0; x<width; x++) | |
{ | |
int c = count( buffer, x-r, y-r, x+r, y+r, width, height ); | |
int index = y*width+x; | |
bgra *i = &buffer[index]; | |
bgra *o = &out[index]; | |
if ( c < s ) | |
{ | |
o->r = 0; | |
o->g = 0; | |
o->b = 0; | |
o->a = i->a; | |
} else | |
{ | |
*o = *i; | |
} | |
} | |
} | |
} | |
#if 0 | |
theta_d = sqrt(xd(1,:).^2 + xd(2,:).^2); | |
theta = theta_d; % initial guess | |
for kk=1:20, | |
theta = theta_d ./ (1 + k(1)*theta.^2 + k(2)*theta.^4); | |
end; | |
xd = x * ( 1 + k0*r*r + k1*r*r*r*r); | |
r = x*x+y*y; | |
x = xd / (1+k0*r + k1*r*r); | |
y = yd / (1+k0*r + k1*r*r); | |
#endif | |
void calcundistort( float &x, float &y, float xd, float yd, float k1, float k2 ) | |
{ | |
x = xd; | |
y = yd; | |
int it = 100; | |
while (it--) | |
{ | |
float r = x*x+y*y; | |
x = xd / (1+k1*r + k2*r*r); | |
y = yd / (1+k1*r + k2*r*r); | |
} | |
} | |
void calcdistort( float &xd, float &yd, float x, float y, float k1, float k2 ) | |
{ | |
float r = x*x+y*y; | |
xd = x * (1+k1*r + k2*r*r); | |
yd = y * (1+k1*r + k2*r*r); | |
} | |
float lens[] = { | |
0.f,0.0f, 914.f, 578.f, | |
1.f,0.0f, 799.f, 578.f, | |
2.f,0.0f, 679.f, 578.f, | |
3.f,0.0f, 555.f, 578.f, | |
4.f,0.0f, 425.f, 578.f, | |
5.f,0.0f, 296.f, 578.f, | |
1.f,0.5f, 798.f, 524.f, | |
2.f,1.5f, 676.f, 405.f, | |
3.f,2.5f, 544.f, 281.f, | |
4.f,3.5f, 411.f, 149.f, | |
0.f,0.5f, 914.f, 520.f, | |
0.f,1.5f, 914.f, 405.f, | |
0.f,2.5f, 914.f, 281.f, | |
0.f,3.5f, 914.f, 144.f | |
}; | |
float lenserr( float vec[2] ) | |
{ | |
float mid[] = {914.f, 578.f}; | |
float len = 618.f; | |
float grid = 5.f; | |
float toterr = 0.f; | |
for (int i=0; i<14; i++) | |
{ | |
float *l = &lens[i*4]; | |
float xd, yd; | |
calcdistort( xd, yd, -l[0]/grid, -l[1]/grid, vec[0], vec[1] ); | |
float tx = (l[2]-mid[0]) / len; | |
float ty = (l[3]-mid[1]) / len; | |
//calcundistort( fx, fy, tx, ty, vec[0], vec[1] ); | |
float dx = tx-xd; | |
float dy = ty-yd; | |
//float dx = l[0]-fx; | |
//float dy = l[1]-fy; | |
float err = (dx*dx)+(dy*dy); | |
toterr += err; | |
} | |
return toterr; | |
} | |
// [0] -0.081594504 float | |
// [1] 0.080084130 float | |
float distortionFactor(float radius) | |
{ | |
//float mCoefficients[2] = { 250.0F, 50000.0F }; | |
float mCoefficients[2] = { 0.1526f, 0.01953125f }; | |
float rSq = radius * radius; | |
return 1.0F + mCoefficients[0] * rSq + mCoefficients[1] * rSq * rSq; | |
} | |
float lenserr2( float vec[2], float lensvec[2] ) | |
{ | |
float mid[] = {914.f, 578.f}; | |
float len = 618.f; | |
float grid = 5.f; | |
float toterr = 0.f; | |
for (int i=0; i<14; i++) | |
{ | |
float *l = &lens[i*4]; | |
float xd, yd; | |
calcdistort( xd, yd, -l[0]/grid, -l[1]/grid, vec[0], vec[1] ); | |
float fx, fy; | |
calcdistort( fx, fy, xd, yd, lensvec[0], lensvec[1] );//-0.081594504f, 0.080084130f ); | |
float tx = -l[0]/grid;//(l[2]-mid[0]) / len; | |
float ty = -l[1]/grid;//(l[3]-mid[1]) / len; | |
//calcundistort( fx, fy, tx, ty, vec[0], vec[1] ); | |
float dx = tx-fx; | |
float dy = ty-fy; | |
//float dx = l[0]-fx; | |
//float dy = l[1]-fy; | |
float err = (dx*dx)+(dy*dy); | |
toterr += err; | |
} | |
return toterr; | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
float lensp[2] = {0.f,0.f}; | |
{ | |
int it = 100000; | |
while ( it-- ) | |
{ | |
float maxde = 0.f; | |
int besti = -1; | |
for (int i=0; i<2; i++) | |
{ | |
float v[2] = {lensp[0], lensp[1]}; | |
v[i] = lensp[i] - 0.01f; | |
float err0 = lenserr( v ); | |
v[i] = lensp[i] + 0.01f; | |
float err1 = lenserr( v ); | |
float de = (err1 - err0)/(2.f*0.01f); | |
//printf("%f: %f %f\n", de, err0, err1); | |
if ( fabsf(de) > fabsf(maxde) ) | |
{ | |
besti = i; | |
maxde = de; | |
} | |
} | |
if ( besti == -1 ) | |
break; | |
lensp[besti] -= maxde * 0.01f; | |
} | |
lenserr(lensp); | |
printf(""); | |
} | |
{ | |
float p[2] = {0.f,0.f}; | |
int it = 100000; | |
while ( it-- ) | |
{ | |
float maxde = 0.f; | |
int besti = -1; | |
for (int i=0; i<2; i++) | |
{ | |
float v[2] = {p[0], p[1]}; | |
v[i] = p[i] - 0.01f; | |
float err0 = lenserr2( v, lensp ); | |
v[i] = p[i] + 0.01f; | |
float err1 = lenserr2( v, lensp ); | |
float de = (err1 - err0)/(2.f*0.01f); | |
//printf("%f: %f %f\n", de, err0, err1); | |
if ( fabsf(de) > fabsf(maxde) ) | |
{ | |
besti = i; | |
maxde = de; | |
} | |
} | |
if ( besti == -1 ) | |
break; | |
p[besti] -= maxde * 0.001f; | |
} | |
lenserr2(p, lensp); | |
//float df = distortionFactor(0.025f);// | |
float df = distortionFactor(1.f);// | |
float r = 1.f * 1.f; | |
float f = 1.f + p[0]*r + p[1]*r*r; | |
printf("%f %f", df, f); | |
//0.025F; | |
printf(""); | |
} | |
{ | |
for (int y=0; y<=10; y++) | |
{ | |
for (int x=0; x<=10; x++) | |
{ | |
float dx = (x-5.f)/5.f; | |
float dy = (y-5.f)/5.f; | |
float fx, fy; | |
calcundistort(fx,fy,dx,dy,0.22f, 0.24f); | |
calcdistort( dx,dy,fx, fy,0.22f, 0.24f); | |
printf( "%f, %f, %f, %f\n", fx, fy, dx, dy ); | |
} | |
} | |
} | |
struct SimpleCapParams capture; | |
int c = setupESCAPI(); | |
capture.mWidth = 640; | |
capture.mHeight = 480; | |
capture.mTargetBuf = new int[capture.mWidth*capture.mHeight]; | |
int device = 0; | |
if ( c ) | |
{ | |
initCapture(device,&capture); | |
doCapture(device); | |
} | |
err_s e = | |
{ | |
{ | |
{ 0.f, 0.25f, 1.f }, | |
{ -0.25f, 0.25f, 1.f }, | |
{ -0.25f, -0.25f, 1.f }, | |
{ 0.f, -0.25f, 1.f }, | |
}, | |
{ | |
1.f, sqrtf(2.f), 1.f, | |
1.f, sqrtf(2.f), | |
1.f, | |
}, | |
}; | |
if ( c ) | |
{ | |
while ( 1 ) | |
{ | |
if (isCaptureDone(device)) | |
{ | |
// copy process more | |
// ..and ask for more | |
bgra *buffer = (bgra*)capture.mTargetBuf; | |
filtergreen( buffer, capture.mWidth, capture.mHeight ); | |
bgra *f0 = new bgra[capture.mWidth * capture.mHeight]; | |
filtersmallclumps( f0, buffer, capture.mWidth, capture.mHeight, 3, 5*5 ); | |
stbi_write_png( "test0.png", capture.mWidth, capture.mHeight, 4, capture.mTargetBuf, capture.mWidth*4 ); | |
stbi_write_png( "test1.png", capture.mWidth, capture.mHeight, 4, f0, capture.mWidth*4 ); | |
doCapture(device); | |
} | |
Sleep( 1000 ); | |
} | |
} | |
float d[4] = {3.f,3.f,3.f,3.f}; | |
for (int i=0; i<10000; i++) | |
{ | |
int index; | |
float t = derr( index, &e, d, 0.001f ); | |
if ( index == -1 || fabsf(t) < 0.001f ) | |
break; | |
printf( "%d %f\n", i, t ); | |
d[index] += -t * 0.1f; | |
} | |
float ce = err( &e, d ); | |
return 0; | |
} | |
#if 0 | |
Img img0: DETECTED | |
Img img1: DETECTED | |
Img img2: DETECTED | |
Img img3: DETECTED | |
Img img4: DETECTED | |
Img img5: DETECTED | |
Img img6: DETECTED | |
7 valid images. | |
Img: img0: (x,y,z,yaw,pitch,roll)=(-0.1099,0.1909,0.4340,-176.30deg,-2.42deg,-170.08deg) | |
Img: img1: (x,y,z,yaw,pitch,roll)=(0.0527,-0.1730,0.3133,4.88deg,17.43deg,-146.16deg) | |
Img: img2: (x,y,z,yaw,pitch,roll)=(0.0271,0.2538,0.3655,174.58deg,-24.45deg,-151.71deg) | |
Img: img3: (x,y,z,yaw,pitch,roll)=(-0.1241,-0.1758,0.4540,-21.76deg,3.68deg,-154.57deg) | |
Img: img4: (x,y,z,yaw,pitch,roll)=(-0.0215,-0.3273,0.2617,3.82deg,5.31deg,-126.41deg) | |
Img: img5: (x,y,z,yaw,pitch,roll)=(-0.1485,0.2013,0.4338,-178.09deg,-0.69deg,-168.80deg) | |
Img: img6: (x,y,z,yaw,pitch,roll)=(-0.0567,0.2439,0.4136,-179.49deg,-4.89deg,-163.12deg) | |
[CAMERA_PARAMS] | |
resolution=[640 480] | |
cx=385.79400 | |
cy=280.94590 | |
fx=817.38841 | |
fy=768.73963 | |
dist=[6.950765e-002 -2.527250e-001 -1.659663e-004 2.404563e-002 0.000000e+000] | |
Average err. of reprojection: 0.945455 pixels | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// runanalysis.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <float.h> | |
#include <time.h> | |
#include "pugixml.hpp" | |
#include <map> | |
#include <string> | |
#include <vector> | |
#include <io.h> | |
#include <algorithm> | |
#include "stb_truetype.h" | |
#include "stb_image_write.h" | |
#include <string> | |
char ttf_buffer[1<<20]; | |
unsigned char temp_bitmap[512*512]; | |
stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs | |
void my_stbtt_initfont(void) | |
{ | |
fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); | |
stbtt_BakeFontBitmap((unsigned char*)ttf_buffer,0, 16.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits! | |
} | |
struct stbtt_aligned_quadint | |
{ | |
int s0, t0, w, h; | |
float adv; | |
float xoff; | |
float yoff; | |
}; | |
void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, stbtt_aligned_quadint *q) | |
{ | |
stbtt_bakedchar *b = chardata + char_index; | |
q->xoff = b->xoff; | |
q->yoff = b->yoff; | |
q->s0 = b->x0; | |
q->t0 = b->y0; | |
q->w = b->x1 - b->x0; | |
q->h = b->y1 - b->y0; | |
q->adv = b->xadvance; | |
} | |
class image2d | |
{ | |
unsigned int *m_abgr; | |
int width; | |
int height; | |
public: | |
image2d( int w, int h ) : width(w), height(h) | |
{ | |
m_abgr = new unsigned int[ w * h ]; | |
} | |
image2d() : m_abgr(NULL), width(0), height(0) | |
{ | |
} | |
void setsize( int w, int h ) | |
{ | |
delete []m_abgr; | |
m_abgr = new unsigned int[ w * h ]; | |
width = w; | |
height = h; | |
} | |
void write( const char *filename ) | |
{ | |
stbi_write_png( filename, width, height, 4, m_abgr, width * 4 ); | |
} | |
void putpixel( int x, int y, unsigned int abgr ) | |
{ | |
if ( x >= 0 && y >= 0 && x < width && y < height ) | |
{ | |
int alpha = abgr >> 24; | |
int sb = (abgr>>16) & 0xff; | |
int sg = (abgr>>8) & 0xff; | |
int sr = (abgr>>0) & 0xff; | |
unsigned int dest = m_abgr[ y * width + x ]; | |
int db = (dest>>16) & 0xff; | |
int dg = (dest>>8) & 0xff; | |
int dr = (dest>>0) & 0xff; | |
int fb = (alpha * sb + (255-alpha) * db)/255; | |
int fg = (alpha * sg + (255-alpha) * dg)/255; | |
int fr = (alpha * sr + (255-alpha) * dr)/255; | |
m_abgr[ y * width + x ] = (alpha << 24) | (fb<<16) | (fg<<8) | fr; | |
} | |
} | |
void line( int x0, int y0, int x1, int y1, unsigned int abgr ) | |
{ | |
int dx = x1-x0; | |
int dy = y1-y0; | |
int adx = abs( dx ); | |
int ady = abs( dy ); | |
if ( adx == 0 && ady == 0 ) | |
{ | |
putpixel( x0, y0, abgr ); | |
} else | |
if ( adx > ady ) | |
{ | |
int dir = dx > 0 ? 1 : -1; | |
for (int x=0; x<=adx; x++) | |
{ | |
int y = (dy*x)/(adx); | |
putpixel( x0+x*dir, y0+y, abgr ); | |
} | |
} | |
else | |
{ | |
int dir = dy > 0 ? 1 : -1; | |
for (int y=0; y<=ady; y++) | |
{ | |
int x = (dx*y)/(ady); | |
putpixel( x0+x, y0+y*dir, abgr ); | |
} | |
} | |
} | |
void print(float tx, float ty, const char *text, unsigned int abgr, int rotate ) | |
{ | |
while (*text) { | |
if (*text >= 32 && *text < 128) { | |
stbtt_aligned_quadint q; | |
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &q); | |
for (int y=0; y<q.h; y++) | |
{ | |
for (int x=0; x<q.w; x++) | |
{ | |
int v = temp_bitmap[ (q.t0+y)*512 + (q.s0+x)]; | |
if ( v ) | |
{ | |
if ( rotate ) | |
{ | |
putpixel( tx-(q.yoff+y), ty+q.xoff+x, abgr|(v<<24) ); | |
} else | |
{ | |
putpixel( tx+q.xoff+x, ty+q.yoff+y, abgr|(v<<24) ); | |
} | |
} | |
} | |
} | |
if ( rotate ) | |
{ | |
ty += q.adv; | |
} else | |
{ | |
tx += q.adv; | |
} | |
} | |
++text; | |
} | |
} | |
void clear( unsigned int abgr ) | |
{ | |
for (int i=0; i<width*height; i++) | |
{ | |
m_abgr[i] = abgr; | |
} | |
} | |
void linegraph( float *value, int stride, int num, unsigned int abgr, float xscale = 1.f, float yscale = 1.f, float xoff = 0.f, float yoff = 0.f ) | |
{ | |
for (int i=1; i<num; i++) | |
{ | |
float *last = (float*)((unsigned char*)value + ( (i-1)*stride )); | |
float *cur = (float*)((unsigned char*)value + ( i*stride )); | |
line( (i-1) * xscale + xoff, (*last) * yscale + yoff, i*xscale + xoff, (*cur) * yscale + yoff, abgr ); | |
} | |
} | |
void bargraph( float *value, int stride, int num, unsigned int abgr, float xscale = 1.f, float yscale = 1.f, float xoff = 0.f, float yoff = 0.f ) | |
{ | |
for (int i=0; i<num; i++) | |
{ | |
float *cur = (float*)((unsigned char*)value + ( i*stride )); | |
int x0 = (int)((i) * xscale + xoff); | |
int x1 = (int)((i+1) * xscale + xoff); | |
for (int j=x0; j<x1; j++) | |
{ | |
line( j, yoff, j, (*cur) * yscale + yoff, abgr ); | |
} | |
} | |
} | |
void splitgraph( float *value, int numsplits, int stride, int num, unsigned int *abgr, float xscale = 1.f, float yscale = 1.f, float xoff = 0.f, float yoff = 0.f ) | |
{ | |
for (int i=0; i<num; i++) | |
{ | |
float *cur = (float*)((unsigned char*)value + ( i*stride )); | |
float tot = 0.f; | |
for (int j=0; j<numsplits; j++) | |
{ | |
tot += cur[j]; | |
} | |
float last = 0.f; | |
float run = 0.f; | |
for (int j=0; j<numsplits; j++) | |
{ | |
run += cur[j]; | |
line( i * xscale + xoff, (last/tot) * 100.f * yscale + yoff, i*xscale + xoff, (run/tot) * 100.f * yscale + yoff, abgr[j] ); | |
last = run; | |
} | |
} | |
} | |
void xaxis( std::string *names, int stride, int num, unsigned int abgr, int skip, int y, float xscale = 1.f, float xoff = 0.f ) | |
{ | |
for (int i=0; i<num; i+=skip) | |
{ | |
std::string *cur = (std::string*)((unsigned char*)names + ( i*stride )); | |
print( i*xscale+xoff, y, cur->c_str(), abgr, 1 ); | |
} | |
} | |
}; | |
struct ehack_s | |
{ | |
const char *date; | |
int timeM; | |
int intensity; | |
}; | |
ehack_s ehack[] = | |
{ | |
{ "2012-11-24", 50, 80 }, // event | |
{ "2012-11-24", 90, 70 }, // event | |
{ "2012-11-24", 25, 80 }, // event | |
{ "2012-12-28", 60, 80 }, // ct | |
{ "2012-12-29", 60, 80 }, // ct | |
{ "2012-12-31", 60, 80 }, // ct | |
{ "2013-01-04", 60, 80 }, // ct | |
{ "2013-01-13", 45, 70 }, // bike | |
{ "2013-01-13", 30, 80 }, // ct | |
{ "2013-01-20", 30, 80 }, // ct | |
{ "2013-01-26", 53, 90 }, // event | |
{ "2013-01-26", 75, 80 }, // event | |
{ "2013-01-26", 27, 90 }, // event | |
{ NULL }, | |
}; | |
struct speedToEffort_s | |
{ | |
float speed; | |
int effort; | |
}; | |
const speedToEffort_s speedToEffort_orig[] = | |
{ | |
{ 0.f, 0 }, | |
{ 1.f, 20 }, // 1 | |
{ 8.f, 40 }, // 3 | |
{ 11.f, 50 }, // 4 | |
{ 11.75f, 60 }, // 5 | |
{ 12.25f, 70 }, // 6 | |
{ 13.f, 80 }, // 7 | |
{ 14.7f, 100 }, // 8 | |
{ 15.8f, 120 }, // 9 | |
{ FLT_MAX, 140 }, // 10 | |
}; | |
const speedToEffort_s speedToEffort[] = | |
{ | |
{ 0.f, 0 }, | |
{ 1.f, 20 }, // 1 | |
{ 8.f, 40 }, // 3 | |
{ 11.f, 50 }, // 4 | |
{ 11.75f, 60 }, // 5 | |
{ 12.25f, 70 }, // 6 | |
{ 13.f, 80 }, // 7 | |
{ 14.1f, 100 }, // 8 | |
{ 15.0f, 120 }, // 9 | |
{ FLT_MAX, 140 }, // 10 | |
}; | |
const speedToEffort_s speedToEffort_high[] = | |
{ | |
{ 0.f, 0 }, | |
{ 1.f, 20 }, // 1 | |
{ 8.f, 50 }, // 3 | |
{ 11.f, 60 }, // 4 | |
{ 11.75f, 70 }, // 5 | |
{ 12.25f, 80 }, // 6 | |
{ 13.f, 100 }, // 7 | |
{ 14.7f, 120 }, // 8 | |
{ 15.8f, 140 }, // 9 | |
{ FLT_MAX, 140 }, // 10 | |
}; | |
const int speedToEffortNum = sizeof(speedToEffort) / sizeof(speedToEffort[0]); | |
char *readtextfile( const char *filename, int pad ) | |
{ | |
FILE *f = fopen( filename, "rb" ); | |
if ( f ) | |
{ | |
fseek( f, 0, SEEK_END ); | |
int l = ftell( f ); | |
fseek( f, 0, SEEK_SET ); | |
char *mem = (char*)malloc( l + 1 + 16 ); | |
mem[l] = 0; | |
fread( mem, 1, l, f ); | |
fclose( f ); | |
return mem; | |
} | |
return NULL; | |
} | |
int determineEffort( float kmh ) | |
{ | |
for (int i=0; i<speedToEffortNum; i++) | |
{ | |
if ( kmh < speedToEffort[i+1].speed ) | |
{ | |
return speedToEffort[i].effort; | |
} | |
} | |
return 0; | |
} | |
float calculateTSS( float kmh, float sec ) | |
{ | |
return sec / 3600.f * determineEffort( kmh ); | |
} | |
void fixupbadelement( char *text ) | |
{ | |
char *f = strstr( text, "<nodes>" ); | |
if ( f ) | |
{ | |
f = strstr( f+1, "<nodes>" ); | |
if ( f ) | |
{ | |
strcpy( f, "</nodes>" ); | |
} | |
} | |
} | |
__time32_t dateToInt( __time32_t &week, std::string &strDate, const char *dstr ) | |
{ | |
//2012-12-19 | |
int y, m, d; | |
if ( sscanf( dstr, "%04d-%02d-%02dT", &y, &m, &d ) ) | |
{ | |
tm t; | |
memset( &t, 0, sizeof(t) ); | |
t.tm_year = y - 1900; | |
t.tm_mday = d - 1; | |
t.tm_mon = m - 1; | |
__time32_t res = _mktime32( &t ); | |
if ( res < 0 ) | |
printf(""); | |
char buffer[64]; | |
sprintf( buffer, "%04d-%02d-%02d", y, m, d ); | |
strDate = buffer; | |
week = res - 86400 * t.tm_wday; | |
return res; | |
} | |
else | |
{ | |
strDate = ""; | |
return 0; | |
} | |
} | |
struct alt_s | |
{ | |
float time; | |
float alt; | |
}; | |
float calculateGrade( float time, float kph, std::vector<alt_s> const &altSamples ) | |
{ | |
static int cacheI = 0; | |
if ( cacheI >= altSamples.size() ) | |
cacheI = 0; | |
int i = 0; | |
if ( cacheI && time > altSamples[cacheI-1].time ) | |
{ | |
i = cacheI; | |
} | |
for (; i<altSamples.size(); i++) | |
{ | |
if ( time < altSamples[i].time ) | |
{ | |
if ( i > 2 && i < (altSamples.size()-2) ) | |
{ | |
cacheI = i; | |
float vertChange = altSamples[i+2].alt - altSamples[i-2].alt; | |
float deltaTime = altSamples[i+2].time - altSamples[i-2].time; | |
float deltaDist = (kph * 1000.f) / (60.f*60.f) * deltaTime; | |
float grade = deltaDist > 0.f ? vertChange / deltaDist : 0.f; | |
if ( grade > 0.1f ) | |
grade = 0.1f; | |
if ( grade < -0.1f ) | |
grade = -0.1f; | |
return grade * 100.f; | |
} | |
else | |
{ | |
return 0.f; | |
} | |
} | |
} | |
return 0.f; | |
} | |
inline float maxf( float a, float b ) | |
{ | |
return a>b ? a : b; | |
} | |
float gradeAdjustedPace( float time, float kph, std::vector<alt_s> const &altSamples ) | |
{ | |
float grade = calculateGrade( time, kph, altSamples ); | |
if ( grade >= 0.f ) | |
{ | |
return maxf( 0.f, kph / ( 1.f - grade * 0.03f ) ); | |
} | |
else | |
{ | |
return maxf( 0.f, kph / ( 1.f - grade * 0.03f * 0.5f ) ); | |
} | |
} | |
bool calculateTSS( float &tss, float &totalSec, float &effortArea, __time32_t &date, __time32_t &week, std::string &strDate, float *areas, const char *filename ) | |
{ | |
tss = 0.f; | |
totalSec = 0.f; | |
effortArea = 0.f; | |
char *text = readtextfile( filename, 16 ); | |
if ( text == NULL ) | |
return false; | |
fixupbadelement( text ); | |
pugi::xml_document doc; | |
if ( doc.load_buffer( text, strlen(text) ) ) | |
{ | |
int totalSamples = 0; | |
int samplesAbove100 = 0; | |
int duration = doc.child("nodes").child("activity").child("duration").text().as_int(); | |
std::vector<alt_s> altSamples; | |
for ( pugi::xml_node node = doc.child("nodes").child("activity").child("geo").child("waypoints").child("node"); node; node = node.next_sibling( "node" ) ) | |
{ | |
alt_s a; | |
a.alt = node.child("ele").text().as_float(); | |
a.time = 0.f; | |
altSamples.push_back( a ); | |
} | |
for (unsigned int i=0; i<altSamples.size(); i++) | |
{ | |
altSamples[i].time = ((i * duration)/1000.f)/(altSamples.size()-1); | |
} | |
pugi::xml_node time = doc.child("nodes").child("activity").child("startTimeUtc"); | |
date = dateToInt( week, strDate, time.text().as_string() ); | |
pugi::xml_node history = doc.child("nodes").child("activity").child("history"); | |
for ( pugi::xml_node node = history.child( "node" ); node; node = node.next_sibling( "node" ) ) | |
{ | |
if ( strstr( node.child( "type" ).text().as_string(), "SPEED" ) ) | |
{ | |
float interval = node.child( "intervalMetric" ).text().as_float(); | |
float lastKPH = 0.f; | |
for ( pugi::xml_node vnode = node.child( "values" ).child("node"); vnode; vnode = vnode.next_sibling( "node" ) ) | |
{ | |
float kph = vnode.text().as_float(); | |
if ( kph == 0.f ) | |
{ | |
kph = lastKPH; | |
} | |
if ( kph > 0.f ) | |
{ | |
if ( determineEffort( kph ) >= 100 ) | |
{ | |
samplesAbove100 ++; | |
} | |
areas[determineEffort( kph )/10] += interval/60.f; | |
//float grade = calculateGrade( totalSec, kph, altSamples ); | |
//float adjustedKPH = gradeAdjustedPace( totalSec, kph, altSamples ); | |
//printf( "effort %d\n", ); | |
tss += calculateTSS( gradeAdjustedPace( totalSec, kph, altSamples ), interval ); | |
totalSec += interval; | |
lastKPH = kph; | |
totalSamples ++; | |
} | |
} | |
} | |
} | |
if ( totalSamples ) | |
{ | |
effortArea = (float)samplesAbove100 / totalSamples; | |
} | |
//printf( "TSS %.2f TIME %.1f min\n", tss, totalSec/60.f ); | |
free( text ); | |
return true; | |
} | |
else | |
{ | |
free( text ); | |
return false; | |
} | |
} | |
bool calculateTSS( float &tss, float &totalSec, float &effortArea, __time32_t &date, __time32_t &week, std::string &strDate, float *areas, ehack_s &hack ) | |
{ | |
tss = 0.f; | |
totalSec = 0.f; | |
effortArea = 0.f; | |
{ | |
int samplesAbove100 = 0; | |
date = dateToInt( week, strDate, hack.date ); | |
float interval = hack.timeM * 60.f; | |
if ( hack.intensity >= 100 ) | |
{ | |
samplesAbove100 ++; | |
} | |
areas[hack.intensity/10] += interval/60.f; | |
tss += hack.intensity * interval / (60.f*60.f); | |
totalSec += interval; | |
effortArea = (float)samplesAbove100; | |
return true; | |
} | |
} | |
char fixseparator( char c ) | |
{ | |
return ( c == '/' ) ? '\\' : c; | |
} | |
void findFiles( std::vector< std::string > &files, const char *pattern ) | |
{ | |
std::string path = pattern; | |
std::transform( path.begin(), path.end(), path.begin(), fixseparator ); | |
std::string::size_type pos = path.find_last_of( '\\' ); | |
if ( pos != std::string::npos ) | |
{ | |
path = path.substr( 0, pos ); | |
} | |
else | |
{ | |
path = ".\\"; | |
} | |
_finddata_t fi; | |
intptr_t fh = _findfirst( pattern, &fi ); | |
if ( fh != -1 ) | |
{ | |
do | |
{ | |
files.push_back( path + "\\" + fi.name ); | |
} | |
while ( _findnext( fh, &fi ) == 0 ); | |
_findclose( fh ); | |
} | |
} | |
struct dailyscore_s | |
{ | |
float totalTSS; | |
float totalSec; | |
float effortAreaSec; | |
std::string date; | |
float areas[15]; | |
dailyscore_s() : totalTSS(0.f), totalSec(0.f), effortAreaSec(0.f) { memset( areas, 0, sizeof(areas) );} | |
}; | |
struct graphscore_s | |
{ | |
float totalTSS; | |
float totalSec; | |
std::string date; | |
float areas[15]; | |
float ctl; | |
float atl; | |
float tsb; | |
}; | |
int maxi( int a, int b ) | |
{ | |
return (a>b) ? a : b; | |
} | |
int mini( int a, int b ) | |
{ | |
return (a<b) ? a : b; | |
} | |
void genscores( const char *statscsv, const char *statsdat, std::map< __time32_t, dailyscore_s > const &scores, int deltaDays, __time32_t curtime ) | |
{ | |
image2d ctlatlGraph; | |
float CTLy = 0.f; | |
float ATLy = 0.f; | |
float MINy = 0.f; | |
float AREAy = 0.f; | |
int count = 1; | |
std::map<__time32_t, dailyscore_s >::const_iterator it = scores.cbegin(); | |
__time32_t curTime = it->first; | |
it = scores.cend(); | |
it--; | |
__time32_t endTime = it->first; | |
FILE *dat = fopen( statsdat, "wb" ); | |
FILE *csv = fopen( statscsv, "wb" ); | |
if ( csv ) | |
fprintf( csv, "\"DATE\",\"CTL\",\"ATL\",\"TSB\",\"TSS\",\"MIN\",\"MIN/av\",\"PCNT\",\"PCNT/av\",\"z0\",\"z1\",\"z2\",\"z3\",\"z4\",\"z5\",\"z6\",\"z7\",\"z8\",\"z9\",\"z10\",\"z11\",\"z12\",\"z13\",\"z14\"\n" ); | |
int index = 0; | |
std::vector< graphscore_s > graphData; | |
for ( ;curTime <= curtime/*endTime*/; curTime+=(86400*deltaDays), count++ )//it != dailyscore.cend() ) | |
{ | |
it = scores.find( curTime ); | |
float CTL; | |
float ATL; | |
float PCNT; | |
float TSS; | |
float MIN; | |
float AREA; | |
float totalMin; | |
float areas[15]; | |
if ( it == scores.end() ) | |
{ | |
CTL = CTLy + (0.f - CTLy) / mini( (42/deltaDays), count ); | |
ATL = ATLy + (0.f - ATLy) / mini( (7/deltaDays), count ); | |
MIN = MINy + (0.f - MINy) / mini( (7/deltaDays), count ); | |
AREA = AREAy + (0.f - AREAy) / mini( (7/deltaDays), count ); | |
PCNT = 0.f; | |
TSS = 0.f; | |
totalMin = 0.f; | |
memset( areas, 0, sizeof(areas) ); | |
} | |
else | |
{ | |
CTL = CTLy + (it->second.totalTSS - CTLy) / mini( (42/deltaDays), count ); | |
ATL = ATLy + (it->second.totalTSS - ATLy) / mini( (7/deltaDays), count ); | |
MIN = MINy + ((it->second.totalSec / 60.f) - MINy) / mini( (7/deltaDays), count ); | |
PCNT = 100.f*it->second.effortAreaSec/it->second.totalSec; | |
AREA = AREAy + (PCNT - AREAy) / mini( (7/deltaDays), count ); | |
TSS = it->second.totalTSS; | |
totalMin = it->second.totalSec / 60.f; | |
memcpy( areas, it->second.areas, sizeof(areas) ); | |
} | |
char outtime[256]; | |
__time32_t t = curTime + 86400; | |
strftime( outtime, sizeof(outtime), "%a %Y-%m-%d", _localtime32( &t ) ); | |
float TSB = CTL - ATL; | |
graphscore_s gs; | |
memcpy( gs.areas, areas, sizeof(gs.areas) ); | |
gs.ctl = CTL/(float)deltaDays; | |
gs.atl = ATL/(float)deltaDays; | |
gs.tsb = TSB/(float)deltaDays; | |
gs.date = outtime; | |
graphData.push_back( gs ); | |
if ( csv ) | |
{ | |
fprintf( csv, "\"%s\",%.1f,%.2f,%.2f,%.2f,%.1f,%.1f,%.2f,%.2f", outtime, CTL, ATL, TSB, TSS, totalMin, MIN, PCNT, AREAy ); | |
for (int j=0; j<15; j++) | |
fprintf( csv, ",%1.f", areas[j] ); | |
fprintf( csv, "\n" ); | |
} | |
if ( dat ) | |
{ | |
fprintf( dat, "%s %d %.1f %.2f %.2f %.2f %.1f %.1f %.2f,%.2f", outtime, index, CTL, ATL, TSB, TSS, totalMin, MIN, PCNT, AREAy ); | |
for (int j=0; j<15; j++) | |
fprintf( dat, ",%1.f", areas[j] ); | |
fprintf( dat, "\n" ); | |
} | |
printf( "\"%s\",%.1f,%.2f,%.2f,%.2f,%.2f,%.1f,%.1f,%.2f,%.2f", outtime, CTL, ATL, TSB, TSS/totalMin, TSS, totalMin, MIN, PCNT, AREAy ); | |
for (int j=0; j<15; j++) | |
printf( ",%1.f", areas[j] ); | |
printf( "\n" ); | |
CTLy = CTL; | |
ATLy = ATL; | |
MINy = MIN; | |
AREAy = AREA; | |
index++; | |
} | |
if ( csv ) | |
fclose( csv ); | |
if ( dat ) | |
fclose( dat ); | |
int height = 250; | |
int graphAxis = height - 100; | |
int textAxis = height - 100; | |
ctlatlGraph.setsize( graphData.size() * 2, height ); | |
ctlatlGraph.bargraph( &graphData[0].tsb, sizeof(graphscore_s), graphData.size(), 0xff00ff00, 2.f, -1.f, 0.f, graphAxis/2 ); | |
ctlatlGraph.linegraph( &graphData[0].ctl, sizeof(graphscore_s), graphData.size(), 0xff0000ff, 2.f, -1.f, 0.f, graphAxis ); | |
ctlatlGraph.linegraph( &graphData[0].atl, sizeof(graphscore_s), graphData.size(), 0xffff0000, 2.f, -1.f, 0.f, graphAxis ); | |
ctlatlGraph.xaxis( &graphData[0].date, sizeof(graphscore_s), graphData.size(), 0x00ffffffff, graphData.size()/40, textAxis, 2.f ); | |
ctlatlGraph.write( "ctl.png" ); | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
my_stbtt_initfont(); | |
std::vector<std::string> files; | |
findFiles( files, argv[1] ); | |
std::map< __time32_t, dailyscore_s > dailyscore; | |
std::map< __time32_t, dailyscore_s > weeklyscore; | |
tm curtime; | |
_getsystime( &curtime ); | |
__time32_t curtimeValue = _mktime32( &curtime ); | |
ehack_s *cur = ehack; | |
while ( cur->date ) | |
{ | |
float tss, sec, ea; | |
__time32_t date; | |
__time32_t week; | |
std::string strDate; | |
float areas[15]; | |
memset( areas, 0, sizeof(areas) ); | |
if ( calculateTSS( tss, sec, ea, date, week, strDate, areas, *cur ) ) | |
{ | |
{ | |
dailyscore_s &ds = dailyscore[date]; | |
ds.totalTSS += tss; | |
ds.totalSec += sec; | |
ds.effortAreaSec += ea * sec; | |
ds.date = strDate; | |
for (int j=0; j<15; j++) | |
{ | |
ds.areas[j] += areas[j]; | |
} | |
} | |
{ | |
dailyscore_s &ws = weeklyscore[week]; | |
ws.totalTSS += tss; | |
ws.totalSec += sec; | |
ws.effortAreaSec += ea * sec; | |
ws.date = strDate; | |
for (int j=0; j<15; j++) | |
{ | |
ws.areas[j] += areas[j]; | |
} | |
} | |
} | |
cur++; | |
} | |
for (unsigned int i=0; i<files.size(); i++) | |
{ | |
float tss, sec, ea; | |
__time32_t date; | |
__time32_t week; | |
std::string strDate; | |
float areas[15]; | |
memset( areas, 0, sizeof(areas) ); | |
if ( calculateTSS( tss, sec, ea, date, week, strDate, areas, files[i].c_str() ) ) | |
{ | |
{ | |
dailyscore_s &ds = dailyscore[date]; | |
ds.totalTSS += tss; | |
ds.totalSec += sec; | |
ds.effortAreaSec += ea * sec; | |
ds.date = strDate; | |
for (int j=0; j<15; j++) | |
{ | |
ds.areas[j] += areas[j]; | |
} | |
} | |
{ | |
dailyscore_s &ws = weeklyscore[week]; | |
ws.totalTSS += tss; | |
ws.totalSec += sec; | |
ws.effortAreaSec += ea * sec; | |
ws.date = strDate; | |
for (int j=0; j<15; j++) | |
{ | |
ws.areas[j] += areas[j]; | |
} | |
} | |
} | |
} | |
float CTLy = 0.f; | |
float ATLy = 0.f; | |
float MINy = 0.f; | |
float AREAy = 0.f; | |
int count = 1; | |
std::map<__time32_t, dailyscore_s >::const_iterator it = dailyscore.cbegin(); | |
__time32_t curTime = it->first; | |
it = dailyscore.cend(); | |
it--; | |
__time32_t endTime = it->first; | |
genscores( "stats_day.csv", "stats_day.dat", dailyscore, 1, curtimeValue ); | |
genscores( "stats_wk.csv", "stats_wk.dat", weeklyscore, 7, curtimeValue ); | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// serialisation.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <string.h> | |
#include <vector> | |
#define SERIALISE_TYPEINFO(THISCLASS,PARENTCLASS) \ | |
typedef THISCLASS ThisClass; \ | |
typedef PARENTCLASS SuperClass; \ | |
\ | |
struct Creator \ | |
{ \ | |
const char *(*name_f)(); \ | |
ThisClass *(*creator_f)(); \ | |
Creator *next; \ | |
}; \ | |
\ | |
static Creator *s_subClassCreators; \ | |
\ | |
virtual const char *className() \ | |
{ \ | |
return #THISCLASS; \ | |
} \ | |
static const char *staticClassName() \ | |
{ \ | |
return #THISCLASS; \ | |
} \ | |
template <class C> \ | |
static C* staticCreator() \ | |
{ \ | |
return new ThisClass; \ | |
} \ | |
static ThisClass* create( const char *name ) \ | |
{ \ | |
ThisClass::Creator *curCreator = ThisClass::s_subClassCreators; \ | |
while ( curCreator ) \ | |
{ \ | |
if ( strcmp( curCreator->name_f(), name ) == 0 ) \ | |
{ \ | |
return curCreator->creator_f(); \ | |
} \ | |
curCreator = curCreator->next; \ | |
} \ | |
return NULL; \ | |
} \ | |
static void registerCreator( const char *(*name_f)(), ThisClass *(*creator_f)() ) \ | |
{ \ | |
ThisClass::Creator *creator = new ThisClass::Creator; \ | |
creator->name_f = name_f; \ | |
creator->creator_f = creator_f; \ | |
creator->next = ThisClass::s_subClassCreators; \ | |
ThisClass::s_subClassCreators = creator; \ | |
} | |
#define SERIALISE_TYPEINFO_INST(THISCLASS,PARENTCLASS) \ | |
THISCLASS::Creator *THISCLASS::s_subClassCreators = NULL; | |
#define SERIALISE_NVP(a) #a, a | |
#include <string> | |
class Serialiser | |
{ | |
public: | |
enum | |
{ | |
FILTER_WRITEDATA = 1, | |
FILTER_VISITTOKEN = 2, | |
FILTER_WRITEENTER = 4, | |
}; | |
virtual bool IsLoad() = 0; | |
virtual std::string GetClassType() = 0; | |
virtual void SetClassType( const char *type ) = 0; | |
virtual void Enter( const char *name ) = 0; | |
virtual void Serialise( const char *name, float &v ) = 0; | |
virtual void Serialise( const char *name, int &v ) = 0; | |
virtual void Serialise( const char *name, unsigned int &v ) = 0; | |
virtual void Serialise( const char *name, float *v, int num ) = 0; | |
virtual void Serialise( const char *name, int *v, int num ) = 0; | |
virtual void Serialise( const char *name, unsigned int *v, int num ) = 0; | |
virtual void Exit( const char *name ) = 0; | |
virtual bool VisitToken( void *&visitToken, void *&ptr ) = 0; | |
virtual void Visited( void *visitToken, void *ptr ) = 0; | |
virtual void FilterEnter( unsigned int mask ) { } | |
virtual unsigned int FilterWrite() { return FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER; } | |
virtual void FilterExit( unsigned int mask ) { } | |
}; | |
void SERIALISE( Serialiser &s, const char *name, float &c ) | |
{ | |
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) ) | |
return; | |
s.Serialise( name, c ); | |
} | |
void SERIALISE( Serialiser &s, const char *name, int &c ) | |
{ | |
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) ) | |
return; | |
s.Serialise( name, c ); | |
} | |
void SERIALISE( Serialiser &s, const char *name, unsigned int &c ) | |
{ | |
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) ) | |
return; | |
s.Serialise( name, c ); | |
} | |
template <class C> | |
void SERIALISE( Serialiser &s, const char *name, std::vector<C> &c ) | |
{ | |
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) ) | |
return; | |
s.Enter( name ); | |
unsigned int num = c.size(); | |
s.Serialise( "count", num ); | |
c.resize( num ); | |
for (unsigned int i=0; i<num; i++) | |
{ | |
SERIALISE( s, "entry", c[i] ); | |
} | |
s.Exit( name ); | |
} | |
template <class C> | |
void SERIALISE( Serialiser &s, const char *name, C* &c, unsigned int filterMask = 0 ) | |
{ | |
s.FilterEnter( filterMask ); | |
unsigned int validToOutput = s.FilterWrite(); | |
void* visitToken; | |
if ( validToOutput & Serialiser::FILTER_VISITTOKEN ) | |
{ | |
if ( s.VisitToken( visitToken, (void*&)c ) ) | |
{ | |
s.FilterExit( filterMask ); | |
return; | |
} | |
} | |
if ( validToOutput & Serialiser::FILTER_WRITEDATA ) | |
{ | |
if ( s.IsLoad() ) | |
{ | |
std::string className = s.GetClassType(); | |
if ( className.empty() ) | |
{ | |
c = NULL; | |
s.FilterExit( filterMask ); | |
return; | |
} | |
c = C::create( className.c_str() ); | |
} | |
else | |
{ | |
if ( c == NULL ) | |
{ | |
s.SetClassType( "" ); | |
s.FilterExit( filterMask ); | |
return; | |
} | |
else | |
{ | |
s.SetClassType( c->className() ); | |
} | |
} | |
s.Visited( visitToken, c ); | |
} | |
if ( validToOutput & Serialiser::FILTER_WRITEENTER ) | |
{ | |
s.Enter( name ); | |
c->Serialise( s ); | |
s.Exit( name ); | |
} | |
s.FilterExit( filterMask ); | |
} | |
template <class C> | |
void SERIALISE( Serialiser &s, const char *name, C &c, unsigned int filterMask = 0 ) | |
{ | |
s.Enter( name ); | |
c.Serialise( s ); | |
s.Exit( name ); | |
} | |
#include <map> | |
class VisitDictionary | |
{ | |
std::map<void*, void*> m_written; | |
public: | |
virtual void* VisitToken( void *&visitToken ) | |
{ | |
void *out = m_written[visitToken]; | |
return out; | |
} | |
virtual void Visited( void *visitToken, void *ptr ) | |
{ | |
m_written[visitToken] = ptr; | |
} | |
}; | |
class BINSerialiserO : public Serialiser | |
{ | |
FILE *m_f; | |
VisitDictionary *m_visit; | |
public: | |
BINSerialiserO( const char *filename, VisitDictionary *visit ) : m_visit(visit) | |
{ | |
m_f = fopen( filename, "wb" ); | |
} | |
~BINSerialiserO() | |
{ | |
fclose(m_f); | |
} | |
virtual bool IsLoad() | |
{ | |
return false; | |
} | |
virtual std::string GetClassType() | |
{ | |
return ""; | |
} | |
virtual void SetClassType( const char *ct ) | |
{ | |
int len = strlen( ct ); | |
fwrite( &len, 1, sizeof(len), m_f ); | |
fwrite( ct, 1, len, m_f ); | |
} | |
virtual void Enter( const char *name ) | |
{ | |
} | |
virtual void Serialise( const char *name, float &v ) | |
{ | |
fwrite( &v, 1, sizeof(v), m_f ); | |
} | |
virtual void Serialise( const char *name, int &v ) | |
{ | |
fwrite( &v, 1, sizeof(v), m_f ); | |
} | |
virtual void Serialise( const char *name, unsigned int &v ) | |
{ | |
fwrite( &v, 1, sizeof(v), m_f ); | |
} | |
virtual void Serialise( const char *name, float *v, int num ) | |
{ | |
fwrite( v, 1, sizeof(v[0])*num, m_f ); | |
} | |
virtual void Serialise( const char *name, int *v, int num ) | |
{ | |
fwrite( v, 1, sizeof(v[0])*num, m_f ); | |
} | |
virtual void Serialise( const char *name, unsigned int *v, int num ) | |
{ | |
fwrite( v, 1, sizeof(v[0])*num, m_f ); | |
} | |
virtual void Exit( const char *name ) | |
{ | |
} | |
virtual bool VisitToken( void *&visitToken, void *&ptr ) | |
{ | |
visitToken = ptr; | |
bool res = ptr ? m_visit->VisitToken( visitToken ) != NULL : false; | |
fwrite( &visitToken, 1, sizeof(visitToken), m_f ); | |
return res; | |
} | |
virtual void Visited( void *visitToken, void *ptr ) | |
{ | |
m_visit->Visited( visitToken, ptr ); | |
} | |
}; | |
class BINSerialiserO_Core : public BINSerialiserO | |
{ | |
bool m_outputEnabled; | |
public: | |
BINSerialiserO_Core( const char *filename, VisitDictionary *visit ) : BINSerialiserO( filename, visit ), m_outputEnabled(true) {} | |
virtual void FilterEnter( unsigned int mask ) { if ( mask ) m_outputEnabled = false; } | |
virtual unsigned int FilterWrite() { return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_VISITTOKEN; } | |
virtual void FilterExit( unsigned int mask ) { if ( mask ) m_outputEnabled = true; } | |
}; | |
class BINSerialiserO_Ext : public BINSerialiserO | |
{ | |
bool m_outputEnabled; | |
public: | |
BINSerialiserO_Ext( const char *filename, VisitDictionary *visit ) : BINSerialiserO( filename, visit ), m_outputEnabled(false) {} | |
virtual void FilterEnter( unsigned int mask ) | |
{ | |
if ( mask ) m_outputEnabled = true; | |
} | |
virtual unsigned int FilterWrite() | |
{ | |
return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_WRITEENTER; | |
} | |
virtual void FilterExit( unsigned int mask ) | |
{ | |
if ( mask ) m_outputEnabled = false; | |
} | |
}; | |
class BINSerialiserI : public Serialiser | |
{ | |
FILE *m_f; | |
VisitDictionary *m_visit; | |
public: | |
BINSerialiserI( const char *filename, VisitDictionary *visit ) : m_visit(visit) | |
{ | |
m_f = fopen( filename, "rb" ); | |
} | |
~BINSerialiserI() | |
{ | |
fclose(m_f); | |
} | |
virtual bool IsLoad() | |
{ | |
return true; | |
} | |
virtual std::string GetClassType() | |
{ | |
int len; | |
fread( &len, 1, sizeof(len), m_f ); | |
std::string str; | |
str.resize(len); | |
fread( &str[0], 1, len, m_f ); | |
return str; | |
} | |
virtual void SetClassType( const char *ct ) | |
{ | |
} | |
virtual void Enter( const char *name ) | |
{ | |
} | |
virtual void Serialise( const char *name, float &v ) | |
{ | |
fread( &v, 1, sizeof(v), m_f ); | |
} | |
virtual void Serialise( const char *name, int &v ) | |
{ | |
fread( &v, 1, sizeof(v), m_f ); | |
} | |
virtual void Serialise( const char *name, unsigned int &v ) | |
{ | |
fread( &v, 1, sizeof(v), m_f ); | |
} | |
virtual void Exit( const char *name ) | |
{ | |
} | |
virtual bool VisitToken( void *&visitToken, void *&ptr ) | |
{ | |
fread( &visitToken, 1, sizeof(visitToken), m_f ); | |
ptr = m_visit->VisitToken( visitToken ); | |
return ptr ? true : false; | |
} | |
virtual void Visited( void *visitToken, void *ptr ) | |
{ | |
m_visit->Visited( visitToken, ptr ); | |
} | |
}; | |
class BINSerialiserI_Core : public BINSerialiserI | |
{ | |
bool m_outputEnabled; | |
public: | |
BINSerialiserI_Core( const char *filename, VisitDictionary *visit ) : BINSerialiserI( filename, visit ), m_outputEnabled(true) {} | |
virtual void FilterEnter( unsigned int mask ) { if ( mask ) m_outputEnabled = false; } | |
virtual unsigned int FilterWrite() { return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_VISITTOKEN; } | |
virtual void FilterExit( unsigned int mask ) { if ( mask ) m_outputEnabled = true; } | |
}; | |
class BINSerialiserI_Ext : public BINSerialiserI | |
{ | |
bool m_outputEnabled; | |
public: | |
BINSerialiserI_Ext( const char *filename, VisitDictionary *visit ) : BINSerialiserI( filename, visit ), m_outputEnabled(false) {} | |
virtual void FilterEnter( unsigned int mask ) | |
{ | |
if ( mask ) m_outputEnabled = true; | |
} | |
virtual unsigned int FilterWrite() | |
{ | |
return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_WRITEENTER; | |
} | |
virtual void FilterExit( unsigned int mask ) | |
{ | |
if ( mask ) m_outputEnabled = false; | |
} | |
}; | |
struct B | |
{ | |
SERIALISE_TYPEINFO(B,B); | |
virtual void Serialise( Serialiser &s ) | |
{ | |
} | |
}; | |
SERIALISE_TYPEINFO_INST(B,B); | |
struct channel | |
{ | |
std::vector< float > bigData; | |
SERIALISE_TYPEINFO(channel,channel); | |
virtual void Serialise( Serialiser &s ) | |
{ | |
SERIALISE( s, SERIALISE_NVP(bigData) ); | |
} | |
}; | |
SERIALISE_TYPEINFO_INST(channel,channel); | |
struct classA | |
{ | |
float x, y, z; | |
B *ca; | |
B *cb; | |
channel *chan; | |
B c; | |
public: | |
classA() : x(0.f), y(0.f), z(0.f), ca(NULL), cb(NULL), chan(NULL) | |
{ | |
} | |
SERIALISE_TYPEINFO(classA,classA); | |
virtual void Serialise( Serialiser &s ) | |
{ | |
SERIALISE( s, SERIALISE_NVP(x) ); | |
SERIALISE( s, SERIALISE_NVP(y) ); | |
SERIALISE( s, SERIALISE_NVP(z) ); | |
SERIALISE( s, SERIALISE_NVP(ca) ); | |
SERIALISE( s, SERIALISE_NVP(cb) ); | |
SERIALISE( s, SERIALISE_NVP(c) ); | |
SERIALISE( s, SERIALISE_NVP(chan), 1 ); | |
} | |
}; | |
SERIALISE_TYPEINFO_INST(classA,classA) | |
struct classB : public classA | |
{ | |
float a, b; | |
public: | |
classB() : a(-1.f), b(1.f) {} | |
SERIALISE_TYPEINFO(classB,classA); | |
virtual void Serialise( Serialiser &s ) | |
{ | |
SuperClass::Serialise( s ); | |
SERIALISE( s, SERIALISE_NVP(a) ); | |
SERIALISE( s, SERIALISE_NVP(b) ); | |
} | |
}; | |
SERIALISE_TYPEINFO_INST(classB,classA) | |
template <class T, class C > | |
void Register() | |
{ | |
T::registerCreator( C::staticClassName, C::staticCreator<T> ); | |
if ( T::SuperClass::staticClassName != T::staticClassName ) | |
{ | |
Register<T::SuperClass,C>(); | |
} | |
} | |
class XMLSerialiserO : public Serialiser | |
{ | |
FILE *m_f; | |
std::string m_curClass; | |
public: | |
XMLSerialiserO( const char *filename ) | |
{ | |
m_f = fopen( filename, "wb" ); | |
} | |
~XMLSerialiserO() | |
{ | |
fclose(m_f); | |
} | |
virtual bool IsLoad() | |
{ | |
return false; | |
} | |
virtual std::string GetClassType() | |
{ | |
return ""; | |
} | |
virtual void SetClassType( const char *ct ) | |
{ | |
m_curClass = ct; | |
} | |
virtual void Enter( const char *name ) | |
{ | |
fprintf( m_f, "<%s classname=\"%s\">\n", name, m_curClass.c_str() ); | |
} | |
virtual void Serialise( const char *name, float &v ) | |
{ | |
fprintf( m_f, "<%s>%f</%s>\n", name, v, name ); | |
} | |
virtual void Serialise( const char *name, int &v ) | |
{ | |
fprintf( m_f, "<%s>%d</%s>\n", name, v, name ); | |
} | |
virtual void Serialise( const char *name, unsigned int &v ) | |
{ | |
fprintf( m_f, "<%s>%d</%s>\n", name, v, name ); | |
} | |
virtual void Exit( const char *name ) | |
{ | |
fprintf( m_f, "</%s>\n", name, m_curClass.c_str() ); | |
} | |
virtual bool VisitToken( void *&visitToken, void *&ptr ) | |
{ | |
visitToken = ptr; | |
return false; | |
} | |
virtual void Visited( void *visitToken, void *ptr ) | |
{ | |
} | |
}; | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
Register<classA,classA>(); | |
Register<classB,classB>(); | |
Register<B,B>(); | |
Register<channel,channel>(); | |
{ | |
classA *a = classA::create( "classB" ); | |
a->ca = B::create( "B" ); | |
a->cb = a->ca; | |
a->chan = channel::create( "channel" ); | |
a->chan->bigData.resize( 100 ); | |
VisitDictionary dict; | |
{ | |
BINSerialiserO_Ext ps("test_ext.bin", &dict); | |
SERIALISE( ps, "bin", a ); | |
} | |
{ | |
BINSerialiserO_Core ps("test.bin", &dict); | |
SERIALISE( ps, "bin", a ); | |
} | |
{ | |
XMLSerialiserO ps( "test.xml" ); | |
SERIALISE( ps, "bin", a ); | |
} | |
} | |
{ | |
VisitDictionary dict; | |
classA *a; | |
{ | |
BINSerialiserI_Core ps("test.bin", &dict); | |
SERIALISE( ps, "bin", a ); | |
} | |
{ | |
BINSerialiserI_Ext ps("test_ext.bin", &dict); | |
SERIALISE( ps, "bin", a ); | |
} | |
printf(""); | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment