2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 void *SafeMalloc( size_t n, char *desc );
49 void AnimCompressInit( int nframes,int nVerts,int CompressedFrameSize ){
51 MatWidth = nVerts * 3;
52 MatHeight = CompressedFrameSize;
53 CFrameSize = CompressedFrameSize;
54 matrix = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
55 best = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
56 delta = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
57 comp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
58 tcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
59 bestcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
60 base = (float *)SafeMalloc( MatWidth * sizeof( float ), "AnimCompressInit" );
61 frames = (float *)SafeMalloc( MatWidth * nFrames * sizeof( float ), "AnimCompressInit" );
64 void AnimSetFrame( int frame,int index,float x,float y,float z ){
65 frames[frame * MatWidth + index * 3] = x;
66 frames[frame * MatWidth + index * 3 + 1] = y;
67 frames[frame * MatWidth + index * 3 + 2] = z;
77 #define F_RANDOM ( ( (float)rand() ) / (float)RAND_MAX )
79 extern void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize );
81 void AnimCompressDoit(){
90 for ( k = 0; k < MatWidth; k++ )
92 for ( j = 0; j < nFrames; j++ )
93 for ( k = 0; k < MatWidth; k++ )
94 base[k] += frames[j * MatWidth + k];
95 tmp = 1.0f / (float)nFrames;
96 for ( k = 0; k < MatWidth; k++ )
98 for ( j = 0; j < nFrames; j++ )
99 for ( k = 0; k < MatWidth; k++ )
100 frames[j * MatWidth + k] -= base[k];
102 ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressDoit" );
103 rescale = (float *)SafeMalloc( sizeof( float ) * CFrameSize, "AnimCompressDoit" );
104 DOsvd( frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight );
106 for ( l = 0; l < CFrameSize; l++ )
107 avedev += rescale[l];
108 for ( l = 0; l < CFrameSize; l++ )
109 printf( "%3.1f ",100.0f * rescale[l] / avedev );
111 for ( j = 0; j < nFrames; j++ )
113 for ( l = 0; l < CFrameSize; l++ )
115 bestcomp[j * CFrameSize + l] = 0.0;
116 for ( k = 0; k < MatWidth; k++ )
117 bestcomp[j * CFrameSize + l] += best[l * MatWidth + k] * frames[j * MatWidth + k];
123 for ( j = 0; j < nFrames; j++ )
125 for ( k = 0; k < MatWidth; k++ )
128 for ( l = 0; l < CFrameSize; l++ )
129 ans[k] += best[l * MatWidth + k] * bestcomp[j * CFrameSize + l];
130 ans[k] -= frames[j * MatWidth + k];
131 tmp = (float)fabs( ans[k] );
132 if ( tmp > maxdev ) {
139 avedev /= (float)numave;
140 printf( "%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev );
141 printf( "%d bytes original size\n",MatWidth * nFrames );
142 printf( "%d bytes of overhead\n",MatWidth * MatHeight );
143 printf( "%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize * nFrames );
144 compression = (float)( MatWidth * MatHeight + CFrameSize * nFrames + MatWidth );
145 compression /= (float)( MatWidth * nFrames );
146 printf( "Overall compression = %f %%\n",100.0f - 100.0f * compression );
147 compression = (float)( CFrameSize );
148 compression /= (float)( MatWidth );
149 printf( "frame size compression = %f %%\n",100.0f - 100.0f * compression );
154 void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax ){
172 for ( k = 0; k < MatWidth; k += 3 )
174 if ( base[k] > scale[0] ) {
177 if ( base[k] < trans[0] ) {
181 if ( base[k + 1] > scale[1] ) {
182 scale[1] = base[k + 1];
184 if ( base[k + 1] < trans[1] ) {
185 trans[1] = base[k + 1];
188 if ( base[k + 2] > scale[2] ) {
189 scale[2] = base[k + 2];
191 if ( base[k + 2] < trans[2] ) {
192 trans[2] = base[k + 2];
196 scale[0] -= trans[0];
197 scale[1] -= trans[1];
198 scale[2] -= trans[2];
202 for ( k = 0; k < MatWidth; k += 3 )
204 t = ( base[k] - trans[0] ) / scale[0];
211 cbase[k] = (unsigned char)t;
213 t = ( base[k + 1] - trans[1] ) / scale[1];
220 cbase[k + 1] = (unsigned char)t;
222 t = ( base[k + 2] - trans[2] ) / scale[2];
229 cbase[k + 2] = (unsigned char)t;
231 for ( l = 0; l < MatHeight; l++ )
234 for ( k = 0; k < MatWidth; k++ )
236 if ( fabs( best[l * MatWidth + k] ) > mx ) {
237 mx = (float)fabs( best[l * MatWidth + k] );
244 for ( j = 0; j < nFrames; j++ )
246 bestcomp[j * MatHeight + l] *= mx;
247 if ( bestcomp[j * MatHeight + l] > cscale[l] ) {
248 cscale[l] = bestcomp[j * MatHeight + l];
250 if ( bestcomp[j * MatHeight + l] < coffset[l] ) {
251 coffset[l] = bestcomp[j * MatHeight + l];
254 cscale[l] -= coffset[l];
255 if ( cscale[l] > 1E-10 ) {
256 for ( j = 0; j < nFrames; j++ )
258 tmp = 254.0f * ( bestcomp[j * MatHeight + l] - coffset[l] ) / cscale[l] - 127.0f;
259 if ( tmp > 127.0f ) {
262 if ( tmp < -127.0f ) {
265 ccomp[j * MatHeight + l] = (char)floor( tmp + 0.5 );
267 coffset[l] += cscale[l] * 127.0f / 254.0f;
274 for ( j = 0; j < nFrames; j++ )
275 ccomp[j * MatHeight + l] = 0;
278 for ( k = 0; k < MatWidth; k++ )
280 tmp = best[l * MatWidth + k] * mx;
281 if ( tmp > 127.0f ) {
284 if ( tmp < -127.0f ) {
287 mat[k * MatHeight + l] = (char)floor( tmp + 0.5 );
294 for ( j = 0; j < nFrames; j++ )
295 ccomp[j * MatHeight + l] = 0;
296 for ( k = 0; k < MatWidth; k++ )
297 mat[k * MatHeight + l] = 0;
309 ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressToBytes" );
310 for ( j = 0; j < nFrames; j++ )
312 for ( k = 0; k < MatWidth; k++ )
315 for ( l = 0; l < CFrameSize; l++ )
316 ans[k] += (float)( mat[l + k * MatHeight] ) * ( (float)( ccomp[j * CFrameSize + l] ) * cscale[l] + coffset[l] );
317 ans[k] += (float)( cbase[k] ) * scale[k % 3] + trans[k % 3];
318 tmp = (float)fabs( ans[k] - frames[j * MatWidth + k] - base[k] );
319 if ( tmp > maxdev ) {
325 if ( bmin[k % 3] > ans[k] ) {
326 bmin[k % 3] = ans[k];
328 if ( bmax[k % 3] < ans[k] ) {
329 bmax[k % 3] = ans[k];
333 avedev /= (float)numave;
334 printf( "%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev );
338 void AnimCompressGetMatrix( float *mat ){
340 for ( k = 0; k < MatWidth; k++ )
341 for ( l = 0; l < MatHeight; l++ )
342 mat[k * MatHeight + l] = best[l * MatWidth + k];
345 void AnimCompressGetFrames( float *mat ){
346 memcpy( mat,bestcomp,CFrameSize * nFrames * sizeof( float ) );
349 void AnimCompressGetBase( int i,float *x,float *y,float *z ){
351 *y = base[i * 3 + 1];
352 *z = base[i * 3 + 2];
355 void AnimCompressEnd(){