00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include "PQP.h"
00045 #include "MatVec.h"
00046
00047
00048
00049
00050 #define RAPID2_FIT 0
00051
00052 #if RAPID2_FIT
00053
00054 struct moment
00055 {
00056 PQP_REAL A;
00057 PQP_REAL m[3];
00058 PQP_REAL s[3][3];
00059 };
00060
00061 struct accum
00062 {
00063 PQP_REAL A;
00064 PQP_REAL m[3];
00065 PQP_REAL s[3][3];
00066 };
00067
00068 inline
00069 void
00070 clear_accum(accum &a)
00071 {
00072 a.m[0] = a.m[1] = a.m[2] = 0.0;
00073 a.s[0][0] = a.s[0][1] = a.s[0][2] = 0.0;
00074 a.s[1][0] = a.s[1][1] = a.s[1][2] = 0.0;
00075 a.s[2][0] = a.s[2][1] = a.s[2][2] = 0.0;
00076 a.A = 0.0;
00077 }
00078
00079 inline
00080 void
00081 accum_moment(accum &a, moment &b)
00082 {
00083 a.m[0] += b.m[0] * b.A;
00084 a.m[1] += b.m[1] * b.A;
00085 a.m[2] += b.m[2] * b.A;
00086
00087 a.s[0][0] += b.s[0][0];
00088 a.s[0][1] += b.s[0][1];
00089 a.s[0][2] += b.s[0][2];
00090 a.s[1][0] += b.s[1][0];
00091 a.s[1][1] += b.s[1][1];
00092 a.s[1][2] += b.s[1][2];
00093 a.s[2][0] += b.s[2][0];
00094 a.s[2][1] += b.s[2][1];
00095 a.s[2][2] += b.s[2][2];
00096
00097 a.A += b.A;
00098 }
00099
00100 inline
00101 void
00102 mean_from_moment(PQP_REAL M[3], moment &m)
00103 {
00104 M[0] = m.m[0];
00105 M[1] = m.m[1];
00106 M[2] = m.m[2];
00107 }
00108
00109 inline
00110 void
00111 mean_from_accum(PQP_REAL M[3], accum &a)
00112 {
00113 M[0] = a.m[0] / a.A;
00114 M[1] = a.m[1] / a.A;
00115 M[2] = a.m[2] / a.A;
00116 }
00117
00118 inline
00119 void
00120 covariance_from_accum(PQP_REAL C[3][3], accum &a)
00121 {
00122 int i,j;
00123 for(i=0; i<3; i++)
00124 for(j=0; j<3; j++)
00125 C[i][j] = a.s[i][j] - a.m[i]*a.m[j]/a.A;
00126 }
00127
00128 inline
00129 void
00130 compute_moment(moment &M, PQP_REAL p[3], PQP_REAL q[3], PQP_REAL r[3])
00131 {
00132 PQP_REAL u[3], v[3], w[3];
00133
00134
00135 VmV(u, q, p);
00136 VmV(v, r, p);
00137 VcrossV(w, u, v);
00138 M.A = 0.5 * Vlength(w);
00139
00140 if (M.A == 0.0)
00141 {
00142
00143
00144
00145
00146
00147
00148 M.m[0] = (p[0] + q[0] + r[0]) /3;
00149 M.m[1] = (p[1] + q[1] + r[1]) /3;
00150 M.m[2] = (p[2] + q[2] + r[2]) /3;
00151
00152
00153 M.s[0][0] = (p[0]*p[0] + q[0]*q[0] + r[0]*r[0]);
00154 M.s[0][1] = (p[0]*p[1] + q[0]*q[1] + r[0]*r[1]);
00155 M.s[0][2] = (p[0]*p[2] + q[0]*q[2] + r[0]*r[2]);
00156 M.s[1][1] = (p[1]*p[1] + q[1]*q[1] + r[1]*r[1]);
00157 M.s[1][2] = (p[1]*p[2] + q[1]*q[2] + r[1]*r[2]);
00158 M.s[2][2] = (p[2]*p[2] + q[2]*q[2] + r[2]*r[2]);
00159 M.s[2][1] = M.s[1][2];
00160 M.s[1][0] = M.s[0][1];
00161 M.s[2][0] = M.s[0][2];
00162
00163 return;
00164 }
00165
00166
00167 M.m[0] = (p[0] + q[0] + r[0])/3;
00168 M.m[1] = (p[1] + q[1] + r[1])/3;
00169 M.m[2] = (p[2] + q[2] + r[2])/3;
00170
00171
00172 M.s[0][0] = M.A*(9*M.m[0]*M.m[0]+p[0]*p[0]+q[0]*q[0]+r[0]*r[0])/12;
00173 M.s[0][1] = M.A*(9*M.m[0]*M.m[1]+p[0]*p[1]+q[0]*q[1]+r[0]*r[1])/12;
00174 M.s[1][1] = M.A*(9*M.m[1]*M.m[1]+p[1]*p[1]+q[1]*q[1]+r[1]*r[1])/12;
00175 M.s[0][2] = M.A*(9*M.m[0]*M.m[2]+p[0]*p[2]+q[0]*q[2]+r[0]*r[2])/12;
00176 M.s[1][2] = M.A*(9*M.m[1]*M.m[2]+p[1]*p[2]+q[1]*q[2]+r[1]*r[2])/12;
00177 M.s[2][2] = M.A*(9*M.m[2]*M.m[2]+p[2]*p[2]+q[2]*q[2]+r[2]*r[2])/12;
00178 M.s[2][1] = M.s[1][2];
00179 M.s[1][0] = M.s[0][1];
00180 M.s[2][0] = M.s[0][2];
00181 }
00182
00183 inline
00184 void
00185 compute_moments(moment *M, Tri *tris, int num_tris)
00186 {
00187 int i;
00188
00189
00190
00191
00192 PQP_REAL Amin = 0.0;
00193 int zero = 0;
00194 int nonzero = 0;
00195 for(i=0; i<num_tris; i++)
00196 {
00197 compute_moment(M[i],
00198 tris[i].p1,
00199 tris[i].p2,
00200 tris[i].p3);
00201 if (M[i].A == 0.0)
00202 {
00203 zero = 1;
00204 }
00205 else
00206 {
00207 nonzero = 1;
00208 if (Amin == 0.0) Amin = M[i].A;
00209 else if (M[i].A < Amin) Amin = M[i].A;
00210 }
00211 }
00212
00213 if (zero)
00214 {
00215 fprintf(stderr, "----\n");
00216 fprintf(stderr, "Warning! Some triangles have zero area!\n");
00217 fprintf(stderr, "----\n");
00218
00219
00220
00221
00222
00223 if (Amin == 0.0) Amin = 1.0;
00224
00225 for(i=0; i<num_tris; i++)
00226 {
00227 if (M[i].A == 0.0) M[i].A = Amin;
00228 }
00229 }
00230 }
00231
00232 #else
00233
00234 PQP_REAL max(PQP_REAL a, PQP_REAL b, PQP_REAL c, PQP_REAL d)
00235 {
00236 PQP_REAL t = a;
00237 if (b > t) t = b;
00238 if (c > t) t = c;
00239 if (d > t) t = d;
00240 return t;
00241 }
00242
00243 PQP_REAL min(PQP_REAL a, PQP_REAL b, PQP_REAL c, PQP_REAL d)
00244 {
00245 PQP_REAL t = a;
00246 if (b < t) t = b;
00247 if (c < t) t = c;
00248 if (d < t) t = d;
00249 return t;
00250 }
00251
00252 void
00253 get_centroid_triverts(PQP_REAL c[3], Tri *tris, int num_tris)
00254 {
00255 int i;
00256
00257 c[0] = c[1] = c[2] = 0.0;
00258
00259
00260 for(i=0; i<num_tris; i++)
00261 {
00262 PQP_REAL *p1 = tris[i].p1;
00263 PQP_REAL *p2 = tris[i].p2;
00264 PQP_REAL *p3 = tris[i].p3;
00265
00266 c[0] += p1[0] + p2[0] + p3[0];
00267 c[1] += p1[1] + p2[1] + p3[1];
00268 c[2] += p1[2] + p2[2] + p3[2];
00269 }
00270
00271 PQP_REAL n = (PQP_REAL)(3 * num_tris);
00272
00273 c[0] /= n;
00274 c[1] /= n;
00275 c[2] /= n;
00276 }
00277
00278 void
00279 get_covariance_triverts(PQP_REAL M[3][3], Tri *tris, int num_tris)
00280 {
00281 int i;
00282 PQP_REAL S1[3];
00283 PQP_REAL S2[3][3];
00284
00285 S1[0] = S1[1] = S1[2] = 0.0;
00286 S2[0][0] = S2[1][0] = S2[2][0] = 0.0;
00287 S2[0][1] = S2[1][1] = S2[2][1] = 0.0;
00288 S2[0][2] = S2[1][2] = S2[2][2] = 0.0;
00289
00290
00291 for(i=0; i<num_tris; i++)
00292 {
00293 PQP_REAL *p1 = tris[i].p1;
00294 PQP_REAL *p2 = tris[i].p2;
00295 PQP_REAL *p3 = tris[i].p3;
00296
00297 S1[0] += p1[0] + p2[0] + p3[0];
00298 S1[1] += p1[1] + p2[1] + p3[1];
00299 S1[2] += p1[2] + p2[2] + p3[2];
00300
00301 S2[0][0] += (p1[0] * p1[0] +
00302 p2[0] * p2[0] +
00303 p3[0] * p3[0]);
00304 S2[1][1] += (p1[1] * p1[1] +
00305 p2[1] * p2[1] +
00306 p3[1] * p3[1]);
00307 S2[2][2] += (p1[2] * p1[2] +
00308 p2[2] * p2[2] +
00309 p3[2] * p3[2]);
00310 S2[0][1] += (p1[0] * p1[1] +
00311 p2[0] * p2[1] +
00312 p3[0] * p3[1]);
00313 S2[0][2] += (p1[0] * p1[2] +
00314 p2[0] * p2[2] +
00315 p3[0] * p3[2]);
00316 S2[1][2] += (p1[1] * p1[2] +
00317 p2[1] * p2[2] +
00318 p3[1] * p3[2]);
00319 }
00320
00321 PQP_REAL n = (PQP_REAL)(3 * num_tris);
00322
00323
00324
00325 M[0][0] = S2[0][0] - S1[0]*S1[0] / n;
00326 M[1][1] = S2[1][1] - S1[1]*S1[1] / n;
00327 M[2][2] = S2[2][2] - S1[2]*S1[2] / n;
00328 M[0][1] = S2[0][1] - S1[0]*S1[1] / n;
00329 M[1][2] = S2[1][2] - S1[1]*S1[2] / n;
00330 M[0][2] = S2[0][2] - S1[0]*S1[2] / n;
00331 M[1][0] = M[0][1];
00332 M[2][0] = M[0][2];
00333 M[2][1] = M[1][2];
00334 }
00335
00336 #endif
00337
00338
00339
00340
00341
00342
00343 int
00344 split_tris(Tri *tris, int num_tris, PQP_REAL a[3], PQP_REAL c)
00345 {
00346 int i;
00347 int c1 = 0;
00348 PQP_REAL p[3];
00349 PQP_REAL x;
00350 Tri temp;
00351
00352 for(i = 0; i < num_tris; i++)
00353 {
00354
00355
00356
00357
00358
00359
00360 VcV(p, tris[i].p1);
00361 VpV(p, p, tris[i].p2);
00362 VpV(p, p, tris[i].p3);
00363 x = VdotV(p, a);
00364 x /= 3.0;
00365 if (x <= c)
00366 {
00367
00368 temp = tris[i];
00369 tris[i] = tris[c1];
00370 tris[c1] = temp;
00371 c1++;
00372 }
00373 else
00374 {
00375
00376 }
00377 }
00378
00379
00380
00381 if ((c1 == 0) || (c1 == num_tris)) c1 = num_tris/2;
00382
00383 return c1;
00384 }
00385
00386
00387
00388
00389
00390 int
00391 build_recurse(PQP_Model *m, int bn, int first_tri, int num_tris)
00392 {
00393 BV *b = m->child(bn);
00394
00395
00396
00397 PQP_REAL C[3][3], E[3][3], R[3][3], s[3], axis[3], mean[3], coord;
00398
00399 #if RAPID2_FIT
00400 moment *tri_moment = new moment[num_tris];
00401 compute_moments(tri_moment, &(m->tris[first_tri]), num_tris);
00402 accum acc;
00403 clear_accum(acc);
00404 for(int i = 0; i < num_tris; i++) accum_moment(acc, tri_moment[i]);
00405 delete [] tri_moment;
00406 covariance_from_accum(C,acc);
00407 #else
00408 get_covariance_triverts(C,&m->tris[first_tri],num_tris);
00409 #endif
00410
00411 Meigen(E, s, C);
00412
00413
00414
00415 int min, mid, max;
00416 if (s[0] > s[1]) { max = 0; min = 1; }
00417 else { min = 0; max = 1; }
00418 if (s[2] < s[min]) { mid = min; min = 2; }
00419 else if (s[2] > s[max]) { mid = max; max = 2; }
00420 else { mid = 2; }
00421 McolcMcol(R,0,E,max);
00422 McolcMcol(R,1,E,mid);
00423 R[0][2] = E[1][max]*E[2][mid] - E[1][mid]*E[2][max];
00424 R[1][2] = E[0][mid]*E[2][max] - E[0][max]*E[2][mid];
00425 R[2][2] = E[0][max]*E[1][mid] - E[0][mid]*E[1][max];
00426
00427
00428
00429 b->FitToTris(R, &m->tris[first_tri], num_tris);
00430
00431 if (num_tris == 1)
00432 {
00433
00434
00435 b->first_child = -(first_tri + 1);
00436 }
00437 else if (num_tris > 1)
00438 {
00439
00440
00441 b->first_child = m->num_bvs;
00442 m->num_bvs+=2;
00443
00444
00445
00446 McolcV(axis,R,0);
00447
00448 #if RAPID2_FIT
00449 mean_from_accum(mean,acc);
00450 #else
00451 get_centroid_triverts(mean,&m->tris[first_tri],num_tris);
00452 #endif
00453 coord = VdotV(axis, mean);
00454
00455
00456
00457 int num_first_half = split_tris(&m->tris[first_tri], num_tris,
00458 axis, coord);
00459
00460
00461
00462 build_recurse(m, m->child(bn)->first_child, first_tri, num_first_half);
00463 build_recurse(m, m->child(bn)->first_child + 1,
00464 first_tri + num_first_half, num_tris - num_first_half);
00465 }
00466 return PQP_OK;
00467 }
00468
00469
00470
00471
00472 void
00473 make_parent_relative(PQP_Model *m, int bn,
00474 const PQP_REAL parentR[3][3]
00475 #if PQP_BV_TYPE & RSS_TYPE
00476 ,const PQP_REAL parentTr[3]
00477 #endif
00478 #if PQP_BV_TYPE & OBB_TYPE
00479 ,const PQP_REAL parentTo[3]
00480 #endif
00481 )
00482 {
00483 PQP_REAL Rpc[3][3], Tpc[3];
00484
00485 if (!m->child(bn)->Leaf())
00486 {
00487
00488
00489 make_parent_relative(m,m->child(bn)->first_child,
00490 m->child(bn)->R
00491 #if PQP_BV_TYPE & RSS_TYPE
00492 ,m->child(bn)->Tr
00493 #endif
00494 #if PQP_BV_TYPE & OBB_TYPE
00495 ,m->child(bn)->To
00496 #endif
00497 );
00498 make_parent_relative(m,m->child(bn)->first_child+1,
00499 m->child(bn)->R
00500 #if PQP_BV_TYPE & RSS_TYPE
00501 ,m->child(bn)->Tr
00502 #endif
00503 #if PQP_BV_TYPE & OBB_TYPE
00504 ,m->child(bn)->To
00505 #endif
00506 );
00507 }
00508
00509
00510
00511 MTxM(Rpc,parentR,m->child(bn)->R);
00512 McM(m->child(bn)->R,Rpc);
00513 #if PQP_BV_TYPE & RSS_TYPE
00514 VmV(Tpc,m->child(bn)->Tr,parentTr);
00515 MTxV(m->child(bn)->Tr,parentR,Tpc);
00516 #endif
00517 #if PQP_BV_TYPE & OBB_TYPE
00518 VmV(Tpc,m->child(bn)->To,parentTo);
00519 MTxV(m->child(bn)->To,parentR,Tpc);
00520 #endif
00521
00522 }
00523
00524 int
00525 build_model(PQP_Model *m)
00526 {
00527
00528
00529 m->num_bvs = 1;
00530
00531
00532
00533 build_recurse(m, 0, 0, m->num_tris);
00534
00535
00536
00537 PQP_REAL R[3][3],T[3];
00538 Midentity(R);
00539 Videntity(T);
00540
00541 make_parent_relative(m,0,R
00542 #if PQP_BV_TYPE & RSS_TYPE
00543 ,T
00544 #endif
00545 #if PQP_BV_TYPE & OBB_TYPE
00546 ,T
00547 #endif
00548 );
00549
00550 return PQP_OK;
00551 }