]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/animcomp.c
uncrustify! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / animcomp.c
1 /*
2    Copyright (C) 1999-2007 id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
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.
11
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.
16
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
20  */
21
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <math.h>
26 #include <memory.h>
27 #include "animcomp.h"
28
29
30 void    *SafeMalloc( size_t n, char *desc );
31
32
33
34 float *matrix;
35 float *delta;
36 float *best;
37 float *comp;
38 float *tcomp;
39 float *bestcomp;
40 float *frames;
41 float *base;
42
43 int MatWidth;
44 int MatHeight;
45 int CFrameSize;
46 int nFrames;
47
48
49 void AnimCompressInit( int nframes,int nVerts,int CompressedFrameSize ){
50         nFrames = nframes;
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" );
62 }
63
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;
68 }
69
70 typedef struct
71 {
72         int index;
73         float val;
74 } SORTP;
75
76
77 #define F_RANDOM ( ( (float)rand() ) / (float)RAND_MAX )
78
79 extern void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize );
80
81 void AnimCompressDoit(){
82         float compression;
83         float *rescale;
84         float *ans;
85         float maxdev;
86         float avedev;
87         float tmp;
88         int j,k,l,numave;
89
90         for ( k = 0; k < MatWidth; k++ )
91                 base[k] = 0.0f;
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++ )
97                 base[k] *= tmp;
98         for ( j = 0; j < nFrames; j++ )
99                 for ( k = 0; k < MatWidth; k++ )
100                         frames[j * MatWidth + k] -= base[k];
101
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 );
105         avedev = 0.0;
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 );
110         printf( "\n" );
111         for ( j = 0; j < nFrames; j++ )
112         {
113                 for ( l = 0; l < CFrameSize; l++ )
114                 {
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];
118                 }
119         }
120         numave = 0;
121         avedev = 0.0;
122         maxdev = 0.0;
123         for ( j = 0; j < nFrames; j++ )
124         {
125                 for ( k = 0; k < MatWidth; k++ )
126                 {
127                         ans[k] = 0.0;
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 ) {
133                                 maxdev = tmp;
134                         }
135                         avedev += tmp;
136                         numave++;
137                 }
138         }
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 );
150         free( rescale );
151         free( ans );
152 }
153
154 void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax ){
155         int k,l,nv,j;
156         float maxdev;
157         float avedev;
158         float tmp;
159         int numave;
160         float t,mx;
161         float *ans;
162
163
164         nv = MatWidth / 3;
165
166         trans[0] = 1E30f;
167         scale[0] = -1E30f;
168         trans[1] = 1E30f;
169         scale[1] = -1E30f;
170         trans[2] = 1E30f;
171         scale[2] = -1E30f;
172         for ( k = 0; k < MatWidth; k += 3 )
173         {
174                 if ( base[k] > scale[0] ) {
175                         scale[0] = base[k];
176                 }
177                 if ( base[k] < trans[0] ) {
178                         trans[0] = base[k];
179                 }
180
181                 if ( base[k + 1] > scale[1] ) {
182                         scale[1] = base[k + 1];
183                 }
184                 if ( base[k + 1] < trans[1] ) {
185                         trans[1] = base[k + 1];
186                 }
187
188                 if ( base[k + 2] > scale[2] ) {
189                         scale[2] = base[k + 2];
190                 }
191                 if ( base[k + 2] < trans[2] ) {
192                         trans[2] = base[k + 2];
193                 }
194         }
195
196         scale[0] -= trans[0];
197         scale[1] -= trans[1];
198         scale[2] -= trans[2];
199         scale[0] /= 255.0f;
200         scale[1] /= 255.0f;
201         scale[2] /= 255.0f;
202         for ( k = 0; k < MatWidth; k += 3 )
203         {
204                 t = ( base[k] - trans[0] ) / scale[0];
205                 if ( t < 0.0f ) {
206                         t = 0.0f;
207                 }
208                 if ( t > 255.0f ) {
209                         t = 255.0f;
210                 }
211                 cbase[k] = (unsigned char)t;
212
213                 t = ( base[k + 1] - trans[1] ) / scale[1];
214                 if ( t < 0.0f ) {
215                         t = 0.0f;
216                 }
217                 if ( t > 255.0f ) {
218                         t = 255.0f;
219                 }
220                 cbase[k + 1] = (unsigned char)t;
221
222                 t = ( base[k + 2] - trans[2] ) / scale[2];
223                 if ( t < 0.0f ) {
224                         t = 0.0f;
225                 }
226                 if ( t > 255.0f ) {
227                         t = 255.0f;
228                 }
229                 cbase[k + 2] = (unsigned char)t;
230         }
231         for ( l = 0; l < MatHeight; l++ )
232         {
233                 mx = 0.0;
234                 for ( k = 0; k < MatWidth; k++ )
235                 {
236                         if ( fabs( best[l * MatWidth + k] ) > mx ) {
237                                 mx = (float)fabs( best[l * MatWidth + k] );
238                         }
239                 }
240                 if ( mx > 1E-8 ) {
241                         mx /= 127.0f;
242                         coffset[l] = 1E30f;
243                         cscale[l] = -1E30f;
244                         for ( j = 0; j < nFrames; j++ )
245                         {
246                                 bestcomp[j * MatHeight + l] *= mx;
247                                 if ( bestcomp[j * MatHeight + l] > cscale[l] ) {
248                                         cscale[l] = bestcomp[j * MatHeight + l];
249                                 }
250                                 if ( bestcomp[j * MatHeight + l] < coffset[l] ) {
251                                         coffset[l] = bestcomp[j * MatHeight + l];
252                                 }
253                         }
254                         cscale[l] -= coffset[l];
255                         if ( cscale[l] > 1E-10 ) {
256                                 for ( j = 0; j < nFrames; j++ )
257                                 {
258                                         tmp = 254.0f * ( bestcomp[j * MatHeight + l] - coffset[l] ) / cscale[l] - 127.0f;
259                                         if ( tmp > 127.0f ) {
260                                                 tmp = 127.0f;
261                                         }
262                                         if ( tmp < -127.0f ) {
263                                                 tmp = -127.0f;
264                                         }
265                                         ccomp[j * MatHeight + l] = (char)floor( tmp + 0.5 );
266                                 }
267                                 coffset[l] += cscale[l] * 127.0f / 254.0f;
268                                 cscale[l] /= 254.0f;
269                         }
270                         else
271                         {
272                                 cscale[l] = 1.0f;
273                                 coffset[l] = 0.0f;
274                                 for ( j = 0; j < nFrames; j++ )
275                                         ccomp[j * MatHeight + l] = 0;
276                         }
277                         mx = 1.0f / mx;
278                         for ( k = 0; k < MatWidth; k++ )
279                         {
280                                 tmp = best[l * MatWidth + k] * mx;
281                                 if ( tmp > 127.0f ) {
282                                         tmp = 127.0f;
283                                 }
284                                 if ( tmp < -127.0f ) {
285                                         tmp = -127.0f;
286                                 }
287                                 mat[k * MatHeight + l] = (char)floor( tmp + 0.5 );
288                         }
289                 }
290                 else
291                 {
292                         cscale[l] = 1.0f;
293                         coffset[l] = 0.0f;
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;
298                 }
299         }
300         bmin[0] = 1E30f;
301         bmin[1] = 1E30f;
302         bmin[2] = 1E30f;
303         bmax[0] = -1E30f;
304         bmax[1] = -1E30f;
305         bmax[2] = -1E30f;
306         numave = 0;
307         avedev = 0.0;
308         maxdev = 0.0;
309         ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressToBytes" );
310         for ( j = 0; j < nFrames; j++ )
311         {
312                 for ( k = 0; k < MatWidth; k++ )
313                 {
314                         ans[k] = 0.0;
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 ) {
320                                 maxdev = tmp;
321                         }
322                         avedev += tmp;
323                         numave++;
324
325                         if ( bmin[k % 3] > ans[k] ) {
326                                 bmin[k % 3] = ans[k];
327                         }
328                         if ( bmax[k % 3] < ans[k] ) {
329                                 bmax[k % 3] = ans[k];
330                         }
331                 }
332         }
333         avedev /= (float)numave;
334         printf( "%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev );
335         free( ans );
336 }
337
338 void AnimCompressGetMatrix( float *mat ){
339         int k,l;
340         for ( k = 0; k < MatWidth; k++ )
341                 for ( l = 0; l < MatHeight; l++ )
342                         mat[k * MatHeight + l] = best[l * MatWidth + k];
343 }
344
345 void AnimCompressGetFrames( float *mat ){
346         memcpy( mat,bestcomp,CFrameSize * nFrames * sizeof( float ) );
347 }
348
349 void AnimCompressGetBase( int i,float *x,float *y,float *z ){
350         *x = base[i * 3];
351         *y = base[i * 3 + 1];
352         *z = base[i * 3 + 2];
353 }
354
355 void AnimCompressEnd(){
356         free( matrix );
357         free( best );
358         free( delta );
359         free( comp );
360         free( tcomp );
361         free( bestcomp );
362         free( base );
363         free( frames );
364 }