winffhp@dutrun.UUCP (Frits Post) (02/25/88)
My ray tracing program, which can display the primitives block, sphere cone and cylinder, uses spatial enumeration of the object space (subdivision in regularly located cubical cells (voxels)) to speed up computation. The voxels each have a list of primitives. If the surface of a primitive is inside a voxel, this primitive will be put in the list of the voxel. I am currently using bounding boxes around the primitives: if part of the bounding box is inside the voxel, the surface of the primitive is said to be inside the voxel. This is a very easy method but also very s-l-o-w. I am trying to find a better way of determining whether the surface of a primitive is in a voxel or not, but I am not very succesful. Does anyone out there have any suggestions ? Thanks in advance, ruud waij UUCP: dutrun!winffhp -- ...mcvax!dutrun!frits Faculty of Mathematics and Informatics Delft University of Technology
saponara@batcomputer.tn.cornell.edu (John Saponara) (03/01/88)
In article <198@dutrun.UUCP> winffhp@dutrun.UUCP (ruud waij) writes: >My ray tracing program, which can display the >primitives block, sphere cone and cylinder, >uses spatial enumeration of the object space >(subdivision in regularly located cubical cells >(voxels)) to speed up computation. > >The voxels each have a list of primitives. >If the surface of a primitive is inside a voxel, >this primitive will be put in the list of the voxel. > >I am currently using bounding boxes around the >primitives: if part of the bounding box is >inside the voxel, the surface of the primitive >is said to be inside the voxel. >This is a very easy method but also very s-l-o-w. > >I am trying to find a better way of determining >whether the surface of a primitive is in a voxel >or not, but I am not very succesful. >Does anyone out there have any suggestions ? Ruud, Why do you consider BV (Bounding Volume) box comparison to voxel extents slow? This has to be the fastest comparison there is: some 6 tests (2 pairs of x,y,z for the box and voxel). If box.hi.x < voxel.lo.x OR box.hi.y < voxel.lo.y OR box.hi.z < voxel.lo.z, - OR - If box.lo.x > voxel.hi.x OR box.lo.y > voxel.hi.y OR box.lo.z > voxel.hi.z, Then the box and voxel don't overlap. A time-saver is to compute the BV's once for each object, storing them temporarily. Then, for each voxel and subvoxel you immediately have the data at hand. The only thing I can figure you mean as "slow" would be if you recomputed the BV box extents for a primitive for EACH comparison. This would indeed be an incredible waste of time. All for now, Eric Haines (not John Saponara)
ph@degas.Berkeley.EDU (Paul Heckbert) (03/01/88)
[ In article <198@dutrun.UUCP> winffhp@dutrun.UUCP (ruud waij) asks how to find the set of voxels intersecting various modeling primitives, such as boxes, spheres, cones, and cylinders. ] Yes, interesting problem! Fitting a bounding box around the object and listing that object in all voxels intersected by the bounding box will be inefficient as it can list the object in many voxels not intersected by the object itself. Imagine a long, thin cylinder at an angle to the voxel grid. I've never implemented this, but I think it would solve your problem for general quadrics: find zmin and zmax for the object. loop over z from zmin to zmax, stepping from grid plane to grid plane. find the conic curve of the intersection of the quadric with the plane. this will be a second degree equation in x and y (an ellipse, parabola, hyperbola, or line). note that you'll have to deal with the end caps of your cylinders and similar details. find ymin and ymax for the conic curve. loop over y from ymin to ymax, stepping from grid line to grid line within the current z-plane find the intersection points of the current y line with the conic. this will be zero, one, or two points. find xmin and xmax of these points. loop over x from xmin to xmax. the voxel at (x, y, z) intersects the object Perhaps others out there have actually implemented stuff like this and will enlighten us with their experience. Paul Heckbert, CS grad student 508-7 Evans Hall, UC Berkeley UUCP: ucbvax!degas.berkeley.edu!ph Berkeley, CA 94720 ARPA: ph@degas.berkeley.edu
paul@hpldola.HP.COM (Paul Bame) (03/02/88)
> / comp.graphics / ph@degas.Berkeley.EDU (Paul Heckbert) / > > I've never implemented this, but I think it would solve your > problem for general quadrics: > > find zmin and zmax for the object. > loop over z from zmin to zmax, stepping from grid plane to grid plane. > find the conic curve of the intersection of the quadric with the plane. > this will be a second degree equation in x and y (an ellipse, > parabola, hyperbola, or line). > note that you'll have to deal with the end caps of your cylinders > and similar details. Just an idea, but at this point you could perhaps use standard conic scan-conversion algorithms. If I'm not being stupid or something, the algorithm listed below will be limited similarly to integer scan-conversions. The problem which might arise is that scan conversions do not usually select all pixels (voxels) on the curve but only approximate it. The missing pixels (voxels in your case) could leave small holes in your image. Two possible solutions might be reasonable: 1) "know" there may be holes and do a search of nearest neighbor voxels when looking for possible intersections - only look for objects not listed in the initial voxel (shouldn't be too expensive in use) or 2) use a grid for scan conversion (or the algorithm below) which is sufficiently smaller than your voxel grid to leave no holes large enough to be distracting (an ill-defined problem I'm afraid). > find ymin and ymax for the conic curve. > loop over y from ymin to ymax, > stepping from grid line to grid line within the current z-plane > find the intersection points of the current y line with the conic. > this will be zero, one, or two points. > find xmin and xmax of these points. > loop over x from xmin to xmax. > the voxel at (x, y, z) intersects the object --Paul Bame hplabs!hpldola!paul hpldola!paul@hp-labs.csnet 303-590-5557 (Starting March 5, 719-590-5557)
glassner@unc.cs.unc.edu (Andrew S. Glassner) (03/02/88)
In article <198@dutrun.UUCP> winffhp@dutrun.UUCP (ruud waij) writes: > >I am trying to find a better way of determining >whether the surface of a primitive is in a voxel >or not, but I am not very succesful. >Does anyone out there have any suggestions ? > Ruud and I have discussed this in person, but I thought I'd respond anyway - both to summarize our discussions and offer some comments on the technique. The central question of the posting was how to assign the surfaces of various objects to volume cells, in order to use some form spatial subdivision to accelerate ray tracing. Notice that there are at least two assumptions underlying this method. The first assumes that the interior of each object is homogeneous in all respects, and thus uninteresting from a ray-tracing point of view. As a counterexample, if we have smoke swirling around inside a crystal ball, then this "homogeneous-contents" assumption breaks down fast. To compensate, we either must include the volume inside each object to each cell's object list (and support a more complex object description encompassing both the surface and the contents), or include as new objects the stuff within the original. The other assumption is that objects have hard edges; otherwise we have to revise our definition of "surface" in this context. This can begin to be a problem with implicit surfaces, though I haven't seen this really discussed yet in print. But so as long as we're using hard-edged objects with homogeneous interiors, the "surface in a cell" approach is still attractive. From here on I'll assume that cells are rectangular boxes. So to which cells do we attach a particular surface? Ruud's current technique (gathered from his posting) finds the bounding box of the surface and marks every cell that is even partly within the bounding volume. Sure, this marks a lot of cells that need not be marked. One way to reduce the marked cell count is to notice that if the object is convex, we can unmark any cell that is completely within the object; we test the 8 corners with an inside/outside test (fast and simple for quadrics; only slightly slower and harder for polyhedra). If all 8 corners are "inside", unmark the cell. Of course, this assumes convex cells - like boxes. Note that some quadrics are not convex (e.g. hyperboloid of one sheet) so you must be at least a little careful here. The opposite doesn't hold - just because all 8 corners are outside does NOT mean a cell may be unmarked. Consider the end of a cylinder poking into one side of a box, like an ice-cream bar on a stick, where the ice-cream bar itself is our cell. The stick is within the ice cream, but all the corners of the ice cream bar are outside the stick. Since this box contains some of the stick's surface, the box should still be marked. So our final cells have either some inside and some outside corners, or all outside corners. What do we lose by having lots of extra cells marked? Probably not much. By storing the ray intersection parameter with each object after an intersection has been computed, we don't ever need to actually repeat an intersection. If the ray id# that is being traced matches the ray id# for which the object holds the intersection parameter, we simply return the intersection value. This requires getting access to the object's description and then a comparison - probably the object access is the most expensive step. But most objects are locally coherent (if you hit a cell containing object A, the next time you need object A again will probably be pretty soon). So "false positives" - cells who claim to contain an object they really don't - aren't so bad, since the pages containing an object will probably still be resident when we need it again. We do need to protect ourselves, though, against a little gotcha that I neglected to discuss in my '84 CG&A paper. If you enter a cell and find that you hit an object it claims to contain, you must check that the intersection you computed actually resides within that cell. It's possible that the cell is a false positive, so the object itself isn't even in the cell. It's also possible that the object is something like a boomerang, where it really is within the current cell but the actual intersection is in another cell. The loss comes in when the intersection is actually in the next cell, but another surface in the next cell (but not in this one) is actually in front. Even worse, if you're doing CSG, that phony intersection can distort your entire precious CSG status tree! The moral is not to be fooled just because you hit an object in a cell; check to be sure that the intersection itself is also within the cell. How to find the bounding box of a quadric? A really simple way is to find the bounding box of the quadric in its canonical space, and then transform the box into the object's position. Fit a new bounding box around the eight transformed corners of the original bounding box. This will not make a very tight volume at all, (imagine a slanted, tilted cylinder and its bounding box), but it's quick and dirty and I use it for getting code debugged and at least running. If you have a convex hull program, you can compute the hull for concave polyhedra and use its bounding box; obviously you needn't bother for convex polyhedra. For parametric curved surfaces you can try to find a polyhedral shell the is guaranteed to enclose the surface; again you can find the shell's convex hull and then find the extreme values along each co-ordinate. If your boxes don't have to be axis-aligned, then the problem changes significantly. Consider a sphere: an infinite number of equally-sized boxes at different orientation will enclose the sphere minimally. More complicated shapes appear more formidable. An O(n^3) algorithm for non-aligned bounding boxes can be found in "Finding Minimal Enclosing Boxes" by O'Rourke (International Journal of Computer and Information Sciences, Vol 14, No 3, 1985, pp. 183-199). Other approaches include traditional 3-d scan conversion, which I think should be easily convertable into an adaptive octree environment. Or you can grab the bull by the horns and go for raw octree encoding, approximating the surface with lots of little sugar cubes. Then mark any cell in your space subdivision tree that encloses (some or all of) any of these cubes. -Andrew (P.S. to Rudi: I've had no luck trying to get through to dutrun!winffhp via electronic mail. If you can reach me at glassner@cs.unc.edu or uunet!mcnc!unc!glassner (or anything else that might work) then I can try to get back to you along that path. -A) - -- ---- ------- ------------ -------------------- --------------------- Andrew Glassner UUCP:decvax!mcnc!unc!glassner ARPA:glassner@cs.unc.edu
sow@cad.luth.se (Sven-Ove Westberg) (03/06/88)
In article <23153@ucbvax.BERKELEY.EDU> ph@degas.Berkeley.EDU.UUCP (Paul Heckbert) writes: |[ In article <198@dutrun.UUCP> winffhp@dutrun.UUCP (ruud waij) asks | how to find the set of voxels intersecting various modeling primitives, | such as boxes, spheres, cones, and cylinders. ] | |Yes, interesting problem! Fitting a bounding box around the object and listing |that object in all voxels intersected by the bounding box will be inefficient as |it can list the object in many voxels not intersected by the object itself. |Imagine a long, thin cylinder at an angle to the voxel grid. | Yes this is a real interesting problem. But it is similar to the problem of converting a boundary representation to a block model. So it is possible to find good algorithms in the cad literature. One reference that converts a polyhedon to a block model is: Tamminen M, Samet H, Efficient Octree Conversion by Connectivity Labeling, Computer Graphics 18 (3), pp 43-51, July, 1984. Perhaps Markko Tamminen or Martti Mantyla, at Helsinki University of Technology, Finland could give us some good comments on this problem. Sven-Ove Westberg, CAD, University of Lulea, S-951 87 Lulea, Sweden. Tel: +46-920-91677 (work) +46-920-48390 (home) UUCP: {uunet,mcvax}!enea!cad.luth.se!sow Internet: sow@cad.luth.se