OSG_BASE_DLLMAPPING 
void extend(SphereVolume &srcVol, const CylinderVolume &vol)
{
    Pnt3f   min, max, min1, max1, min2, max2, c;
    Real32  r;

    if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
         srcVol.isInfinite()                       ||
         srcVol.isStatic  ()                         )
    {
        return;
    }

    if(!vol.isValid())
        return;

    if(srcVol.isEmpty())
    {
        if(vol.isEmpty())
        {
            return;
        }
        else
        {
            vol.getBounds(min, max);
            vol.getCenter(c);

            r = (min - c).length();

            srcVol.setValue(c, r);

            return;
        }
    }
    else if(vol.isEmpty())
    {
        return;
    }

    srcVol.getBounds(min,  max);
    vol   .getBounds(min1, max1);

    min2 = Pnt3f(osgMin(min.x(), min1.x()), 
                 osgMin(min.y(), min1.y()),
                 osgMin(min.z(), min1.z()));

    max2 = Pnt3f(osgMax(max.x(), max1.x()), 
                 osgMax(max.y(), max1.y()),
                 osgMax(max.z(), max1.z()));

    c = Pnt3f((min2.x() + max2.x()) * 0.5f, 
              (min2.y() + max2.y()) * 0.5f,
              (min2.z() + max2.z()) * 0.5f);

    r = ((max2 - min2).length()) * 0.5f;

    srcVol.setValue(c, r);

    return;
}
OSG_BASE_DLLMAPPING 
void extend(CylinderVolume &srcVol, const CylinderVolume &vol)
{
    Pnt3f  min, max, min1, max1, min2, max2, apos;
    Vec2f  p;
    Vec3f  adir;
    Real32 r;

    if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
         srcVol.isInfinite()                       ||
         srcVol.isStatic  ()                         )
    {
        return;
    }

    if(!vol.isValid())
        return;

    if(srcVol.isEmpty())
    {
        if(vol.isEmpty())
        {
            return;
        }
        else
        {
            srcVol = vol;
            return;
        }
    }
    else if(vol.isEmpty())
    {
        return;
    }

    srcVol.getBounds(min,  max);
    vol   .getBounds(min1, max1);

    min2 = Pnt3f(osgMin(min.x(), min1.x()), 
                 osgMin(min.y(), min1.y()),
                 osgMin(min.z(), min1.z()));
    max2 = Pnt3f(osgMax(max.x(), max1.x()), 
                 osgMax(max.y(), max1.y()),
                 osgMax(max.z(), max1.z()));

    p = Vec2f(max2.x() - min2.x(), max2.y() - min2.y());
    r = (p.length()) * 0.5f;

    adir = Vec3f(0.f, 0.f, max2.z() - min2.z());
    apos = Pnt3f(p.x(), p.y(), min2.z());

    srcVol.setValue(apos, adir, r);

    return;
}
OSG_BASE_DLLMAPPING 
bool intersect(const CylinderVolume &cyl1, 
               const CylinderVolume &cyl2)
{
    Pnt3f p1, p2;
    Vec3f v1, v2;
    cyl1.getAxis(p1, v1);
    cyl2.getAxis(p2, v2);
    return dist3D_Segment_to_Segment(p1, v1, p2, v2) <= 
            (cyl1.getRadius() + cyl2.getRadius());
}
OSG_BASE_DLLMAPPING 
void extend(BoxVolume &srcVol, const CylinderVolume &vol)
{
    Pnt3f min, max;

    if((!srcVol.isValid   () && !srcVol.isEmpty()) ||
         srcVol.isInfinite()                       ||
         srcVol.isStatic  ()                         )
    {
        return;
    }

    if(!vol.isValid())
        return;

    if(srcVol.isEmpty())
    {
        if(vol.isEmpty())
        {
            return;
        }
        else
        {
            vol   .getBounds(min, max);
            srcVol.setBounds(min, max);

            return;
        }
    }
    else if(vol.isEmpty())
    {
        return;
    }

    vol.getBounds(min, max);

    srcVol.setBounds(osgMin(min.x(), srcVol.getMin().x()),
                     osgMin(min.y(), srcVol.getMin().y()),
                     osgMin(min.z(), srcVol.getMin().z()),
                     osgMax(max.x(), srcVol.getMax().x()),
                     osgMax(max.y(), srcVol.getMax().y()),
                     osgMax(max.z(), srcVol.getMax().z()));

    if(vol.isInfinite())
        srcVol.setInfinite(true);

    return;
}
OSG_BASE_DLLMAPPING 
void extend(CylinderVolume &srcVol, const Volume &vol)
{
    const Volume         *v       = &vol;
    const CylinderVolume *cylinder;
    
#ifndef OSG_2_PREP
    const DynamicVolume  *dynamic = dynamic_cast<const DynamicVolume *>(v);

    if(dynamic)
    {
        v = &(dynamic->getInstance());
    }
#endif

    if((cylinder = dynamic_cast<const CylinderVolume *>(v)) != NULL)
    {
        OSG::extend(srcVol, *cylinder);
    }
    else
    {
        CylinderVolume localCylinder;
        Pnt3f          min, max, apos;
        Vec3f          adir;
        Real32         r;
        Vec2f          p;

        v->getBounds(min, max);

        p = Vec2f(max.x() - min.x(), max.y() - min.y());
        r = (p.length()) * 0.5f;

        adir = Vec3f(0.f, 0.f, max.z() - min.z());
        apos = Pnt3f(p.x(), p.y(), min.z());

        localCylinder.setValue(apos, adir, r);

        OSG::extend(srcVol, localCylinder);
    }

    return;
}
OSG_BASE_DLLMAPPING 
bool intersect(const CylinderVolume &cylinder, const FrustumVolume &frustum)
{
    Pnt3f min, max;
    cylinder.getBounds(min, max);

    const Plane       *frust = frustum.getPlanes();

    // check each point of the box to the 6 planes

    for(Int32 i = 0; i < 6; i++)
    {
        if(frust[i].isOutHalfSpace(min, max))
            return false;
    }

    return true;
}
OSG_BASE_DLLMAPPING 
bool intersect(const SphereVolume &sphere, const CylinderVolume &cylinder)
{
    bool  retCode;
    Pnt3f apos;
    Vec3f adir;

    cylinder.getAxis(apos, adir);

    if(sphere.isEmpty() || cylinder.isEmpty())
    {
        retCode = false;
    }
    else if(sphere.isInfinite() || cylinder.isInfinite())
    {
        retCode = true;
    }
    else
    {
        Real32  d = 0.f, s1 = 0.f, s2 = 0.f;
        Pnt3f   c;
        Vec3f   u, u1, u2;

        //get the distance between the upper and lower point of the cylinder
        // and the sphere center

        s1 = (apos        - sphere.getCenter()).length();
        s2 = (apos + adir - sphere.getCenter()).length();

        if ((s1<=DBL_EPSILON) || (s2<=DBL_EPSILON)) 
            return true;
        
        //check the smallest distance and set the vector coordinate
        if(s1 <= s2)
        {
            d = s1;
            c = apos;
        }
        else
        {
            d = s2;
            c = apos + adir;
        }

        // decompose the vector in u1 and u2 which are parallel and 
        // perpendicular to the cylinder axis respectively

        u  = ((d - sphere.getRadius()) / d) * (c - sphere.getCenter());

        u1 = (u[0] * adir[0] + u[1] * adir[1] + u[2] * adir[2]) / 
             (adir.length() * adir.length()) * adir;
        u2 = u - u1;

        if(u2.length() <= 10e-6)
        {
            retCode = (d <= sphere.getRadius());
        }
        else
        {
            retCode = (u2.length() <= cylinder.getRadius());
        }
    }

    return retCode;
}
OSG_BASE_DLLMAPPING 
bool intersect(const BoxVolume &box, const CylinderVolume &cylinder)
{
    bool  retCode;
    Pnt3f apos;
    Vec3f adir;

    cylinder.getAxis(apos, adir);

    if(box.isEmpty() == true || cylinder.isEmpty() == true)
    {
        retCode = false;
    }
    else if(box.isInfinite() == true || cylinder.isInfinite() == true)
    {
        retCode = true;
    }
    else
    {
        Real32  s1 = 0, s2 = 0, s3 = 0, s4 = 0, d = 0, d1 = 0, d2 = 0;
        Pnt3f   c, p, p1, p2;
        Vec3f   u, u1, u2;

        // find the distance between the min and the max of the box
        //with the lower point and the upper point of the cylinder respectively

        s1 = (apos - box.getMin()).length();
        s2 = (apos - box.getMax()).length();

        s3 = (apos + adir - box.getMin()).length();
        s4 = (apos + adir - box.getMax()).length();

        //Check the minimum of the above distances

        if(s1 <= s2)
        {
            d1 = s1;
            p1 = box.getMin();
        }
        else
        {
            d1 = s2;
            p1 = box.getMax();
        }

        if(s3 <= s4)
        {
            d2 = s3;
            p2 = box.getMin();
        }
        else
        {
            d2 = s4;
            p2 = box.getMax();
        }

        //set the value of the vector corresponding to the shortest distance
        if(d1 <= d2)
        {
            d = d1;
            c = apos;
            p = p1;
        }
        else
        {
            d = d2;
            c = apos + adir;
            p = p2;
        }

        // decompose the vector in u1 and u2 which are parallel and 
        // perpendicular to the cylinder axis respectively
        u  = p - c;
        u1 = (u[0] * adir[0] + u[1] * adir[1] + u[2] * adir[2]) /
            (adir.length() * adir.length()) * adir;

        u2 = u - u1;

        if(u1.length() <= 10e-6)
        {
            retCode = true;
        }
        else if(u2.length() <= 10e-6)
        {
            retCode = (d <= 10e-6);
        }
        else
        {
            retCode = (u2.length() <= cylinder.getRadius());
        }
    }

    return retCode;
}
Exemple #9
0
int main (int argc, char **argv) {

    Real32 ent, ex;
    int i;

    //Lines:

    const int nlines = 10;

    Line lines[nlines];
    Pnt3f pnts[nlines * 2] = {
                        Pnt3f(0,0,0), Pnt3f(0,1,0),
                        Pnt3f(0,0,0), Pnt3f(2,1,0),
                        Pnt3f(2,0,0), Pnt3f(2,1,0),
                        Pnt3f(-2,0,0), Pnt3f(0,2,0),
                        Pnt3f(-4,2,0), Pnt3f(0,2,0),
                        Pnt3f(-3,0,0), Pnt3f(-2,1,0),
                        Pnt3f(3,4,0), Pnt3f(1,3,0),
                        Pnt3f(-1,0,0), Pnt3f(-1,1,0),
                        Pnt3f(-4,0,0), Pnt3f(-3,1,0),
                        Pnt3f(-4,6,0), Pnt3f(0,6,0)
                        };

    for ( i = 0; i < nlines; i++ )
        lines[i].setValue( pnts[i*2], pnts[i*2+1] );


    BoxVolume b;

    float xmin, ymin, zmin, xmax, ymax, zmax;

    xmin = 0;
    ymin = 0.5;
    zmin = 0;
    xmax = 1;
    ymax = .5;
    zmax = 1;

    b.setBounds(xmin, ymin, zmin, xmax, ymax, zmax);

    std::cout << std::endl;
    b.dump();
    std::cout << std::endl;

    for ( i = 0 ; i < nlines; i++ )
    {
        std::cout << "Line: (" << lines[i].getPosition() << ") ("
             << lines[i].getDirection() << ")" << std::endl;

        bool res = lines[i].intersect( b, ent, ex );
        Pnt3f   ep = lines[i].getPosition() + ent * lines[i].getDirection(),
                xp = lines[i].getPosition() + ex * lines[i].getDirection();

        std::cout << "Result: " << res;

        if ( res )
        {
            std::cout << " enter " << ent << "=(" << ep << ") ";

            bool es = ( b.isOnSurface( ep ) || b.intersect( ep ) ),
                 xs = b.isOnSurface( xp );

            if ( ( res && es ) || !res )    std::cout << "ok";
            else                            std::cout << "**BAD**";

            std::cout << ";  exit " << ex << "=(" << xp << ") ";

            if ( ( res && xs ) || !res )    std::cout << "ok";
            else                            std::cout << "**BAD**";
        }

        std::cout << std::endl;
    }

    return 0;

    SphereVolume s;

    float radius;
    Vec3f center;

    center[0] = 0;
    center[1] = 0;
    center[2] = 0;

    radius = 1;

    s.setCenter(center);
    s.setRadius(radius);

    std::cout << std::endl;
    s.dump();
    std::cout << std::endl;


    for ( i = 0 ; i < nlines; i++ )
    {
        std::cout << "Line: (" << lines[i].getPosition() << ") ("
                  << lines[i].getDirection() << ")" << std::endl;

        bool res = lines[i].intersect( s, ent, ex );
        Pnt3f   ep = lines[i].getPosition() + ent * lines[i].getDirection(),
                xp = lines[i].getPosition() + ex * lines[i].getDirection();

        std::cout << "Result: " << res;

        if ( res )
        {
            std::cout << " enter " << ent << "=(" << ep << ") ";

            bool es = ( s.isOnSurface( ep ) || s.intersect( ep ) ),
                 xs = s.isOnSurface( xp );

            if ( ( res && es ) || !res )    std::cout << "ok";
            else                            std::cout << "**BAD**";

            std::cout << ";  exit " << ex << "=(" << xp << ") ";

            if ( ( res && xs ) || !res )    std::cout << "ok";
            else                            std::cout << "**BAD**";
        }

        std::cout << std::endl;
    }

//  Intersect the line with a cylinder.


    Pnt3f p;
    Vec3f d;
    float rad;

    p[0] = 0;
    p[1] = 1;
    p[2] = 0;

    d[0] = 0;
    d[1] = 4;
    d[2] = 0;

    rad = 2;

    CylinderVolume c;

    c.setValue(p, d, rad);

//  c.setAxis(p, d);
//  c.setRadius(rad);

    std::cout << std::endl;
    c.dump();
    std::cout << std::endl;


    for ( i = 0 ; i < nlines; i++ )
    {
        std::cout << "Line: (" << lines[i].getPosition() << ") ("
             << lines[i].getDirection() << ")" << std::endl;

        bool res = lines[i].intersect( c, ent, ex );
        Pnt3f   ep = lines[i].getPosition() + ent * lines[i].getDirection(),
                xp = lines[i].getPosition() + ex * lines[i].getDirection();

        std::cout << "Result: " << res;

        if ( res )
        {
            std::cout << " enter " << ent << "=(" << ep << ") ";

            bool es = ( c.isOnSurface( ep ) || c.intersect( ep ) ),
                 xs = c.isOnSurface( xp );

            if ( ( res && es ) || !res )    std::cout << "ok";
            else                            std::cout << "**BAD**";

            std::cout << ";  exit " << ex << "=(" << xp << ") ";

            if ( ( res && xs ) || !res )    std::cout << "ok";
            else                            std::cout << "**BAD**";
        }

        std::cout << std::endl;
    }

    //### volume intersection ##############################################


    std::cout << "### volume intersection test ###" << std::endl;

    BoxVolume box(-1,-1,-1,1,1,1);
    BoxVolume boxOut (5,5,5,10,10,10);
    BoxVolume boxIn(-1,-1,-1,2,2,2);

    SphereVolume sphere(Pnt3f(0,0,0),2);
    SphereVolume sphereOut(Pnt3f(2,2,2),1);
    SphereVolume sphereIn(Pnt3f(1,0,0),1);

    CylinderVolume cylinder(Pnt3f(0,0,0),Vec3f(1,1,1),1);
    CylinderVolume cylinderOut(Pnt3f(0,9,9),Vec3f(0,0,1),1);
    CylinderVolume cylinderIn(Pnt3f(1,0,0),Vec3f(0,1,0),1);


    // Frustum defined by normal vector and distance

    Plane pnear(Vec3f(0,0,-1),2);
    Plane pfar(Vec3f(0,0,1),7);
    Plane pright(Vec3f(-0.7071,0,-0.7071),0);
    Plane pleft(Vec3f(0.7071,0,-0.7071),0);
    Plane ptop(Vec3f(0,-0.7071,-0.7071),0);
    Plane pbottom(Vec3f(0,0.7071,-0.7071),0);

    FrustumVolume frustum(pnear, pfar, pleft, pright, ptop, pbottom);

    //Frustum defined by a clipMatrix

    Matrix matrix;
    matrix.setValue(0.7071,0,0,0,
            0,0.7071,0,0,
            0,0,-1.27,-3.959,
            0,0,-0.7071,0);

    FrustumVolume frustum1;
    frustum1.setPlanes(matrix);

    // Frustum defined by 8 points

    Pnt3f nlt(-2,2,-2);
    Pnt3f nlb(-2,-2,-2);
    Pnt3f nrt(2,2,-2);
    Pnt3f nrb(2,-2,-2);
    Pnt3f flt(-7,7,-7);
    Pnt3f flb(-7,-7,-7);
    Pnt3f frt(7,7,-7);
    Pnt3f frb(7,-7,-7);

    FrustumVolume frustum2;
    frustum2.setPlanes(nlt, nlb, nrt, nrb, flt, flb, frt, frb);


        //Tests

    std::cout << "Box/box outside test: " << std::flush;
    std::cout << (box.intersect(boxOut) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Box/box inside test: " << std::flush;
    std::cout << (box.intersect(boxIn) ? "ok" : "**BAD**") << std::endl;

    std::cout << "Box/sphere outside test: " << std::flush;
    std::cout << (box.intersect(sphereOut) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Box/sphere inside test: " << std::flush;
    std::cout << (box.intersect(sphereIn) ? "ok" : "**BAD**")<< std::endl;

    std::cout << "Sphere/sphere outside test: " << std::flush;
    std::cout << (sphere.intersect(sphereOut) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Sphere/sphere inside test: " << std::flush;
    std::cout << (sphere.intersect(sphereIn) ? "ok" : "**BAD**") << std::endl;

    std::cout << "Box/cylinder outside test: " << std::flush;
    std::cout << (box.intersect(cylinderOut) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Box/cylinder inside test: " << std::flush;
    std::cout << (box.intersect(cylinderIn) ? "ok" : "**BAD**") << std::endl;

    std::cout << "Sphere/cylinder outside test: " << std::flush;
    std::cout << (sphere.intersect(cylinderOut) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Sphere/cylinder inside test: " << std::flush;
    std::cout << (sphere.intersect(cylinderIn) ? "ok" : " **BAD**") << std::endl;

    std::cout << "Cylinder/cylinder outside test: "<<std::flush;
    std::cout << (cylinder.intersect(cylinderOut) ? "**BAD**" : "ok")<<std::endl;

    std::cout << "Cylinder/cylinder inside test: "<<std::flush;
    std::cout << (cylinder.intersect(cylinderIn) ? "ok" : " **BAD** ")<<std::endl;

    std::cout << "Box/Frustum outside test : " << std::flush;
    std::cout << (boxOut.intersect(frustum) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Box/Frustum inside test : " << std::flush;
    std::cout << (boxIn.intersect(frustum) ? "ok" : "**BAD**") << std::endl;

    std::cout << "Sphere/Frustum outside test : " << std::flush;
    std::cout << (sphereOut.intersect(frustum) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Sphere/Frustum inside test : " << std::flush;
    std::cout << (sphereIn.intersect(frustum) ? "ok" : "**BAD**") << std::endl;


    std::cout << "Cylinder/Frustum outside test : " << std::flush;
    std::cout << (cylinderOut.intersect(frustum) ? "**BAD**" : "ok") << std::endl;

    std::cout << "Cylinder/Frustum inside test : " << std::flush;
    std::cout << (cylinderIn.intersect(frustum) ? "ok" : "**BAD**") << std::endl;

    std::cout << "Cylinder/Sphere outside test: " << std::flush;
    std::cout << (cylinderOut.intersect(sphere) ? "**BAD**" : "ok") << std::endl;

    //###VOLUME EXTENSION################################################

    std::cout << "### volume extension test ###" << std::endl;

    Pnt3f min,max;

    //Box extension

    extend(box, boxIn);
    box.getBounds(min,max);
    std::cout<< "min of the box : " <<min<<std::endl;
    std::cout<< "max of the box : " <<max<<std::endl;

    extend(box,sphere);
    box.getBounds(min,max);
    std::cout<< "min of the box : " <<min<<std::endl;
    std::cout<< "max of the box : " <<max<<std::endl;

    extend(box,cylinder);
    box.getBounds(min,max);
    std::cout<< "min of the box : " <<min<<std::endl;
    std::cout<< "max of the box : " <<max<<std::endl;

    //Sphere extension

    extend(sphere, box);
    std::cout<<"Center of the sphere : " <<sphere.getCenter()<<std::endl;
    std::cout<<"Radius of the sphere : " <<sphere.getRadius()<<std::endl;

    extend(sphere, sphereOut);
    std::cout<<"Center of the sphere : " <<sphere.getCenter()<<std::endl;
    std::cout<<"Radius of the sphere : " <<sphere.getRadius()<<std::endl;

    extend(sphere, cylinder);
    std::cout<<"Center of the sphere : " <<sphere.getCenter()<<std::endl;
    std::cout<<"Radius of the sphere : " <<sphere.getRadius()<<std::endl;

    //Cylinder extension

    extend (cylinder, box);
    cylinder.getBounds(min,max);
    std::cout<< "min of the cylinder : " <<min<<std::endl;
    std::cout<< "max of the cylinder : " <<max<<std::endl;

    extend (cylinder, sphere);
    cylinder.getBounds(min,max);
    std::cout<< "min of the cylinder : " <<min<<std::endl;
    std::cout<< "max of the cylinder : " <<max<<std::endl;

    extend (cylinder, cylinder);
    cylinder.getBounds(min,max);
    std::cout<< "min of the cylinder : " <<min<<std::endl;
    std::cout<< "max of the cylinder : " <<max<<std::endl;


    return 0;


}
bool Line::intersect(const CylinderVolume &cyl, 
                           Real           &enter,  
                           Real           &exit ) const
{
    Real  radius = cyl.getRadius();

    Vec3r adir;
    Vec3r o_adir;
    Pnt3r apos;

    cyl.getAxis(apos, adir);

    o_adir = adir;
    adir.normalize();

    bool isect;

    Real  ln;
    Real  dl;
    Vec3r RC;
    Vec3r n;
    Vec3r D;

    RC = _pos - apos;

    n  = _dir.cross (adir);
    ln =  n  .length(    );

    if(ln == 0.f)    // IntersectionLine is parallel to CylinderAxis
    {
        D  = RC - (RC.dot(adir)) * adir;
        dl = D.length();

        if(dl <= radius)   // line lies in cylinder
        {
            enter = 0.f;
            exit  = Inf;
        }
        else
        {
            return false;
        }
    }
    else
    {
        n.normalize();

        dl    = osgAbs(RC.dot(n));        //shortest distance
        isect = (dl <= radius);

        if(isect)
        {                 // if ray hits cylinder
            Real  t;
            Real  s;
            Vec3r O;

            O = RC.cross(adir);
            t = - (O.dot(n)) / ln;
            O = n.cross(adir);

            O.normalize();

            s = osgAbs (
                (osgSqrt ((radius * radius) - (dl * dl))) / (_dir.dot(O)));

            exit = t + s;

            if(exit < 0.f)
                return false;

            enter = t - s;

            if(enter < 0.f)
                enter = 0.f;
        }
        else
        {
            return false;
        }
    }

    Real t;

    Plane bottom(-adir, apos);

    if(bottom.intersect(*this, t))
    {
        if(bottom.isInHalfSpace(_pos))
        {
            if(t > enter) 
                enter = t;
        }
        else
        {
            if(t < exit) 
                exit = t;
        }
    }
    else
    {
        if(bottom.isInHalfSpace(_pos))
            return false;
    }
    
    Plane top(adir, apos + o_adir);

    if(top.intersect(*this, t))
    {
        if(top.isInHalfSpace(_pos))
        {
            if(t > enter)
                enter = t;
        }
        else
        {
            if(t < exit)
                exit = t;
        }
    }
    else
    {
        if(top.isInHalfSpace(_pos))
            return false;
    }

    return (enter < exit);
}