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
00042 #ifndef lint
00043 static const char RCSmetaball[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_metaball.c,v 14.17 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00044 #endif
00045
00046 #include "common.h"
00047
00048 #include <stddef.h>
00049 #include <stdio.h>
00050 #ifdef HAVE_STRING_H
00051 # include <string.h>
00052 #else
00053 # include <strings.h>
00054 #endif
00055 #include <math.h>
00056
00057 #include "machine.h"
00058 #include "vmath.h"
00059 #include "db.h"
00060 #include "nmg.h"
00061 #include "raytrace.h"
00062 #include "nurb.h"
00063 #include "rtgeom.h"
00064 #include "wdb.h"
00065 #include "./debug.h"
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 fastf_t rt_metaball_get_bounding_sphere(point_t *center, fastf_t threshold, struct bu_list *points)
00076 {
00077 struct wdb_metaballpt *mbpt, *mbpt2;
00078 point_t min, max, d;
00079 fastf_t r = 0.0, dist, mag;
00080 int i;
00081
00082
00083 VSETALL(min,+INFINITY);
00084 VSETALL(max,-INFINITY);
00085 for(BU_LIST_FOR(mbpt, wdb_metaballpt, points))
00086 for(i=0;i<3;i++) {
00087 if(mbpt->coord[i] < min[i])
00088 min[i] = mbpt->coord[i];
00089 if (mbpt->coord[i] > max[i])
00090 max[i] = mbpt->coord[i];
00091 }
00092
00093
00094 VADD2(*center, min, max);
00095 VSCALE(*center, *center, 0.5);
00096
00097
00098 for(BU_LIST_FOR(mbpt, wdb_metaballpt, points)){
00099 VSUB2(d,mbpt->coord,*center);
00100
00101
00102 dist = MAGNITUDE(d) + mbpt->fldstr/threshold;
00103
00104 for(BU_LIST_FOR(mbpt2, wdb_metaballpt, points))
00105 if(mbpt2 != mbpt){
00106 fastf_t additive;
00107 VSUB2(d, mbpt2->coord, mbpt->coord);
00108 mag = MAGNITUDE(d) + dist;
00109 additive = (mbpt2->fldstr*mbpt2->fldstr) / mag;
00110 dist += additive;
00111 }
00112
00113 if(dist > r)
00114 r = dist;
00115 }
00116 return r;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125 int
00126 rt_metaball_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00127 {
00128 struct rt_metaball_internal *mb, *nmb;
00129 struct wdb_metaballpt *mbpt, *nmbpt;
00130 int i;
00131
00132 mb = ip->idb_ptr;
00133 RT_METABALL_CK_MAGIC(mb);
00134
00135
00136 nmb = bu_malloc(sizeof(struct rt_metaball_internal), "rt_metaball_prep: nmb");
00137 BU_LIST_INIT( &nmb->metaball_ctrl_head );
00138 nmb->threshold = mb->threshold;
00139
00140
00141 for(BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) {
00142 nmbpt = (struct wdb_metaballpt *)bu_malloc(sizeof(struct wdb_metaballpt), "rt_metaball_prep: nmbpt");
00143 nmbpt->fldstr = mbpt->fldstr;
00144 VMOVE(nmbpt->coord,mbpt->coord);
00145 BU_LIST_INSERT( &nmb->metaball_ctrl_head, &nmbpt->l );
00146 }
00147
00148
00149 stp->st_aradius = rt_metaball_get_bounding_sphere(&stp->st_center, mb->threshold, &mb->metaball_ctrl_head);
00150 stp->st_bradius = stp->st_aradius * 1.01;
00151
00152
00153 VSET(stp->st_min,
00154 stp->st_center[X] - stp->st_aradius,
00155 stp->st_center[Y] - stp->st_aradius,
00156 stp->st_center[Z] - stp->st_aradius);
00157 VSET(stp->st_max,
00158 stp->st_center[X] + stp->st_aradius,
00159 stp->st_center[Y] + stp->st_aradius,
00160 stp->st_center[Z] + stp->st_aradius);
00161 stp->st_specific = (void *)nmb;
00162 return 0;
00163 }
00164
00165
00166
00167
00168 void
00169 rt_metaball_print(register const struct soltab *stp)
00170 {
00171 bu_log("rt_metaball_print called\n");
00172 return;
00173 }
00174
00175 fastf_t
00176 rt_metaball_point_value(point_t *p, struct bu_list *points)
00177 {
00178 struct wdb_metaballpt *mbpt;
00179 fastf_t ret = 0.0;
00180 point_t v;
00181
00182 for(BU_LIST_FOR(mbpt, wdb_metaballpt, points)) {
00183 VSUB2(v, mbpt->coord, *p);
00184 ret += (mbpt->fldstr*mbpt->fldstr) / MAGSQ(v);
00185 }
00186 return ret;
00187 }
00188
00189
00190
00191
00192 int
00193 rt_metaball_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00194 {
00195 int stat=0, retval = 0, segsleft = abs(ap->a_onehit);
00196 struct rt_metaball_internal *mb = (struct rt_metaball_internal *)stp->st_specific;
00197 struct seg *segp = NULL;
00198 point_t p, inc, delta;
00199 fastf_t initstep = stp->st_aradius / 20.0, finalstep = stp->st_aradius / 1e8, step = initstep, distleft = (rp->r_max-rp->r_min);
00200
00201 VJOIN1(p, rp->r_pt, rp->r_min, rp->r_dir);
00202 VSCALE(inc, rp->r_dir, step);
00203
00204
00205
00206
00207 #define STEPBACK { distleft += step; VSUB2(p, p, inc); step *= .5; VSCALE(inc,inc,.5); }
00208 #define STEPIN(x) { --segsleft; ++retval; VSUB2(delta, p, rp->r_pt); segp->seg_##x.hit_dist = MAGNITUDE(delta); }
00209 while( distleft >= 0.0 ) {
00210 distleft -= step;
00211 VADD2(p, p, inc);
00212 if(stat == 1) {
00213 if(rt_metaball_point_value(&p, &mb->metaball_ctrl_head) < mb->threshold ) {
00214 if(step<=finalstep) {
00215 STEPIN(out);
00216 stat = 0;
00217 if(segsleft <= 0) {
00218 return retval;
00219 }
00220 } else
00221 STEPBACK
00222 }
00223 } else {
00224 if(rt_metaball_point_value(&p, &mb->metaball_ctrl_head) > mb->threshold ) {
00225 if(step<=finalstep) {
00226 RT_GET_SEG(segp, ap->a_resource);
00227 segp->seg_stp = stp;
00228 STEPIN(in);
00229 segp->seg_out.hit_dist = segp->seg_in.hit_dist + .1;
00230 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00231 if(segsleft <= 0){
00232 return retval;
00233 }
00234
00235 stat = 1;
00236 VSUB2(p, p, inc);
00237 VSCALE(inc, rp->r_dir, step);
00238 step = initstep;
00239 } else
00240 STEPBACK
00241 }
00242 }
00243 }
00244 #undef STEPBACK
00245 #undef STEPIN
00246 return retval;
00247 }
00248
00249
00250
00251
00252
00253
00254 void
00255 rt_metaball_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00256 {
00257 struct rt_metaball_internal *mb = stp->st_specific;
00258 struct wdb_metaballpt *mbpt;
00259 vect_t v;
00260 fastf_t f, a;
00261
00262 VSETALL(hitp->hit_normal, 0);
00263 for(BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)){
00264 VSUB2(v, hitp->hit_point, mbpt->coord);
00265 f = mbpt->fldstr * mbpt->fldstr;
00266 a = MAGNITUDE(v);
00267 f /= (a*a*a);
00268 VUNITIZE(v);
00269 VJOIN1(hitp->hit_normal, hitp->hit_normal, f, v);
00270 }
00271 VUNITIZE(hitp->hit_normal);
00272 return;
00273 }
00274
00275
00276
00277
00278
00279
00280 void
00281 rt_metaball_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00282 {
00283 bu_log("called rt_metaball_curve!\n");
00284 return;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 void
00297 rt_metaball_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00298 {
00299 bu_log("called rt_metaball_uv!\n");
00300 return;
00301 }
00302
00303
00304
00305
00306 void
00307 rt_metaball_free(register struct soltab *stp)
00308 {
00309
00310 bu_log("rt_metaball_free called\n");
00311 return;
00312 }
00313
00314
00315
00316 int
00317 rt_metaball_class(void)
00318 {
00319 return RT_CLASSIFY_UNIMPLEMENTED;
00320 }
00321
00322
00323 void
00324 rt_metaball_plot_sph(struct bu_list *vhead, point_t *center, fastf_t radius)
00325 {
00326 fastf_t top[16*3], middle[16*3], bottom[16*3];
00327 point_t a, b, c;
00328 int i;
00329
00330 VSET(a, radius, 0, 0);
00331 VSET(b, 0, radius, 0);
00332 VSET(c, 0, 0, radius);
00333 rt_ell_16pts( top, *center, a, b );
00334 rt_ell_16pts( bottom, *center, b, c );
00335 rt_ell_16pts( middle, *center, a, c );
00336
00337 RT_ADD_VLIST( vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
00338 for( i=0; i<16; i++ ) RT_ADD_VLIST( vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00339 RT_ADD_VLIST( vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
00340 for( i=0; i<16; i++ ) RT_ADD_VLIST( vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00341 RT_ADD_VLIST( vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
00342 for( i=0; i<16; i++ ) RT_ADD_VLIST( vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00343 }
00344
00345
00346
00347
00348 int
00349 rt_metaball_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00350 {
00351 struct rt_metaball_internal *mb;
00352 struct wdb_metaballpt *mbpt;
00353 point_t bsc;
00354 fastf_t rad;
00355
00356 RT_CK_DB_INTERNAL(ip);
00357 mb = (struct rt_metaball_internal *)ip->idb_ptr;
00358 RT_METABALL_CK_MAGIC(mb);
00359 rad = rt_metaball_get_bounding_sphere(&bsc, mb->threshold, &mb->metaball_ctrl_head);
00360 rt_metaball_plot_sph(vhead, &bsc, rad);
00361 for(BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
00362 rt_metaball_plot_sph(vhead, &mbpt->coord, mbpt->fldstr);
00363 return 0;
00364 }
00365
00366
00367
00368
00369
00370
00371 int
00372 rt_metaball_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00373 {
00374 bu_log("rt_metaball_tess called!\n");
00375 return -1;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 int
00385 rt_metaball_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00386 {
00387 struct wdb_metaballpt *mbpt;
00388 struct rt_metaball_internal *mb;
00389 fastf_t *buf;
00390 int metaball_count = 0, i;
00391
00392 BU_CK_EXTERNAL( ep );
00393 metaball_count = bu_glong((unsigned char *)ep->ext_buf);
00394 buf = (fastf_t *)bu_malloc((metaball_count*4+2)*SIZEOF_NETWORK_DOUBLE,"rt_metaball_import5: buf");
00395 ntohd((unsigned char *)buf, (unsigned char *)ep->ext_buf+SIZEOF_NETWORK_LONG, metaball_count*4+2);
00396
00397 RT_CK_DB_INTERNAL( ip );
00398 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00399 ip->idb_type = ID_METABALL;
00400 ip->idb_meth = &rt_functab[ID_METABALL];
00401 ip->idb_ptr = bu_malloc( sizeof(struct rt_metaball_internal), "rt_metaball_internal");
00402 mb = (struct rt_metaball_internal *)ip->idb_ptr;
00403 mb->magic = RT_METABALL_INTERNAL_MAGIC;
00404 mb->threshold = buf[0];
00405 mb->method = ((long *)buf)[1];
00406 BU_LIST_INIT( &mb->metaball_ctrl_head );
00407 for(i=2 ; i<=metaball_count*4 ; i+=4) {
00408
00409 BU_GETSTRUCT( mbpt, wdb_metaballpt );
00410 mbpt->l.magic = WDB_METABALLPT_MAGIC;
00411 MAT4X3PNT( mbpt->coord, mat, &buf[i] );
00412 mbpt->fldstr = buf[i+3] / mat[15];
00413 BU_LIST_INSERT( &mb->metaball_ctrl_head, &mbpt->l );
00414 }
00415
00416 bu_free((genptr_t)buf, "rt_metaball_import5: buf");
00417 return 0;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 int
00435 rt_metaball_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00436 {
00437 struct rt_metaball_internal *mb;
00438 struct wdb_metaballpt *mbpt;
00439 int metaball_count = 0, i = 2;
00440 fastf_t *buf;
00441
00442 RT_CK_DB_INTERNAL(ip);
00443 if( ip->idb_type != ID_METABALL )
00444 return(-1);
00445 mb = (struct rt_metaball_internal *)ip->idb_ptr;
00446 RT_METABALL_CK_MAGIC(mb);
00447 if (mb->metaball_ctrl_head.magic == 0) return -1;
00448
00449
00450 for(BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) metaball_count++;
00451
00452 BU_CK_EXTERNAL(ep);
00453 ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE*(1+4*metaball_count) + 2*SIZEOF_NETWORK_LONG;
00454 ep->ext_buf = (genptr_t)bu_malloc(ep->ext_nbytes, "metaball external");
00455 bu_plong((unsigned char *)ep->ext_buf, metaball_count);
00456
00457
00458 buf = (fastf_t *)bu_malloc((metaball_count*4+1)*SIZEOF_NETWORK_DOUBLE,"rt_metaball_export5: buf");
00459 buf[0] = mb->threshold;
00460 ((long *)buf)[1] = mb->method;
00461 for(BU_LIST_FOR( mbpt, wdb_metaballpt, &mb->metaball_ctrl_head), i+=4){
00462 VSCALE(&buf[i], mbpt->coord, local2mm);
00463 buf[i+3] = mbpt->fldstr * local2mm;
00464 }
00465 htond((unsigned char *)ep->ext_buf + SIZEOF_NETWORK_LONG, (unsigned char *)buf, 2 + 4 * metaball_count);
00466 bu_free(buf,"rt_metaball_export5: buf");
00467
00468 return 0;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478 int
00479 rt_metaball_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
00480 {
00481 int metaball_count = 0;
00482 char buf[BUFSIZ];
00483 struct rt_metaball_internal *mb;
00484 struct wdb_metaballpt *mbpt;
00485
00486 RT_CK_DB_INTERNAL(ip);
00487 mb = (struct rt_metaball_internal *)ip->idb_ptr;
00488 RT_METABALL_CK_MAGIC(mb);
00489 for(BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) metaball_count++;
00490
00491 snprintf(buf, BUFSIZ, "Metaball with %d points and a threshold of %g\n", metaball_count, mb->threshold);
00492 bu_vls_strcat(str,buf);
00493 if(!verbose)return 0;
00494 metaball_count=0;
00495 for( BU_LIST_FOR( mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)){
00496 snprintf(buf,BUFSIZ,"\t%d: %g field strength at (%g, %g, %g)\n",
00497 ++metaball_count, mbpt->fldstr, V3ARGS(mbpt->coord));
00498 bu_vls_strcat(str,buf);
00499 }
00500 return 0;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 void
00510 rt_metaball_ifree(struct rt_db_internal *ip)
00511 {
00512 register struct rt_metaball_internal *metaball;
00513 register struct wdb_metaballpt *mbpt;
00514
00515 RT_CK_DB_INTERNAL(ip);
00516 metaball = (struct rt_metaball_internal*)ip->idb_ptr;
00517 RT_METABALL_CK_MAGIC(metaball);
00518
00519 if (metaball->metaball_ctrl_head.magic != 0)
00520 while(BU_LIST_WHILE(mbpt, wdb_metaballpt, &metaball->metaball_ctrl_head)) {
00521 BU_LIST_DEQUEUE(&(mbpt->l));
00522 bu_free((char *)mbpt, "wdb_metaballpt");
00523 }
00524 bu_free( ip->idb_ptr, "metaball ifree" );
00525 ip->idb_ptr = GENPTR_NULL;
00526 }
00527
00528
00529
00530
00531 int
00532 rt_metaball_tnurb(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct bn_tol *tol)
00533 {
00534 bu_log("rt_metaball_tnurb called!\n");
00535 return 0;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546