2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
28 static double at,bt,ct;
\r
29 #define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
\r
30 (ct=bt/at,at*sqrt(1.0+ct*ct)) : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
\r
32 static double maxarg1,maxarg2;
\r
33 #define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
\r
34 (maxarg1) : (maxarg2))
\r
35 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
\r
37 void ntrerror(char *s)
\r
43 double *allocVect(int sz)
\r
47 ret = calloc(sizeof(double), (size_t)sz);
\r
51 void freeVect(double *ret)
\r
56 double **allocMatrix(int r,int c)
\r
60 ret = calloc(sizeof(double), (size_t)(r*c));
\r
64 void freeMatrix(double **ret,int r)
\r
69 void svdcmp(double** a, int m, int n, double* w, double** v)
\r
71 int flag,i,its,j,jj,k,l,nm;
\r
72 double c,f,h,s,x,y,z;
\r
73 double anorm=0.0,g=0.0,scale=0.0;
\r
77 if (m < n) ntrerror("SVDCMP: You must augment A with extra zero rows");
\r
79 for (i=1;i<=n;i++) {
\r
84 for (k=i;k<=m;k++) scale += fabs(a[k][i]);
\r
86 for (k=i;k<=m;k++) {
\r
88 s += a[k][i]*a[k][i];
\r
91 g = -SIGN(sqrt(s),f);
\r
95 for (j=l;j<=n;j++) {
\r
96 for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
\r
98 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
\r
101 for (k=i;k<=m;k++) a[k][i] *= scale;
\r
106 if (i <= m && i != n) {
\r
107 for (k=l;k<=n;k++) scale += fabs(a[i][k]);
\r
109 for (k=l;k<=n;k++) {
\r
111 s += a[i][k]*a[i][k];
\r
114 g = -SIGN(sqrt(s),f);
\r
117 for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
\r
119 for (j=l;j<=m;j++) {
\r
120 for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
\r
121 for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
\r
124 for (k=l;k<=n;k++) a[i][k] *= scale;
\r
127 anorm=MAX(anorm,(fabs(w[i])+fabs(rv1[i])));
\r
129 for (i=n;i>=1;i--) {
\r
133 v[j][i]=(a[i][j]/a[i][l])/g;
\r
134 for (j=l;j<=n;j++) {
\r
135 for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
\r
136 for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
\r
139 for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
\r
145 for (i=n;i>=1;i--) {
\r
149 for (j=l;j<=n;j++) a[i][j]=0.0;
\r
153 for (j=l;j<=n;j++) {
\r
154 for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
\r
156 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
\r
159 for (j=i;j<=m;j++) a[j][i] *= g;
\r
161 for (j=i;j<=m;j++) a[j][i]=0.0;
\r
165 for (k=n;k>=1;k--) {
\r
166 for (its=1;its<=30;its++) {
\r
168 for (l=k;l>=1;l--) {
\r
170 if (fabs(rv1[l])+anorm == anorm) {
\r
174 if (fabs(w[nm])+anorm == anorm) break;
\r
179 for (i=l;i<=k;i++) {
\r
181 if (fabs(f)+anorm != anorm) {
\r
188 for (j=1;j<=m;j++) {
\r
201 for (j=1;j<=n;j++) v[j][k]=(-v[j][k]);
\r
205 if (its == 30) ntrerror("No convergence in 30 SVDCMP iterations");
\r
211 f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
\r
213 f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
\r
215 for (j=l;j<=nm;j++) {
\r
229 for (jj=1;jj<=n;jj++) {
\r
244 for (jj=1;jj<=m;jj++) {
\r
261 void svbksb(double** u, double* w, double** v,int m, int n, double* b, double* x)
\r
266 for (j=1;j<=n;j++)
\r
271 for (i=1;i<=m;i++)
\r
272 s += u[i][j]*b[i];
\r
277 for (j=1;j<=n;j++)
\r
280 for (jj=1;jj<=n;jj++)
\r
281 s += v[j][jj]*tmp[jj];
\r
293 void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize)
\r
305 if (nframes>framesize)
\r
310 da=allocMatrix(usedfs,nframes);
\r
311 v=allocMatrix(nframes,nframes);
\r
312 w=allocVect(nframes);
\r
314 DOFerr = 0; //false
\r
315 for (i=0;i<nframes;i++)
\r
317 for (j=0;j<framesize;j++)
\r
318 da[j+1][i+1]=a[i*framesize+j];
\r
319 for (;j<usedfs;j++)
\r
323 svdcmp(da,usedfs,nframes,w,v);
\r
325 remap = calloc(sizeof(int), (size_t)nframes);
\r
328 for (i=0;i<nframes;i++)
\r
330 for (j=0;j<compressedsize;j++)
\r
333 for (i=0;i<nframes;i++)
\r
335 if (remap[i]<0&&fabs(w[i+1])>mx)
\r
337 mx=(float) fabs(w[i+1]);
\r
354 printf("Warning: To many degrees of freedom! File size may increase\n");
\r
356 for (i=0;i<compressedsize;i++)
\r
359 for (j=0;j<framesize;j++)
\r
360 res[i*framesize+j]=0;
\r
364 for (i=0;i<nframes;i++)
\r
370 values[remap[i]]=(float) w[i+1];
\r
371 for (j=0;j<framesize;j++)
\r
372 res[remap[i]*framesize+j]=(float) da[j+1][i+1];
\r
376 freeMatrix(v,nframes);
\r
377 freeMatrix(da,framesize);
\r
383 void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize)
\r
389 if (nrows<framesize)
\r
391 double **da=allocMatrix(nrows,framesize);
\r
392 double **v=allocMatrix(framesize,framesize);
\r
393 double *w=allocVect(framesize);
\r
397 for (j=0;j<framesize;j++)
\r
399 for (i=0;i<nframes;i++)
\r
400 da[j+1][i+1]=a[i*framesize+j];
\r
405 svdcmp(da,nrows,framesize,w,v);
\r
407 remap=new int[framesize];
\r
410 for (i=0;i<framesize;i++)
\r
412 for (j=0;j<compressedsize;j++)
\r
415 for (i=0;i<framesize;i++)
\r
417 if (remap[i]<0&&fabs(w[i+1])>mx)
\r
426 // josh **DO NOT** put your dof>nframes mod here
\r
427 for (i=0;i<framesize;i++)
\r
433 values[remap[i]]=w[i+1];
\r
434 for (j=0;j<framesize;j++)
\r
435 res[remap[i]*framesize+j]=v[j+1][i+1];
\r
439 freeMatrix(v,framesize);
\r
440 freeMatrix(da,nrows);
\r
446 void DOsvdPlane(float *pnts,int npnts,float *n,float *base)
\r
449 double **da=allocMatrix(npnts,3);
\r
450 double **v=allocMatrix(3,3);
\r
451 double *w=allocVect(3);
\r
460 for (i=1;i<npnts;i++)
\r
463 base[j]+=pnts[i*3+j];
\r
465 base[0]/=(float)(npnts);
\r
466 base[1]/=(float)(npnts);
\r
467 base[2]/=(float)(npnts);
\r
471 for (j=0;j<npnts;j++)
\r
472 da[j+1][i+1]=pnts[j*3+i]-base[i];
\r
475 svdcmp(da,npnts,3,w,v);
\r
478 if (fabs(w[i+1])<mn)
\r
480 mn=(float) fabs(w[i+1]);
\r
484 n[0]=(float) v[1][bestat+1];
\r
485 n[1]=(float) v[2][bestat+1];
\r
486 n[2]=(float) v[3][bestat+1];
\r
489 freeMatrix(da,npnts);
\r