OSGVolumeFunctions.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *                 Copyright (C) 2003 by the OpenSG Forum                    *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the impclied warranty of               *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028  \*--------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038
00039 #include "OSGBoxVolume.h"
00040 #include "OSGSphereVolume.h"
00041 #include "OSGCylinderVolume.h"
00042 #include "OSGFrustumVolume.h"
00043
00044 OSG_BEGIN_NAMESPACE
00045
00046 // ###################################################################
00047 // # Volume Interesect Functions #####################################
00048 // ###################################################################
00049
00050 OSG_BASE_DLLMAPPING
00051 bool intersect(const OSG::Volume &vol1, const OSG::Volume &vol2)
00052 {
00053     bool                  retCode = false;
00054
00055     const BoxVolume      *bv;
00056     const SphereVolume   *sv;
00057     const CylinderVolume *cv;
00058     const FrustumVolume  *fv;
00059
00060     if((bv = dynamic_cast<const BoxVolume *>(&vol1)) != NULL)
00061     {
00062         retCode = intersect(*bv, vol2);
00063     }
00064     else if((sv = dynamic_cast<const SphereVolume   *>(&vol1)) != NULL)
00065     {
00066         retCode = intersect(*sv, vol2);
00067     }
00068     else if((cv = dynamic_cast<const CylinderVolume *>(&vol1)) != NULL)
00069     {
00070         retCode = intersect(*cv, vol2);
00071     }
00072     else if((fv = dynamic_cast<const FrustumVolume  *>(&vol1)) != NULL)
00073     {
00074         retCode = intersect(*fv, vol2);
00075     }
00076     else
00077     {
00078         FWARNING(
00079             ("intersect(Volume, Volume): Argument 1 has unhandled type.\n"));
00080     }
00081
00082     return retCode;
00083 }
00084
00085 // # Box #############################################################
00086
00087 OSG_BASE_DLLMAPPING
00088 bool intersect(const OSG::BoxVolume &box1, const OSG::BoxVolume &box2)
00089 {
00090     bool retCode = false;
00091
00092     if(box1.isEmpty() == true || box2.isEmpty() == true)
00093     {
00094         retCode = false;
00095     }
00096     else if(box1.isInfinite() == true || box2.isInfinite() == true)
00097     {
00098         retCode = true;
00099     }
00100     else
00101     {
00102         retCode =
00103             (box1.getMin()[0] <= box2.getMax()[0] &&
00104              box1.getMax()[0] >= box2.getMin()[0]   ) &&
00105             (box1.getMin()[1] <= box2.getMax()[1] &&
00106              box1.getMax()[1] >= box2.getMin()[1]   ) &&
00107             (box1.getMin()[2] <= box2.getMax()[2] &&
00108              box1.getMax()[2] >= box2.getMin()[2]   );
00109     }
00110
00111     return retCode;
00112 }
00113
00114
00115 OSG_BASE_DLLMAPPING
00116 bool intersect(const OSG::BoxVolume &box, const OSG::SphereVolume &sphere)
00117 {
00118     // source:
00119     // J. Arvo. A simple method for box-sphere intersection testing.
00120     // In A. Glassner, editor, Graphics Gems, pp. 335-339,
00121     // Academic Press, Boston, MA, 1990
00122
00123     bool    retCode;
00124
00125     if(box.isEmpty() == true || sphere.isEmpty() == true)
00126     {
00127         retCode = false;
00128     }
00129     else if(box.isInfinite() == true || sphere.isInfinite() == true)
00130     {
00131         retCode = true;
00132     }
00133     else
00134     {
00135         Real  s;
00136         Real  d = 0.f;
00137
00138         //find the square of the distance from the sphere to the box
00139
00140         for(Int32 i = 0; i < 3; i++)
00141         {
00142             if(sphere.getCenter()[i] < box.getMin()[i])
00143             {
00144                 s  = sphere.getCenter()[i] - box.getMin()[i];
00145                 d += s * s;
00146             }
00147             else if(sphere.getCenter()[i] > box.getMax()[i])
00148             {
00149                 s  = sphere.getCenter()[i] - box.getMax()[i];
00150                 d += s * s;
00151             }
00152         }
00153
00154         retCode = (d <= (sphere.getRadius() * sphere.getRadius()));
00155     }
00156
00157     return retCode;
00158 }
00159
00160 OSG_BASE_DLLMAPPING
00161 bool intersect(const OSG::BoxVolume &box, const OSG::CylinderVolume &cylinder)
00162 {
00163     bool  retCode;
00164     Pnt3r apos;
00165     Vec3r adir;
00166
00167     cylinder.getAxis(apos, adir);
00168
00169     if(box.isEmpty() == true || cylinder.isEmpty() == true)
00170     {
00171         retCode = false;
00172     }
00173     else if(box.isInfinite() == true || cylinder.isInfinite() == true)
00174     {
00175         retCode = true;
00176     }
00177     else
00178     {
00179         Real  s1 = 0.f, s2 = 0.f, s3 = 0.f, s4 = 0.f,
00180               d = 0.f, d1 = 0.f, d2 = 0.f;
00181         Pnt3r c, p, p1, p2;
00182         Vec3r u, u1, u2;
00183
00184         // find the distance between the min and the max of the box
00185         //with the lower point and the upper point of the cylinder respectively
00186
00187         s1 = (apos - box.getMin()).length();
00188         s2 = (apos - box.getMax()).length();
00189
00190         s3 = (apos + adir - box.getMin()).length();
00191         s4 = (apos + adir - box.getMax()).length();
00192
00193         //Check the minimum of the above distances
00194
00195         if(s1 <= s2)
00196         {
00197             d1 = s1;
00198             p1 = box.getMin();
00199         }
00200         else
00201         {
00202             d1 = s2;
00203             p1 = box.getMax();
00204         }
00205
00206         if(s3 <= s4)
00207         {
00208             d2 = s3;
00209             p2 = box.getMin();
00210         }
00211         else
00212         {
00213             d2 = s4;
00214             p2 = box.getMax();
00215         }
00216
00217         //set the value of the vector corresponding to the shortest distance
00218         if(d1 <= d2)
00219         {
00220             d = d1;
00221             c = apos;
00222             p = p1;
00223         }
00224         else
00225         {
00226             d = d2;
00227             c = apos + adir;
00228             p = p2;
00229         }
00230
00231         // decompose the vector in u1 and u2 which are parallel and 
00232         // perpendicular to the cylinder axis respectively
00233         u  = p - c;
00234         u1 = (u[0] * adir[0] + u[1] * adir[1] + u[2] * adir[2]) /
00235             (adir.length() * adir.length()) * adir;
00236
00237         u2 = u - u1;
00238
00239         if(u1.length() <= 10e-6f)
00240         {
00241             retCode = true;
00242         }
00243         else if(u2.length() <= 10e-6f)
00244         {
00245             retCode = (d <= 10e-6f);
00246         }
00247         else
00248         {
00249             retCode = (u2.length() <= cylinder.getRadius());
00250         }
00251     }
00252
00253     return retCode;
00254 }
00255
00256
00257 OSG_BASE_DLLMAPPING
00258 bool intersect(const OSG::BoxVolume &box, const OSG::FrustumVolume &frustum)
00259 {
00260     Pnt3r min, max;
00261
00262     box.getBounds(min, max);
00263
00264     const Plane       *frust = frustum.getPlanes();
00265
00266     // check each point of the box to the 6 planes
00267
00268     for(Int32 i = 0; i < 6; i++)
00269     {
00270         if(frust[i].isOutHalfSpace(min, max))
00271             return false;
00272     }
00273
00274     return true;
00275 }
00276
00277 OSG_BASE_DLLMAPPING
00278 bool intersect(const OSG::BoxVolume &box, const OSG::Volume &vol)
00279 {
00280     bool                 retCode = false;
00281
00282     const BoxVolume      *bv;
00283     const SphereVolume   *sv;
00284     const CylinderVolume *cv;
00285     const FrustumVolume  *fv;
00286
00287     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
00288     {
00289         retCode = intersect(box, *bv);
00290     }
00291     else if((sv = dynamic_cast<const SphereVolume   *>(&vol)) != NULL)
00292     {
00293         retCode = intersect(box, *sv);
00294     }
00295     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
00296     {
00297         retCode = intersect(box, *cv);
00298     }
00299     else if((fv = dynamic_cast<const FrustumVolume  *>(&vol)) != NULL)
00300     {
00301         retCode = intersect(box, *fv);
00302     }
00303     else
00304     {
00305         FWARNING(
00306             ("intersect(BoxVolume, Volume): Argument 2 has unhandled type.\n"));
00307     }
00308
00309     return retCode;
00310 }
00311
00312
00313 // # Sphere ###########################################################
00314
00315 OSG_BASE_DLLMAPPING
00316 bool intersect(const OSG::SphereVolume &sphere1,
00317                const OSG::SphereVolume &sphere2)
00318 {
00319     bool retCode = false;
00320     Real dist    = (sphere2.getCenter() - sphere1.getCenter()).length();
00321
00322     if(sphere1.isEmpty() || sphere2.isEmpty())
00323     {
00324         retCode = false;
00325     }
00326     else if(sphere1.isInfinite() || sphere2.isInfinite())
00327     {
00328         retCode = true;
00329     }
00330     else if(dist < sphere1.getRadius() + sphere2.getRadius())
00331     {
00332         // the distance between the center of the 2 spheres is bigger
00333         // than the sum of the 2 radiuses
00334
00335         retCode = true;
00336     }
00337
00338     return retCode;
00339 }
00340
00341
00342 OSG_BASE_DLLMAPPING
00343 bool intersect(const OSG::SphereVolume   &sphere,
00344                const OSG::CylinderVolume &cylinder)
00345 {
00346     bool  retCode;
00347     Pnt3r apos;
00348     Vec3r adir;
00349
00350     cylinder.getAxis(apos, adir);
00351
00352     if(sphere.isEmpty() || cylinder.isEmpty())
00353     {
00354         retCode = false;
00355     }
00356     else if(sphere.isInfinite() || cylinder.isInfinite())
00357     {
00358         retCode = true;
00359     }
00360     else
00361     {
00362         Real  d = 0.f, s1 = 0.f, s2 = 0.f;
00363         Pnt3r c;
00364         Vec3r u, u1, u2;
00365
00366         //get the distance between the upper and lower point of the cylinder
00367         // and the sphere center
00368
00369         s1 = (apos        - sphere.getCenter()).length();
00370         s2 = (apos + adir - sphere.getCenter()).length();
00371
00372 #ifdef OSG_EMBEDDED
00373         if((s1 <= FLT_EPSILON) || (s2 <= FLT_EPSILON))
00374 #else
00375         if((s1 <= DBL_EPSILON) || (s2 <= DBL_EPSILON))
00376 #endif
00377         {
00378             return true;
00379         }
00380         //check the smallest distance and set the vector coordinate
00381         if(s1 <= s2)
00382         {
00383             d = s1;
00384             c = apos;
00385         }
00386         else
00387         {
00388             d = s2;
00389             c = apos + adir;
00390         }
00391
00392         // decompose the vector in u1 and u2 which are parallel and 
00393         // perpendicular to the cylinder axis respectively
00394
00395         u  = ((d - sphere.getRadius()) / d) * (c - sphere.getCenter());
00396
00397         u1 = (u[0] * adir[0] + u[1] * adir[1] + u[2] * adir[2]) /
00398              (adir.length() * adir.length()) * adir;
00399         u2 = u - u1;
00400
00401         if(u2.length() <= 10e-6f)
00402         {
00403             retCode = (d <= sphere.getRadius());
00404         }
00405         else
00406         {
00407             retCode = (u2.length() <= cylinder.getRadius());
00408         }
00409     }
00410
00411     return retCode;
00412 }
00413
00414
00415 OSG_BASE_DLLMAPPING
00416 bool intersect(const OSG::SphereVolume  &sphere,
00417                const OSG::FrustumVolume &frustum)
00418 {
00419     const Plane             *frust = frustum.getPlanes();
00420
00421     //check the center of the sphere with each plane of the frustum
00422     for(Int32 i = 0; i < 6; i++)
00423     {
00424         if(frust[i].distance(sphere.getCenter()) < -sphere.getRadius())
00425             return false;
00426     }
00427
00428     return true;
00429 }
00430
00431
00432 OSG_BASE_DLLMAPPING
00433 bool intersect(const OSG::SphereVolume &sphere, const OSG::Volume &vol)
00434 {
00435     bool                 retCode = false;
00436
00437     const BoxVolume      *bv;
00438     const SphereVolume   *sv;
00439     const CylinderVolume *cv;
00440     const FrustumVolume  *fv;
00441
00442     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
00443     {
00444         retCode = intersect(sphere, *bv);
00445     }
00446     else if((sv = dynamic_cast<const SphereVolume   *>(&vol)) != NULL)
00447     {
00448         retCode = intersect(sphere, *sv);
00449     }
00450     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
00451     {
00452         retCode = intersect(sphere, *cv);
00453     }
00454     else if((fv = dynamic_cast<const FrustumVolume  *>(&vol)) != NULL)
00455     {
00456         retCode = intersect(sphere, *fv);
00457     }
00458     else
00459     {
00460         FWARNING(
00461             ("intersect(Sphere, Volume): Argument 2 has unhandled type.\n"));
00462     }
00463
00464     return retCode;
00465 }
00466
00467
00468 // # Cylinder ########################################################
00469
00470 // http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm#dist3D_Segment_to_Segment() 
00471 // Adapted for OpenSG by Marcus Lindblom 2005-09-06
00472
00473 // Copyright 2001, softSurfer (www.softsurfer.com)
00474 // This code may be freely used and modified for any purpose
00475 // providing that this copyright notice is included with it.
00476 // SoftSurfer makes no warranty for this code, and cannot be held
00477 // liable for any real or imagined damage resulting from its use.
00478 // Users of this code must verify correctness for their application.
00479
00480 // Assume that classes are already given for the objects:
00481 //    Point and Vector with
00482 //        coordinates {float x, y, z;}
00483 //        operators for:
00484 //            Point  = Point  Vector
00485 //            Vector = Point - Point
00486 //            Vector = Vector  Vector
00487 //            Vector = Scalar * Vector
00488 //    Line and Segment with defining points {Point P0, P1;}
00489 //    Track with initial position and velocity vector
00490 //            {Point P0; Vector v;}
00491 //===================================================================
00492
00493 Real dist3D_Segment_to_Segment(const Pnt3r& s1p,
00494                                const Vec3r& s1d,
00495                                const Pnt3r& s2p,
00496                                const Vec3r& s2d)
00497 {
00498     const float  SMALL_NUM = 1e-9f; // anything that avoids division overflow
00499     const Vec3r& u = s1d;
00500     const Vec3r& v = s2d;
00501           Vec3r  w = s1p - s2p;
00502
00503     Real    a = u.dot(u);        // always >= 0
00504     Real    b = u.dot(v);
00505     Real    c = v.dot(v);        // always >= 0
00506     Real    d = u.dot(w);
00507     Real    e = v.dot(w);
00508     Real    D = a*c - b*b;       // always >= 0
00509     Real    sc, sN, sD = D;      // sc = sN / sD, default sD = D >= 0
00510     Real    tc, tN, tD = D;      // tc = tN / tD, default tD = D >= 0
00511
00512     // compute the line parameters of the two closest points
00513     if(D < SMALL_NUM)   // the lines are almost parallel
00514     {
00515         sN = 0.0f;        // force using point P0 on segment S1
00516         sD = 1.0f;        // to prevent possible division by 0.0 later
00517         tN = e;
00518         tD = c;
00519     }
00520     else                 // get the closest points on the infinite lines
00521     {
00522         sN = (b*e - c*d);
00523         tN = (a*e - b*d);
00524
00525         if(sN < 0.0f)       // sc < 0 => the s=0 edge is visible
00526         {
00527             sN = 0.0f;
00528             tN = e;
00529             tD = c;
00530         }
00531         else if (sN > sD)   // sc > 1 => the s=1 edge is visible
00532         {
00533             sN = sD;
00534             tN = e + b;
00535             tD = c;
00536         }
00537     }
00538
00539     if(tN < 0.0f)            // tc < 0 => the t=0 edge is visible
00540     {
00541         tN = 0.0f;
00542         // recompute sc for this edge
00543         if(-d < 0.0f)
00544         {
00545             sN = 0.0f;
00546         }
00547         else if(-d > a)
00548         {
00549             sN = sD;
00550         }
00551         else
00552         {
00553             sN = -d;
00554             sD = a;
00555         }
00556     }
00557     else if (tN > tD)       // tc > 1 => the t=1 edge is visible
00558     {
00559         tN = tD;
00560         // recompute sc for this edge
00561
00562         if((-d + b) < 0.0f)
00563         {
00564             sN = 0.f;
00565         }
00566         else if ((-d + b) > a)
00567         {
00568             sN = sD;
00569         }
00570         else
00571         {
00572             sN = (-d + b);
00573             sD = a;
00574         }
00575     }
00576
00577     // finally do the division to get sc and tc
00578     sc = (osgAbs(sN) < SMALL_NUM ? 0.0f : sN / sD);
00579     tc = (osgAbs(tN) < SMALL_NUM ? 0.0f : tN / tD);
00580
00581     // get the difference of the two closest points
00582     Vec3r dP = w + (sc * u) - (tc * v);  // = S1(sc) - S2(tc)
00583
00584     return dP.length();   // return the squared distance
00585 }
00586
00587 OSG_BASE_DLLMAPPING
00588 bool intersect(const OSG::CylinderVolume &cyl1,
00589                const OSG::CylinderVolume &cyl2)
00590 {
00591     Pnt3r p1, p2;
00592     Vec3r v1, v2;
00593
00594     cyl1.getAxis(p1, v1);
00595     cyl2.getAxis(p2, v2);
00596
00597     return
00598         dist3D_Segment_to_Segment(p1, v1, p2, v2) <=
00599         (cyl1.getRadius() + cyl2.getRadius());
00600 }
00601
00602
00603 OSG_BASE_DLLMAPPING
00604 bool intersect(const OSG::CylinderVolume &cylinder,
00605                const OSG::FrustumVolume  &frustum)
00606 {
00607     Pnt3r min, max;
00608     cylinder.getBounds(min, max);
00609
00610     const Plane       *frust = frustum.getPlanes();
00611
00612     // check each point of the box to the 6 planes
00613
00614     for(Int32 i = 0; i < 6; i++)
00615     {
00616         if(frust[i].isOutHalfSpace(min, max))
00617             return false;
00618     }
00619
00620     return true;
00621 }
00622
00623
00624 OSG_BASE_DLLMAPPING
00625 bool intersect(const OSG::CylinderVolume &cylinder, const OSG::Volume &vol)
00626 {
00627     bool                 retCode = false;
00628
00629     const BoxVolume      *bv;
00630     const SphereVolume   *sv;
00631     const CylinderVolume *cv;
00632     const FrustumVolume  *fv;
00633
00634     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
00635     {
00636         retCode = intersect(cylinder, *bv);
00637     }
00638     else if((sv = dynamic_cast<const SphereVolume *>(&vol)) != NULL)
00639     {
00640         retCode = intersect(cylinder, *sv);
00641     }
00642     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
00643     {
00644         retCode = intersect(cylinder, *cv);
00645     }
00646     else if((fv = dynamic_cast<const FrustumVolume *>(&vol)) != NULL)
00647     {
00648         retCode = intersect(cylinder, *fv);
00649     }
00650     else
00651     {
00652         FWARNING(
00653             ("intersect(Cylinder, Volume): Argument 2 has unhandled type.\n"));
00654     }
00655
00656
00657     return retCode;
00658 }
00659
00660
00661 // # Frustum ########################################################
00662
00663 OSG_BASE_DLLMAPPING
00664 bool intersect(const OSG::FrustumVolume &OSG_CHECK_ARG(frustum1),
00665                const OSG::FrustumVolume &OSG_CHECK_ARG(frustum2))
00666 {
00667     FFATAL(("intersect (frustum/frustum) is not impl.\n"));
00668     return false;
00669 }
00670
00671 OSG_BASE_DLLMAPPING
00672 bool intersect(const OSG::FrustumVolume &frustum, const OSG::Volume &vol)
00673 {
00674     bool                  retCode = false;
00675
00676     const BoxVolume      *bv;
00677     const SphereVolume   *sv;
00678     const CylinderVolume *cv;
00679     const FrustumVolume  *fv;
00680
00681     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
00682     {
00683         retCode = intersect(frustum, *bv);
00684     }
00685     else if((sv = dynamic_cast<const SphereVolume *>(&vol)) != NULL)
00686     {
00687         retCode = intersect(frustum, *sv);
00688     }
00689     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
00690     {
00691         retCode = intersect(frustum, *cv);
00692     }
00693     else if((fv = dynamic_cast<const FrustumVolume *>(&vol)) != NULL)
00694     {
00695         retCode = intersect(frustum, *fv);
00696     }
00697     else
00698     {
00699         FWARNING(
00700             ("intersect(Frustum, Volume): Argument 2 has unhandled type.\n"));
00701     }
00702
00703     return retCode;
00704 }
00705
00706
00707 // ###################################################################
00708 // # Volume Extend Functions #########################################
00709 // ###################################################################
00710
00711 OSG_BASE_DLLMAPPING
00712 void extend(OSG::Volume &srcVol, const OSG::Volume &vol)
00713 {
00714     BoxVolume      *bv;
00715     SphereVolume   *sv;
00716     CylinderVolume *cv;
00717     FrustumVolume  *fv;
00718
00719     if((bv = dynamic_cast<BoxVolume *>(&srcVol)) != NULL)
00720     {
00721         extend(*bv, vol);
00722     }
00723     else if((sv = dynamic_cast<SphereVolume   *>(&srcVol)) != NULL)
00724     {
00725         extend(*sv, vol);
00726     }
00727     else if((cv = dynamic_cast<CylinderVolume *>(&srcVol)) != NULL)
00728     {
00729         extend(*cv, vol);
00730     }
00731     else if((fv = dynamic_cast<FrustumVolume  *>(&srcVol)) != NULL)
00732     {
00733         extend(*fv, vol);
00734     }
00735     else
00736     {
00737         FWARNING(("extend(Volume, Volume): Argument 1 has unhandled type.\n"));
00738     }
00739 }
00740
00741 // # Box #############################################################
00742
00743 OSG_BASE_DLLMAPPING
00744 void extend(OSG::BoxVolume &srcVol, const OSG::BoxVolume &vol)
00745 {
00746     if( (!srcVol.isValid   () && !srcVol.isEmpty()) ||
00747           srcVol.isInfinite()                       ||
00748           srcVol.isStatic  ()                         )
00749     {
00750         return;
00751     }
00752
00753     if(!vol.isValid())
00754         return;
00755
00756     if(srcVol.isEmpty())
00757     {
00758         if(vol.isEmpty())
00759         {
00760             return;
00761         }
00762         else
00763         {
00764             srcVol = vol;
00765             return;
00766         }
00767     }
00768     else if(vol.isEmpty())
00769     {
00770         return;
00771     }
00772
00773     srcVol.setBounds(osgMin(vol.getMin().x(), srcVol.getMin().x()),
00774                      osgMin(vol.getMin().y(), srcVol.getMin().y()),
00775                      osgMin(vol.getMin().z(), srcVol.getMin().z()),
00776                      osgMax(vol.getMax().x(), srcVol.getMax().x()),
00777                      osgMax(vol.getMax().y(), srcVol.getMax().y()),
00778                      osgMax(vol.getMax().z(), srcVol.getMax().z()));
00779
00780     if(vol.isInfinite())
00781         srcVol.setInfinite(true);
00782
00783     return;
00784 }
00785
00786
00787 OSG_BASE_DLLMAPPING
00788 void extend(OSG::BoxVolume &srcVol, const OSG::SphereVolume &vol)
00789 {
00790     Pnt3r min, max;
00791
00792     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
00793          srcVol.isInfinite()                       ||
00794          srcVol.isStatic  ()                         )
00795     {
00796         return;
00797     }
00798
00799     if(!vol.isValid())
00800         return;
00801
00802     if(srcVol.isEmpty())
00803     {
00804         if(vol.isEmpty())
00805         {
00806             return;
00807         }
00808         else
00809         {
00810             vol   .getBounds(min, max);
00811             srcVol.setBounds(min, max);
00812
00813             return;
00814         }
00815     }
00816     else if(vol.isEmpty())
00817     {
00818         return;
00819     }
00820
00821     vol.getBounds(min, max);
00822
00823     srcVol.setBounds(osgMin(min.x(), srcVol.getMin().x()),
00824                      osgMin(min.y(), srcVol.getMin().y()),
00825                      osgMin(min.z(), srcVol.getMin().z()),
00826                      osgMax(max.x(), srcVol.getMax().x()),
00827                      osgMax(max.y(), srcVol.getMax().y()),
00828                      osgMax(max.z(), srcVol.getMax().z()));
00829
00830     if(vol.isInfinite())
00831         srcVol.setInfinite(true);
00832
00833     return;
00834 }
00835
00836
00837 OSG_BASE_DLLMAPPING
00838 void extend(OSG::BoxVolume &srcVol, const OSG::CylinderVolume &vol)
00839 {
00840     Pnt3r min, max;
00841
00842     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
00843          srcVol.isInfinite()                       ||
00844          srcVol.isStatic  ()                         )
00845     {
00846         return;
00847     }
00848
00849     if(!vol.isValid())
00850         return;
00851
00852     if(srcVol.isEmpty())
00853     {
00854         if(vol.isEmpty())
00855         {
00856             return;
00857         }
00858         else
00859         {
00860             vol   .getBounds(min, max);
00861             srcVol.setBounds(min, max);
00862
00863             return;
00864         }
00865     }
00866     else if(vol.isEmpty())
00867     {
00868         return;
00869     }
00870
00871     vol.getBounds(min, max);
00872
00873     srcVol.setBounds(osgMin(min.x(), srcVol.getMin().x()),
00874                      osgMin(min.y(), srcVol.getMin().y()),
00875                      osgMin(min.z(), srcVol.getMin().z()),
00876                      osgMax(max.x(), srcVol.getMax().x()),
00877                      osgMax(max.y(), srcVol.getMax().y()),
00878                      osgMax(max.z(), srcVol.getMax().z()));
00879
00880     if(vol.isInfinite())
00881         srcVol.setInfinite(true);
00882
00883     return;
00884 }
00885
00886
00887 OSG_BASE_DLLMAPPING
00888 void extend(      OSG::BoxVolume     &OSG_CHECK_ARG(srcVol),
00889             const OSG::FrustumVolume &OSG_CHECK_ARG(vol   ))
00890 {
00891     FFATAL(("extend (box/frustum) is not impl.\n"));
00892     return;
00893 }
00894
00895
00896 #ifdef __sgi
00897 #   pragma set woff 1174, 1552
00898 #endif
00899 
00900 OSG_BASE_DLLMAPPING
00901 void extend(OSG::BoxVolume &srcVol, const OSG::Volume &vol)
00902 {
00903     const BoxVolume      *bv;
00904     const SphereVolume   *sv;
00905     const CylinderVolume *cv;
00906     const FrustumVolume  *fv;
00907
00908     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
00909     {
00910         extend(srcVol, *bv);
00911     }
00912     else if((sv = dynamic_cast<const SphereVolume *>(&vol)) != NULL)
00913     {
00914         extend(srcVol, *sv);
00915     }
00916     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
00917     {
00918         extend(srcVol, *cv);
00919     }
00920     else if((fv = dynamic_cast<const FrustumVolume *>(&vol)) != NULL)
00921     {
00922         extend(srcVol, *fv);
00923     }
00924     else
00925     {
00926         FWARNING(
00927             ("extend(BoxVolume, Volume): Argument 2 has unhandled type.\n"));
00928     }
00929 }
00930
00931 #ifdef __sgi
00932 #   pragma reset woff 1174, 1552
00933 #endif
00934 
00935 // # Sphere ###########################################################
00936
00937 OSG_BASE_DLLMAPPING
00938 void extend(OSG::SphereVolume &srcVol, const OSG::BoxVolume &vol)
00939 {
00940     Pnt3r     min, max, min1, max1, c;
00941     Real      r;
00942     BoxVolume vol1;
00943
00944     vol.getBounds(min, max);
00945
00946     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
00947          srcVol.isInfinite()                       ||
00948          srcVol.isStatic  ()                         )
00949     {
00950         return;
00951     }
00952
00953     if(!vol.isValid())
00954         return;
00955
00956     if(srcVol.isEmpty())
00957     {
00958         if(vol.isEmpty())
00959         {
00960             return;
00961         }
00962         else
00963         {
00964             c = Pnt3r((min.x() + max.x()) * 0.5f,
00965                       (min.y() + max.y()) * 0.5f,
00966                       (min.z() + max.z()) * 0.5f);
00967
00968             r = ((max - min).length()) / 2.f;
00969
00970             srcVol.setValue(c, r);
00971
00972             return;
00973         }
00974     }
00975     else if(vol.isEmpty())
00976     {
00977         return;
00978     }
00979
00980     srcVol.getBounds(min1, max1);
00981
00982     vol1.setBounds(osgMin(min.x(), min1.x()), osgMin(min.y(), min1.y()),
00983                    osgMin(min.z(), min1.z()), osgMax(max.x(), max1.x()),
00984                    osgMax(max.y(), max1.y()), osgMax(max.z(), max1.z()));
00985
00986     vol1.getBounds(min, max);
00987
00988     c = Pnt3r((min.x() + max.x()) * 0.5f,
00989               (min.y() + max.y()) * 0.5f,
00990               (min.z() + max.z()) * 0.5f);
00991
00992     r = ((max - min).length()) / 2.f;
00993
00994     srcVol.setValue(c, r);
00995
00996     return;
00997 }
00998
00999
01000 OSG_BASE_DLLMAPPING
01001 void extend(OSG::SphereVolume &srcVol, const OSG::SphereVolume &vol)
01002 {
01003     Pnt3r min, max, min1, max1, min2, max2, c;
01004     Real  r;
01005
01006     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
01007          srcVol.isInfinite()                       ||
01008          srcVol.isStatic  ()                         )
01009     {
01010         return;
01011     }
01012
01013     if(!vol.isValid())
01014         return;
01015
01016     if(srcVol.isEmpty())
01017     {
01018         if(vol.isEmpty())
01019         {
01020             return;
01021         }
01022         else
01023         {
01024             srcVol = vol;
01025
01026             return;
01027         }
01028     }
01029     else if(vol.isEmpty())
01030     {
01031         return;
01032     }
01033
01034     srcVol.getBounds(min,  max );
01035     vol   .getBounds(min1, max1);
01036
01037     min2 = Pnt3r(osgMin(min.x(), min1.x()),
01038                  osgMin(min.y(), min1.y()),
01039                  osgMin(min.z(), min1.z()));
01040
01041     max2 = Pnt3r(osgMax(max.x(), max1.x()),
01042                  osgMax(max.y(), max1.y()),
01043                  osgMax(max.z(), max1.z()));
01044
01045     c = Pnt3r((min2.x() + max2.x()) * 0.5f,
01046               (min2.y() + max2.y()) * 0.5f,
01047               (min2.z() + max2.z()) * 0.5f);
01048
01049     r = ((max2 - min2).length()) * 0.5f;
01050
01051     srcVol.setValue(c, r);
01052
01053     return;
01054 }
01055
01056
01057 OSG_BASE_DLLMAPPING
01058 void extend(OSG::SphereVolume &srcVol, const OSG::CylinderVolume &vol)
01059 {
01060     Pnt3r min, max, min1, max1, min2, max2, c;
01061     Real  r;
01062
01063     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
01064          srcVol.isInfinite()                       ||
01065          srcVol.isStatic  ()                         )
01066     {
01067         return;
01068     }
01069
01070     if(!vol.isValid())
01071         return;
01072
01073     if(srcVol.isEmpty())
01074     {
01075         if(vol.isEmpty())
01076         {
01077             return;
01078         }
01079         else
01080         {
01081             vol.getBounds(min, max);
01082             vol.getCenter(c);
01083
01084             r = (min - c).length();
01085
01086             srcVol.setValue(c, r);
01087
01088             return;
01089         }
01090     }
01091     else if(vol.isEmpty())
01092     {
01093         return;
01094     }
01095
01096     srcVol.getBounds(min,  max);
01097     vol   .getBounds(min1, max1);
01098
01099     min2 = Pnt3r(osgMin(min.x(), min1.x()),
01100                  osgMin(min.y(), min1.y()),
01101                  osgMin(min.z(), min1.z()));
01102
01103     max2 = Pnt3r(osgMax(max.x(), max1.x()),
01104                  osgMax(max.y(), max1.y()),
01105                  osgMax(max.z(), max1.z()));
01106
01107     c = Pnt3r((min2.x() + max2.x()) * 0.5f,
01108               (min2.y() + max2.y()) * 0.5f,
01109               (min2.z() + max2.z()) * 0.5f);
01110
01111     r = ((max2 - min2).length()) * 0.5f;
01112
01113     srcVol.setValue(c, r);
01114
01115     return;
01116 }
01117
01118
01119 OSG_BASE_DLLMAPPING
01120 void extend(      OSG::SphereVolume  &OSG_CHECK_ARG(srcVol),
01121             const OSG::FrustumVolume &OSG_CHECK_ARG(vol   ))
01122 {
01123     FFATAL(("extend (sphere/frustum) is not impl.\n"));
01124     return;
01125 }
01126
01127
01128 OSG_BASE_DLLMAPPING
01129 void extend(OSG::SphereVolume &srcVol, const OSG::Volume &vol)
01130 {
01131     const BoxVolume      *bv;
01132     const SphereVolume   *sv;
01133     const CylinderVolume *cv;
01134     const FrustumVolume  *fv;
01135
01136     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
01137     {
01138         extend(srcVol, *bv);
01139     }
01140     else if((sv = dynamic_cast<const SphereVolume *>(&vol)) != NULL)
01141     {
01142         extend(srcVol, *sv);
01143     }
01144     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
01145     {
01146         extend(srcVol, *cv);
01147     }
01148     else if((fv = dynamic_cast<const FrustumVolume *>(&vol)) != NULL)
01149     {
01150         extend(srcVol, *fv);
01151     }
01152     else
01153     {
01154         FWARNING(
01155             ("extend(SphereVolume, Volume): Argument 2 has unhandled type.\n"));
01156     }
01157 }
01158
01159
01160 // # Cylinder ########################################################
01161
01162 OSG_BASE_DLLMAPPING
01163 void extend(OSG::CylinderVolume &srcVol, const OSG::BoxVolume &vol)
01164 {
01165     Pnt3r min, max, min1, max1, min2, max2, apos;
01166     Vec2r p;
01167     Vec3r adir;
01168     Real  r;
01169
01170     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
01171          srcVol.isInfinite()                       ||
01172          srcVol.isStatic  ()                         )
01173     {
01174         return;
01175     }
01176
01177     if(!vol.isValid())
01178     {
01179         return;
01180     }
01181
01182     if(srcVol.isEmpty())
01183     {
01184         if(vol.isEmpty())
01185         {
01186             return;
01187         }
01188         else
01189         {
01190             vol.getBounds(min, max);
01191
01192             p = Vec2r(max.x() - min.x(), max.y() - min.y());
01193             r = (p.length()) * 0.5f;
01194
01195             adir = Vec3r(0.f, 0.f, max.z() - min.z());
01196             apos = Pnt3r(p.x(), p.y(), min.z());
01197
01198             srcVol.setValue(apos, adir, r);
01199
01200             return;
01201         }
01202     }
01203     else if(vol.isEmpty())
01204     {
01205         return;
01206     }
01207
01208     srcVol.getBounds(min,  max );
01209     vol   .getBounds(min1, max1);
01210
01211     min2 = Pnt3r(osgMin(min.x(), min1.x()),
01212                  osgMin(min.y(), min1.y()),
01213                  osgMin(min.z(), min1.z()));
01214     max2 = Pnt3r(osgMax(max.x(), max1.x()),
01215                  osgMax(max.y(), max1.y()),
01216                  osgMax(max.z(), max1.z()));
01217
01218     p = Vec2r(max2.x() - min2.x(), max2.y() - min2.y());
01219     r = (p.length()) * 0.5f;
01220
01221     adir = Vec3r(0.f, 0.f, max2.z() - min2.z());
01222     apos = Pnt3r(p.x(), p.y(), min2.z());
01223
01224     srcVol.setValue(apos, adir, r);
01225
01226     return;
01227 }
01228
01229
01230 OSG_BASE_DLLMAPPING
01231 void extend(OSG::CylinderVolume &srcVol, const OSG::SphereVolume &vol)
01232 {
01233     Pnt3r min, max, min1, max1, min2, max2, apos;
01234     Vec2r p;
01235     Vec3r adir;
01236     Real r;
01237
01238     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
01239          srcVol.isInfinite()                       ||
01240          srcVol.isStatic  ()                         )
01241     {
01242         return;
01243     }
01244
01245     if(!vol.isValid())
01246         return;
01247
01248     if(srcVol.isEmpty())
01249     {
01250         if(vol.isEmpty())
01251         {
01252             return;
01253         }
01254         else
01255         {
01256             r = vol.getRadius();
01257
01258             apos = Pnt3r(vol.getCenter().x() - r,
01259                          vol.getCenter().y() - r,
01260                          vol.getCenter().z() - r);
01261             adir = Vec3r(vol.getCenter().x() + r - apos.x(),
01262                          vol.getCenter().y() + r - apos.y(),
01263                          vol.getCenter().z() + r - apos.z());
01264
01265             srcVol.setValue(apos, adir, r);
01266
01267             return;
01268         }
01269     }
01270     else if(vol.isEmpty())
01271     {
01272         return;
01273     }
01274
01275     srcVol.getBounds(min,  max);
01276     vol   .getBounds(min1, max1);
01277
01278     min2 = Pnt3r(osgMin(min.x(), min1.x()),
01279                  osgMin(min.y(), min1.y()),
01280                  osgMin(min.z(), min1.z()));
01281     max2 = Pnt3r(osgMax(max.x(), max1.x()),
01282                  osgMax(max.y(), max1.y()),
01283                  osgMax(max.z(), max1.z()));
01284
01285     p = Vec2r(max2.x() - min2.x(), max2.y() - min2.y());
01286     r = (p.length()) * 0.5f;
01287
01288     adir = Vec3r(0.f, 0.f, max2.z() - min2.z());
01289     apos = Pnt3r(p.x(), p.y(), min2.z());
01290
01291     srcVol.setValue(apos, adir, r);
01292
01293     return;
01294 }
01295
01296
01297 OSG_BASE_DLLMAPPING
01298 void extend(OSG::CylinderVolume &srcVol, const OSG::CylinderVolume &vol)
01299 {
01300     Pnt3r min, max, min1, max1, min2, max2, apos;
01301     Vec2r p;
01302     Vec3r adir;
01303     Real  r;
01304
01305     if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
01306          srcVol.isInfinite()                       ||
01307          srcVol.isStatic  ()                         )
01308     {
01309         return;
01310     }
01311
01312     if(!vol.isValid())
01313         return;
01314
01315     if(srcVol.isEmpty())
01316     {
01317         if(vol.isEmpty())
01318         {
01319             return;
01320         }
01321         else
01322         {
01323             srcVol = vol;
01324             return;
01325         }
01326     }
01327     else if(vol.isEmpty())
01328     {
01329         return;
01330     }
01331
01332     srcVol.getBounds(min,  max);
01333     vol   .getBounds(min1, max1);
01334
01335     min2 = Pnt3r(osgMin(min.x(), min1.x()),
01336                  osgMin(min.y(), min1.y()),
01337                  osgMin(min.z(), min1.z()));
01338     max2 = Pnt3r(osgMax(max.x(), max1.x()),
01339                  osgMax(max.y(), max1.y()),
01340                  osgMax(max.z(), max1.z()));
01341
01342     p = Vec2r(max2.x() - min2.x(), max2.y() - min2.y());
01343     r = (p.length()) * 0.5f;
01344
01345     adir = Vec3r(0.f, 0.f, max2.z() - min2.z());
01346     apos = Pnt3r(p.x(), p.y(), min2.z());
01347
01348     srcVol.setValue(apos, adir, r);
01349
01350     return;
01351 }
01352
01353
01354 OSG_BASE_DLLMAPPING
01355 void extend(      OSG::CylinderVolume &OSG_CHECK_ARG(srcVol),
01356             const OSG::FrustumVolume  &OSG_CHECK_ARG(vol   ))
01357 {
01358     FFATAL(("extend (cylinder/frustum) is not impl.\n"));
01359     return;
01360 }
01361
01362
01363 OSG_BASE_DLLMAPPING
01364 void extend(OSG::CylinderVolume &srcVol, const OSG::Volume &vol)
01365 {
01366     const BoxVolume      *bv;
01367     const SphereVolume   *sv;
01368     const CylinderVolume *cv;
01369     const FrustumVolume  *fv;
01370
01371     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
01372     {
01373         extend(srcVol, *bv);
01374     }
01375     else if((sv = dynamic_cast<const SphereVolume *>(&vol)) != NULL)
01376     {
01377         extend(srcVol, *sv);
01378     }
01379     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
01380     {
01381         extend(srcVol, *cv);
01382     }
01383     else if((fv = dynamic_cast<const FrustumVolume *>(&vol)) != NULL)
01384     {
01385         extend(srcVol, *fv);
01386     }
01387     else
01388     {
01389         FWARNING(
01390             ("extend(Cylinder, Volume): Argument 2 has unhandled type.\n"));
01391     }
01392 }
01393
01394
01395 // # Frustum ########################################################
01396
01397 OSG_BASE_DLLMAPPING
01398 void extend(      OSG::FrustumVolume &OSG_CHECK_ARG(srcVol),
01399             const OSG::BoxVolume     &OSG_CHECK_ARG(vol   ))
01400 {
01401     FFATAL(("extend (frustum/box) is not impl.\n"));
01402     return;
01403 }
01404
01405
01406 OSG_BASE_DLLMAPPING
01407 void extend(      OSG::FrustumVolume &OSG_CHECK_ARG(srcVol),
01408             const OSG::SphereVolume  &OSG_CHECK_ARG(vol   ))
01409 {
01410     FFATAL(("extend (frustum/sphere) is not impl.\n"));
01411     return;
01412 }
01413
01414
01415 OSG_BASE_DLLMAPPING
01416 void extend(      OSG::FrustumVolume  &OSG_CHECK_ARG(srcVol),
01417             const OSG::CylinderVolume &OSG_CHECK_ARG(vol   ))
01418 {
01419     FFATAL(("extend (frustum/cylinder) is not impl.\n"));
01420     return;
01421 }
01422
01423
01424 OSG_BASE_DLLMAPPING
01425 void extend(      OSG::FrustumVolume &OSG_CHECK_ARG(srcVol),
01426             const OSG::FrustumVolume &OSG_CHECK_ARG(vol   ))
01427 {
01428     FFATAL(("extend (frustum/frustum) is not impl.\n"));
01429     return;
01430 }
01431
01432
01433 OSG_BASE_DLLMAPPING
01434 void extend(      OSG::FrustumVolume &srcVol,
01435             const OSG::Volume        &vol    )
01436 {
01437     const BoxVolume      *bv;
01438     const SphereVolume   *sv;
01439     const CylinderVolume *cv;
01440     const FrustumVolume  *fv;
01441
01442     if((bv = dynamic_cast<const BoxVolume *>(&vol)) != NULL)
01443     {
01444         extend(srcVol, *bv);
01445     }
01446     else if((sv = dynamic_cast<const SphereVolume *>(&vol)) != NULL)
01447     {
01448         extend(srcVol, *sv);
01449     }
01450     else if((cv = dynamic_cast<const CylinderVolume *>(&vol)) != NULL)
01451     {
01452         extend(srcVol, *cv);
01453     }
01454     else if((fv = dynamic_cast<const FrustumVolume *>(&vol)) != NULL)
01455     {
01456         extend(srcVol, *fv);
01457     }
01458     else
01459     {
01460         FWARNING(
01461             ("extend(Frustum, Volume): Argument 2 has unhandled type.\n"));
01462     }
01463 }
01464
01465 OSG_END_NAMESPACE
01466