/* Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "animcomp.h" void *SafeMalloc(size_t n, char *desc); float *matrix; float *delta; float *best; float *comp; float *tcomp; float *bestcomp; float *frames; float *base; int MatWidth; int MatHeight; int CFrameSize; int nFrames; void AnimCompressInit(int nframes,int nVerts,int CompressedFrameSize) { nFrames=nframes; MatWidth=nVerts*3; MatHeight=CompressedFrameSize; CFrameSize=CompressedFrameSize; matrix=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit"); best=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit"); delta=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit"); comp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit"); tcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit"); bestcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit"); base=(float *)SafeMalloc(MatWidth*sizeof(float), "AnimCompressInit"); frames=(float *)SafeMalloc(MatWidth*nFrames*sizeof(float), "AnimCompressInit"); } void AnimSetFrame(int frame,int index,float x,float y,float z) { frames[frame*MatWidth+index*3]=x; frames[frame*MatWidth+index*3+1]=y; frames[frame*MatWidth+index*3+2]=z; } typedef struct { int index; float val; } SORTP; #define F_RANDOM (((float)rand())/(float)RAND_MAX) extern void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize); void AnimCompressDoit() { float compression; float *rescale; float *ans; float maxdev; float avedev; float tmp; int j,k,l,numave; for (k=0;kmaxdev) maxdev=tmp; avedev+=tmp; numave++; } } avedev/=(float)numave; printf("%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev); printf("%d bytes original size\n",MatWidth*nFrames); printf("%d bytes of overhead\n",MatWidth*MatHeight); printf("%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize*nFrames); compression=(float)(MatWidth*MatHeight+CFrameSize*nFrames+MatWidth); compression/=(float)(MatWidth*nFrames); printf("Overall compression = %f %%\n",100.0f-100.0f*compression); compression=(float)(CFrameSize); compression/=(float)(MatWidth); printf("frame size compression = %f %%\n",100.0f-100.0f*compression); free(rescale); free(ans); } void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax) { int k,l,nv,j; float maxdev; float avedev; float tmp; int numave; float t,mx; float *ans; nv=MatWidth/3; trans[0]=1E30f; scale[0]=-1E30f; trans[1]=1E30f; scale[1]=-1E30f; trans[2]=1E30f; scale[2]=-1E30f; for (k=0;kscale[0]) scale[0]=base[k]; if (base[k]scale[1]) scale[1]=base[k+1]; if (base[k+1]scale[2]) scale[2]=base[k+2]; if (base[k+2]255.0f) t=255.0f; cbase[k]=(unsigned char)t; t=(base[k+1]-trans[1])/scale[1]; if (t<0.0f) t=0.0f; if (t>255.0f) t=255.0f; cbase[k+1]=(unsigned char)t; t=(base[k+2]-trans[2])/scale[2]; if (t<0.0f) t=0.0f; if (t>255.0f) t=255.0f; cbase[k+2]=(unsigned char)t; } for (l=0;lmx) mx=(float)fabs(best[l*MatWidth+k]); } if (mx>1E-8) { mx/=127.0f; coffset[l]=1E30f; cscale[l]=-1E30f; for (j=0;jcscale[l]) cscale[l]=bestcomp[j*MatHeight+l]; if (bestcomp[j*MatHeight+l]1E-10) { for (j=0;j127.0f) tmp=127.0f; if (tmp<-127.0f) tmp=-127.0f; ccomp[j*MatHeight+l]=(char)floor(tmp+0.5); } coffset[l]+=cscale[l]*127.0f/254.0f; cscale[l]/=254.0f; } else { cscale[l]=1.0f; coffset[l]=0.0f; for (j=0;j127.0f) tmp=127.0f; if (tmp<-127.0f) tmp=-127.0f; mat[k*MatHeight+l]=(char)floor(tmp+0.5); } } else { cscale[l]=1.0f; coffset[l]=0.0f; for (j=0;jmaxdev) maxdev=tmp; avedev+=tmp; numave++; if (bmin[k%3]>ans[k]) bmin[k%3]=ans[k]; if (bmax[k%3]