BRL-CAD
sph.c
Go to the documentation of this file.
1 /* S P H . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1985-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup primitives */
21 /** @{ */
22 /** @file primitives/sph/sph.c
23  *
24  * Intersect a ray with a Sphere.
25  * Special case of the Generalized Ellipsoid
26  *
27  */
28 /** @} */
29 
30 #include "common.h"
31 
32 #include <string.h>
33 #include <math.h>
34 
35 #include "bio.h"
36 
37 #include "vmath.h"
38 #include "rtgeom.h"
39 #include "raytrace.h"
40 
41 
42 /*
43  * Algorithm:
44  *
45  * Given V, A, where |A| = Radius, there is a set of points on this sphere
46  *
47  * { (x, y, z) | (x, y, z) is on sphere defined by V, A }
48  *
49  * To find the intersection of a line with the sphere, consider
50  * the parametric line L:
51  *
52  * L : { P(n) | P + t(n) . D }
53  *
54  * Call W the actual point of intersection between L and the sphere.
55  *
56  * NORMALS. Given the point W on the sphere, what is the vector
57  * normal to the tangent plane at that point?
58  *
59  * N = (W - V) / |A|
60  */
61 
62 struct sph_specific {
63  vect_t sph_V; /* Vector to center of sphere */
64  fastf_t sph_radsq; /* Radius squared */
65  fastf_t sph_invrad; /* Inverse radius (for normal) */
66  fastf_t sph_rad; /* Radius */
67  mat_t sph_SoR; /* Rotate and scale for UV mapping */
68 };
69 
70 #ifdef USE_OPENCL
71 
72 #include <CL/cl.h>
73 
74 #ifndef CL_VERSION_1_2
75 /* #error "Requires OpenCL 1.2." */
76 #endif
77 
78 #ifdef CLT_SINGLE_PRECISION
79 #define cl_double cl_float
80 #define cl_double3 cl_float3
81 #endif
82 
83 struct AlignedPtr
84 {
85  void *alloc;
86  void *ptr;
87 };
88 
89 
90 inline struct AlignedPtr
91 aligned_malloc(size_t alignment, size_t size)
92 {
93  struct AlignedPtr ap;
94  ap.alloc = bu_malloc(size + alignment - 1, "failed to allocate memory in aligned_malloc()");
95  ap.ptr = (void *)(((uintptr_t)ap.alloc + alignment - 1) / alignment*alignment);
96  return ap;
97 }
98 
99 
100 #define ALIGNED_SET(name, type, value) \
101  {(name) = aligned_malloc(sizeof(type), sizeof(type));\
102  *((type *)name.ptr) = (value);}
103 
104 
105 
106 const int clt_semaphore = 12; /* FIXME: for testing; this isn't our semaphore */
107 static int clt_initialized = 0;
108 static cl_device_id clt_device;
109 static cl_context clt_context;
110 static cl_command_queue clt_queue;
111 static cl_program clt_program;
112 static cl_kernel clt_kernel;
113 
114 
115 static void
116 clt_cleanup()
117 {
118  if (!clt_initialized) return;
119 
120  clReleaseKernel(clt_kernel);
121  clReleaseCommandQueue(clt_queue);
122  clReleaseProgram(clt_program);
123  clReleaseContext(clt_context);
124 
125  clt_initialized = 0;
126 }
127 
128 
129 /* for now, just get the first device from the first platform */
130 static cl_device_id
131 clt_get_cl_device()
132 {
133  cl_int error;
134  cl_platform_id platform;
135  cl_device_id device;
136  int using_cpu = 0;
137 
138  error = clGetPlatformIDs(1, &platform, NULL);
139  if (error != CL_SUCCESS) bu_bomb("failed to find an OpenCL platform");
140 
141  error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
142  if (error == CL_DEVICE_NOT_FOUND) {
143  using_cpu = 1;
144  error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, &device, NULL);
145  }
146  if (error != CL_SUCCESS) bu_bomb("failed to find an OpenCL device (using this method)");
147 
148  if (using_cpu) bu_log("clt: no GPU devices available; using CPU for OpenCL\n");
149 
150  return device;
151 }
152 
153 
154 static char *
155 clt_read_code(size_t *length)
156 {
157  const char * const code_path = "sph_shot.cl";
158  FILE *fp;
159  char *data;
160 
161  fp = fopen(code_path , "r");
162  if (!fp) bu_bomb("failed to read OpenCL code");
163 
164  fseek(fp, 0, SEEK_END);
165  *length = ftell(fp);
166  rewind(fp);
167 
168  data = bu_malloc((*length+1)*sizeof(char), "failed bu_malloc() in clt_read_code()");
169 
170  if(fread(data, *length, 1, fp) != 1)
171  bu_bomb("failed to read OpenCL code");
172 
173  fclose(fp);
174  return data;
175 }
176 
177 
178 
179 
180 static cl_program
181 clt_get_program(cl_context context, cl_device_id device)
182 {
183  cl_int error;
184  cl_program program;
185  size_t code_length;
186  char *code = clt_read_code(&code_length);
187  const char *pc_code = code;
188 
189  program = clCreateProgramWithSource(context, 1, &pc_code, &code_length, &error);
190  if (error != CL_SUCCESS) bu_bomb("failed to create OpenCL program");
191 
192  error = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
193  if (error != CL_SUCCESS) {
194  size_t log_size;
195  char *log_data;
196  clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
197  log_data = bu_malloc(log_size*sizeof(char), "failed to allocate memory for log");
198  clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size+1, log_data, NULL);
199  bu_log("BUILD LOG:\n%s\n", log_data);
200  bu_bomb("failed to build OpenCL program");
201  }
202 
203  bu_free(code, "failed bu_free() in clt_get_program()");
204  return program;
205 }
206 
207 
208 
209 static void
210 clt_init()
211 {
212  cl_int error;
213 
214  bu_semaphore_acquire(clt_semaphore);
215  if (clt_initialized) {
216  bu_semaphore_release(clt_semaphore);
217  return;
218  }
219 
220  clt_initialized = 1;
221  atexit(clt_cleanup);
222 
223  clt_device = clt_get_cl_device();
224 
225  clt_context = clCreateContext(NULL, 1, &clt_device, NULL, NULL, &error);
226  if (error != CL_SUCCESS) bu_bomb("failed to create an OpenCL context");
227 
228  clt_queue = clCreateCommandQueue(clt_context, clt_device, 0, &error);
229  if (error != CL_SUCCESS) bu_bomb("failed to create an OpenCL command queue");
230 
231  clt_program = clt_get_program(clt_context, clt_device);
232 
233  clt_kernel = clCreateKernel(clt_program, "sph_shot", &error);
234  if (error != CL_SUCCESS) bu_bomb("failed to create an OpenCL kernel");
235 
236  bu_semaphore_release(clt_semaphore);
237 }
238 
239 
240 static cl_double3
241 clt_shot(cl_double3 o, cl_double3 dir, cl_double3 V, cl_double radsq, size_t hypersample)
242 {
243  const char * const bu_free_error = "failed bu_free() in clt_shot()";
244  cl_int error;
245  cl_mem output;
246  cl_double3 result;
247  struct AlignedPtr a_result, a_o, a_dir, a_V, a_radsq;
248 
249  VSET(result.s, 0, 0, 0);
250  ALIGNED_SET(a_result, cl_double3, result);
251  ALIGNED_SET(a_o, cl_double3, o);
252  ALIGNED_SET(a_dir, cl_double3, dir);
253  ALIGNED_SET(a_V, cl_double3, V);
254  ALIGNED_SET(a_radsq, cl_double, radsq);
255 
256  output = clCreateBuffer(clt_context, CL_MEM_COPY_HOST_PTR | CL_MEM_WRITE_ONLY,
257  sizeof(cl_double3), a_result.ptr, &error);
258  if (error != CL_SUCCESS) bu_bomb("failed to create OpenCL output buffer");
259 
260  bu_semaphore_acquire(clt_semaphore);
261  error = clSetKernelArg(clt_kernel, 0, sizeof(cl_mem), &output);
262  error |= clSetKernelArg(clt_kernel, 1, sizeof(cl_double3), a_o.ptr);
263  error |= clSetKernelArg(clt_kernel, 2, sizeof(cl_double3), a_dir.ptr);
264  error |= clSetKernelArg(clt_kernel, 3, sizeof(cl_double3), a_V.ptr);
265  error |= clSetKernelArg(clt_kernel, 4, sizeof(cl_double), a_radsq.ptr);
266  if (error != CL_SUCCESS) bu_bomb("failed to set OpenCL kernel arguments");
267  error = clEnqueueNDRangeKernel(clt_queue, clt_kernel, 1, NULL, &hypersample, NULL, 0, NULL, NULL);
268  bu_semaphore_release(clt_semaphore);
269  if (error != CL_SUCCESS) bu_bomb("failed to enqueue OpenCL kernel");
270 
271  if (clFinish(clt_queue) != CL_SUCCESS) bu_bomb("failure in clFinish()");
272  clEnqueueReadBuffer(clt_queue, output, CL_TRUE, 0, sizeof(cl_double3), &result, 0, NULL, NULL);
273  clReleaseMemObject(output);
274  bu_free(a_result.alloc, bu_free_error);
275  bu_free(a_o.alloc, bu_free_error);
276  bu_free(a_dir.alloc, bu_free_error);
277  bu_free(a_V.alloc, bu_free_error);
278  bu_free(a_radsq.alloc, bu_free_error);
279 
280  return result;
281 }
282 #endif /* USE_OPENCL */
283 
284 
285 /**
286  * Given a pointer to a GED database record, and a transformation matrix,
287  * determine if this is a valid sphere, and if so, precompute various
288  * terms of the formula.
289  *
290  * Returns -
291  * 0 SPH is OK
292  * !0 Error in description
293  *
294  * Implicit return -
295  * A struct sph_specific is created, and its address is stored in
296  * stp->st_specific for use by rt_sph_shot().
297  * If the ELL is really a SPH, stp->st_id is modified to ID_SPH.
298  */
299 int
300 rt_sph_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
301 {
302  register struct sph_specific *sph;
303  fastf_t magsq_a, magsq_b, magsq_c;
304  vect_t Au, Bu, Cu; /* A, B, C with unit length */
305  fastf_t f;
306  struct rt_ell_internal *eip;
307 
308  eip = (struct rt_ell_internal *)ip->idb_ptr;
309  RT_ELL_CK_MAGIC(eip);
310 
311 #ifdef USE_OPENCL
312  clt_init();
313 #endif
314 
315  /* Validate that |A| > 0, |B| > 0, |C| > 0 */
316  magsq_a = MAGSQ(eip->a);
317  magsq_b = MAGSQ(eip->b);
318  magsq_c = MAGSQ(eip->c);
319  if (magsq_a < rtip->rti_tol.dist_sq || magsq_b < rtip->rti_tol.dist_sq || magsq_c < rtip->rti_tol.dist_sq) {
320  bu_log("rt_sph_prep(): sph(%s) zero length A(%g), B(%g), or C(%g) vector\n",
321  stp->st_name, magsq_a, magsq_b, magsq_c);
322  return 1; /* BAD */
323  }
324 
325  /* Validate that |A|, |B|, and |C| are nearly equal */
326  if (!NEAR_EQUAL(magsq_a, magsq_b, rtip->rti_tol.dist_sq)
327  || !NEAR_EQUAL(magsq_a, magsq_c, rtip->rti_tol.dist_sq)) {
328  return 1; /* ELL, not SPH */
329  }
330 
331  /* Create unit length versions of A, B, C */
332  f = 1.0/sqrt(magsq_a);
333  VSCALE(Au, eip->a, f);
334  f = 1.0/sqrt(magsq_b);
335  VSCALE(Bu, eip->b, f);
336  f = 1.0/sqrt(magsq_c);
337  VSCALE(Cu, eip->c, f);
338 
339  /* Validate that A.B == 0, B.C == 0, A.C == 0 (check dir only) */
340  f = VDOT(Au, Bu);
341  if (! NEAR_ZERO(f, rtip->rti_tol.dist)) {
342  bu_log("rt_sph_prep(): sph(%s) A not perpendicular to B, f=%f\n", stp->st_name, f);
343  return 1; /* BAD */
344  }
345  f = VDOT(Bu, Cu);
346  if (! NEAR_ZERO(f, rtip->rti_tol.dist)) {
347  bu_log("rt_sph_prep(): sph(%s) B not perpendicular to C, f=%f\n", stp->st_name, f);
348  return 1; /* BAD */
349  }
350  f = VDOT(Au, Cu);
351  if (! NEAR_ZERO(f, rtip->rti_tol.dist)) {
352  bu_log("rt_sph_prep(): sph(%s) A not perpendicular to C, f=%f\n", stp->st_name, f);
353  return 1; /* BAD */
354  }
355 
356  /*
357  * This ELL is really an SPH
358  */
359  stp->st_id = ID_SPH; /* "fix" soltab ID */
360  stp->st_meth = &OBJ[ID_SPH];
361 
362  /* Solid is OK, compute constant terms now */
363  BU_GET(sph, struct sph_specific);
364  stp->st_specific = (void *)sph;
365 
366  VMOVE(sph->sph_V, eip->v);
367 
368  sph->sph_radsq = magsq_a;
369  sph->sph_rad = sqrt(sph->sph_radsq);
370  sph->sph_invrad = 1.0 / sph->sph_rad;
371 
372  /*
373  * Save the matrix which rotates our ABC to world
374  * XYZ respectively, and scales points on surface
375  * to unit length. Used here in UV mapping.
376  * See ell.c for details.
377  */
378  MAT_IDN(sph->sph_SoR);
379  VSCALE(&sph->sph_SoR[0], eip->a, 1.0/magsq_a);
380  VSCALE(&sph->sph_SoR[4], eip->b, 1.0/magsq_b);
381  VSCALE(&sph->sph_SoR[8], eip->c, 1.0/magsq_c);
382 
383  /* Compute bounding sphere */
384  VMOVE(stp->st_center, sph->sph_V);
385  stp->st_aradius = stp->st_bradius = sph->sph_rad;
386 
387  /* Compute bounding RPP */
388  if (stp->st_meth->ft_bbox(ip, &(stp->st_min), &(stp->st_max), &(rtip->rti_tol))) return 1;
389  return 0; /* OK */
390 }
391 
392 
393 void
394 rt_sph_print(register const struct soltab *stp)
395 {
396  register const struct sph_specific *sph =
397  (struct sph_specific *)stp->st_specific;
398 
399  VPRINT("V", sph->sph_V);
400  bu_log("Rad %g\n", sph->sph_rad);
401  bu_log("Radsq %g\n", sph->sph_radsq);
402  bu_log("Invrad %g\n", sph->sph_invrad);
403  bn_mat_print("S o R", sph->sph_SoR);
404 }
405 
406 
407 /**
408  * Intersect a ray with a sphere. If an intersection occurs, a struct
409  * seg will be acquired and filled in.
410  *
411  * Notes: In the quadratic equation, A is MAGSQ(r_dir) which is always
412  * equal to 1, so it does not appear. The sign of B is reversed
413  * (vector is reversed) to save negation. We have factored out the 2
414  * and 4 constants.
415  *
416  * Claim: The straight quadratic formula leads to precision problems
417  * if either A or C are small. In our case A is always 1. C is a
418  * radial distance of the ray origin from the sphere surface. Thus if
419  * we are shooting from near the surface we may have problems. XXX -
420  * investigate this.
421  *
422  * Returns -
423  * 0 MISS
424  * >0 HIT
425  */
426 int
427 rt_sph_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
428 {
429 #ifdef USE_OPENCL
430  const size_t hypersample = 1;
431  cl_double3 o; /* ray origin */
432  cl_double3 dir; /* ray direction (unit vector) */
433  cl_double3 V; /* vector to sphere */
434  cl_double radsq; /* sphere radius squared */
435  cl_double3 result;
436  struct seg *segp;
437 
438  (void)rp; (void)ap;
439 
440  VMOVE(o.s, rp->r_pt);
441  VMOVE(dir.s, rp->r_dir);
442  VMOVE(V.s, ((struct sph_specific *)stp->st_specific)->sph_V);
443  radsq = ((struct sph_specific *)stp->st_specific)->sph_radsq;
444  result = clt_shot(o, dir, V, radsq, hypersample);
445 
446  if (EQUAL(result.s[0], 0)) return 0; /* no hit */
447 
448  RT_GET_SEG(segp, ap->a_resource);
449  segp->seg_stp = stp;
450 
451  segp->seg_in.hit_dist = result.s[0];
452  segp->seg_out.hit_dist = result.s[1];
453  segp->seg_in.hit_surfno = 0;
454  segp->seg_out.hit_surfno = 0;
455  BU_LIST_INSERT(&(seghead->l), &(segp->l));
456  return 2; /* HIT */
457 
458 #else
459  register struct sph_specific *sph =
460  (struct sph_specific *)stp->st_specific;
461  register struct seg *segp;
462 
463  vect_t ov; /* ray origin to center (V - P) */
464  fastf_t magsq_ov; /* length squared of ov */
465  fastf_t b; /* second term of quadratic eqn */
466  fastf_t root; /* root of radical */
467 
468  VSUB2(ov, sph->sph_V, rp->r_pt);
469  b = VDOT(rp->r_dir, ov);
470  magsq_ov = MAGSQ(ov);
471 
472  if (magsq_ov >= sph->sph_radsq) {
473  /* ray origin is outside of sphere */
474  if (b < 0) {
475  /* ray direction is away from sphere */
476  return 0; /* No hit */
477  }
478  root = b*b - magsq_ov + sph->sph_radsq;
479  if (root <= 0) {
480  /* no real roots */
481  return 0; /* No hit */
482  }
483  } else {
484  root = b*b - magsq_ov + sph->sph_radsq;
485  }
486  root = sqrt(root);
487 
488  RT_GET_SEG(segp, ap->a_resource);
489  segp->seg_stp = stp;
490 
491  /* we know root is positive, so we know the smaller t */
492  segp->seg_in.hit_dist = b - root;
493  segp->seg_out.hit_dist = b + root;
494  segp->seg_in.hit_surfno = 0;
495  segp->seg_out.hit_surfno = 0;
496  BU_LIST_INSERT(&(seghead->l), &(segp->l));
497  return 2; /* HIT */
498 #endif
499 }
500 
501 
502 #define RT_SPH_SEG_MISS(SEG) (SEG).seg_stp=(struct soltab *) 0;
503 /**
504  * This is the Becker vectorized version
505  */
506 void
507 rt_sph_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
508  /* An array of solid pointers */
509  /* An array of ray pointers */
510  /* array of segs (results returned) */
511  /* Number of ray/object pairs */
512 
513 {
514  register struct sph_specific *sph;
515  register int i;
516 
517  vect_t ov; /* ray origin to center (V - P) */
518  fastf_t magsq_ov; /* length squared of ov */
519  fastf_t b; /* second term of quadratic eqn */
520  fastf_t root; /* root of radical */
521 
522  if (ap) RT_CK_APPLICATION(ap);
523 
524  /* for each ray/sphere pair */
525  for (i = 0; i < n; i++) {
526  if (stp[i] == 0) continue; /* stp[i] == 0 signals skip ray */
527 
528  sph = (struct sph_specific *)stp[i]->st_specific;
529  VSUB2(ov, sph->sph_V, rp[i]->r_pt);
530  b = VDOT(rp[i]->r_dir, ov);
531  magsq_ov = MAGSQ(ov);
532 
533  if (magsq_ov >= sph->sph_radsq) {
534  /* ray origin is outside of sphere */
535  if (b < 0) {
536  /* ray direction is away from sphere */
537  RT_SPH_SEG_MISS(segp[i]); /* No hit */
538  continue;
539  }
540  root = b*b - magsq_ov + sph->sph_radsq;
541  if (root <= 0) {
542  /* no real roots */
543  RT_SPH_SEG_MISS(segp[i]); /* No hit */
544  continue;
545  }
546  } else {
547  root = b*b - magsq_ov + sph->sph_radsq;
548  }
549  root = sqrt(root);
550 
551  segp[i].seg_stp = stp[i];
552 
553  /* we know root is positive, so we know the smaller t */
554  segp[i].seg_in.hit_dist = b - root;
555  segp[i].seg_out.hit_dist = b + root;
556  segp[i].seg_in.hit_surfno = 0;
557  segp[i].seg_out.hit_surfno = 0;
558  }
559 }
560 
561 
562 /**
563  * Given ONE ray distance, return the normal and entry/exit point.
564  */
565 void
566 rt_sph_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
567 {
568  register struct sph_specific *sph =
569  (struct sph_specific *)stp->st_specific;
570 
571  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
572  VSUB2(hitp->hit_normal, hitp->hit_point, sph->sph_V);
573  VSCALE(hitp->hit_normal, hitp->hit_normal, sph->sph_invrad);
574 }
575 
576 
577 /**
578  * Return the curvature of the sphere.
579  */
580 void
581 rt_sph_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
582 {
583  register struct sph_specific *sph =
584  (struct sph_specific *)stp->st_specific;
585 
586  cvp->crv_c1 = cvp->crv_c2 = - sph->sph_invrad;
587 
588  /* any tangent direction */
589  bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
590 }
591 
592 
593 /**
594  * For a hit on the surface of an SPH, return the (u, v) coordinates
595  * of the hit point, 0 <= u, v <= 1.
596  *
597  * u = azimuth
598  * v = elevation
599  */
600 void
601 rt_sph_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
602 {
603  register struct sph_specific *sph =
604  (struct sph_specific *)stp->st_specific;
605  fastf_t r;
606  vect_t work;
607  vect_t pprime;
608 
609  /* hit_point is on surface; project back to unit sphere, creating
610  * a vector from vertex to hit point which always has length=1.0
611  */
612  VSUB2(work, hitp->hit_point, sph->sph_V);
613  MAT4X3VEC(pprime, sph->sph_SoR, work);
614  /* Assert that pprime has unit length */
615 
616  /* U is azimuth, atan() range: -pi to +pi */
617  uvp->uv_u = bn_atan2(pprime[Y], pprime[X]) * M_1_2PI;
618  if (uvp->uv_u < 0)
619  uvp->uv_u += 1.0;
620  /*
621  * V is elevation, atan() range: -pi/2 to +pi/2, because sqrt()
622  * ensures that X parameter is always >0
623  */
624  uvp->uv_v = bn_atan2(pprime[Z],
625  sqrt(pprime[X] * pprime[X] + pprime[Y] * pprime[Y])) *
626  M_1_PI + 0.5;
627 
628  /* approximation: r / (circumference, 2 * pi * aradius) */
629  r = ap->a_rbeam + ap->a_diverge * hitp->hit_dist;
630  uvp->uv_du = uvp->uv_dv =
631  M_1_2PI * r / stp->st_aradius;
632 }
633 
634 
635 void
636 rt_sph_free(register struct soltab *stp)
637 {
638  register struct sph_specific *sph =
639  (struct sph_specific *)stp->st_specific;
640 
641  BU_PUT(sph, struct sph_specific);
642 }
643 
644 
645 int
646 rt_sph_params(struct pc_pc_set *UNUSED(ps), const struct rt_db_internal *ip)
647 {
648  if (ip) RT_CK_DB_INTERNAL(ip);
649 
650  return 0; /* OK */
651 }
652 
653 
654 /* ELL versions are used for many of the callbacks */
655 
656 
657 /*
658  * Local Variables:
659  * mode: C
660  * tab-width: 8
661  * indent-tabs-mode: t
662  * c-file-style: "stroustrup"
663  * End:
664  * ex: shiftwidth=4 tabstop=8
665  */
vect_t sph_V
Definition: sph.c:63
void rt_sph_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
Definition: sph.c:581
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
struct hit seg_in
IN information.
Definition: raytrace.h:370
int(* ft_bbox)(struct rt_db_internal *, point_t *, point_t *, const struct bn_tol *)
Definition: raytrace.h:2196
void rt_sph_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
Definition: sph.c:566
void rt_sph_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
Definition: sph.c:507
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
double dist
>= 0
Definition: tol.h:73
vect_t crv_pdir
Principle direction.
Definition: raytrace.h:307
fastf_t uv_u
Range 0..1.
Definition: raytrace.h:341
struct soltab * seg_stp
pointer back to soltab
Definition: raytrace.h:372
#define VSET(a, b, c, d)
Definition: color.c:53
Definition: raytrace.h:215
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
void rt_sph_free(register struct soltab *stp)
Definition: sph.c:636
Definition: pc.h:108
double dist_sq
dist * dist
Definition: tol.h:74
Definition: raytrace.h:368
#define RT_SPH_SEG_MISS(SEG)
Definition: sph.c:502
Definition: raytrace.h:248
int rt_sph_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: sph.c:300
fastf_t sph_rad
Definition: sph.c:66
fastf_t st_aradius
Radius of APPROXIMATING sphere.
Definition: raytrace.h:433
Header file for the BRL-CAD common definitions.
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
struct bu_list l
Definition: raytrace.h:369
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
HIDDEN void * alloc(alloc_t type, size_t cnt, size_t sz, const char *str)
Definition: malloc.c:202
void rt_sph_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
Definition: sph.c:601
fastf_t sph_invrad
Definition: sph.c:65
Definition: color.c:49
COMPLEX data[64]
Definition: fftest.c:34
fastf_t sph_radsq
Definition: sph.c:64
void bn_mat_print(const char *title, const mat_t m)
Definition: mat.c:81
void rt_sph_print(register const struct soltab *stp)
Definition: sph.c:394
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
fastf_t st_bradius
Radius of BOUNDING sphere.
Definition: raytrace.h:434
fastf_t crv_c2
curvature in other direction
Definition: raytrace.h:309
fastf_t a_diverge
slope of beam divergence/mm
Definition: raytrace.h:1600
fastf_t uv_dv
delta in v
Definition: raytrace.h:344
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
point_t hit_point
DEPRECATED: Intersection point, use VJOIN1 hit_dist.
Definition: raytrace.h:251
point_t st_max
max X, Y, Z of bounding RPP
Definition: raytrace.h:438
struct hit seg_out
OUT information.
Definition: raytrace.h:371
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
#define ID_SPH
Sphere.
Definition: raytrace.h:468
double bn_atan2(double x, double y)
Definition: mat.c:104
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
#define RT_GET_SEG(p, res)
Definition: raytrace.h:379
void * idb_ptr
Definition: raytrace.h:195
HIDDEN int code(fastf_t x, fastf_t y)
Definition: clip.c:43
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
int rt_sph_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
Definition: sph.c:427
const struct rt_functab OBJ[]
Definition: table.c:159
void bn_vec_ortho(vect_t out, const vect_t in)
int rt_sph_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
Definition: sph.c:646
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
fastf_t uv_du
delta in u
Definition: raytrace.h:343
fastf_t crv_c1
curvature in principle dir
Definition: raytrace.h:308
Definition: color.c:51
bn_poly_t output[3]
Definition: bn_poly_add.c:36
int hit_surfno
solid-specific surface indicator
Definition: raytrace.h:255
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
vect_t hit_normal
DEPRECATED: Surface Normal at hit_point, use RT_HIT_NORMAL.
Definition: raytrace.h:252
fastf_t a_rbeam
initial beam radius (mm)
Definition: raytrace.h:1599
const struct rt_functab * st_meth
pointer to per-solid methods
Definition: raytrace.h:428
int st_id
Solid ident.
Definition: raytrace.h:431
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
#define VPRINT(a, b)
Definition: raytrace.h:1881
mat_t sph_SoR
Definition: sph.c:67
Definition: color.c:50
fastf_t uv_v
Range 0..1.
Definition: raytrace.h:342
point_t st_center
Centroid of solid.
Definition: raytrace.h:432