int FrustumContainsSphere( CD3DCamera * pCamera, Sphere3f pSphere)
{
   	// various distances
	float fDistance;

    //$$$TEMP get the frustum planes from the camera's CULLINFO
    Plane3f plane[6];
    CULLINFO *cInfo = pCamera->GetCullInfo();
    for (int j=0; j<6; j++)  {
        plane[j] = Plane3f( Vector3f(cInfo->planeFrustum[j].a,  cInfo->planeFrustum[j].b,  cInfo->planeFrustum[j].c), cInfo->planeFrustum[j].d);
    }


	// calculate our distances to each of the planes
	for(int i = 0; i < 6; ++i) {

		// find the distance to this plane
		//fDistance = plane[i].GetNormal().Dot(pSphere.Center()) + plane[i].GetNormal().Length();
        //fDistance = plane[i].GetNormal().Dot(pSphere.Center()) + plane[i].DistanceTo(pSphere.Center());
        fDistance = plane[i].GetNormal().Dot(pSphere.Center()) + plane[i][3];

		// if this distance is < -sphere.radius, we are outside
		if(fDistance < -pSphere.Radius())
			return(OUTSIDE);

		// else if the distance is between +- radius, then we intersect
		if((float)fabs(fDistance) < pSphere.Radius())
			return(INTERSECT);
	}

	// otherwise we are fully in view
    return (INSIDE);
}
Example #2
0
      void FrustumCamera::zoom( const Sphere3f &sphere, float fovy, bool adjustClipPlanes )
      {
        DP_ASSERT( isPositive(sphere) );

        //  with some simple trigonometry, we get some factors for the distance and the window size:
        //  alpha = fovy / 2
        //  dist from camera position to center = p =>
        //    sin( alpha ) = r / ( p * r ) = 1 / p
        //  => p = 1 / sin( alpha )
        //  window size is 2 * q * r =>
        //    tan( alpha ) = ( q * r ) / ( p * r ) = q / p = q * sin( alpha )
        //  => q = tan( alpha ) / sin( alpha ) = 1 / cos( alpha )

        float aspectRatio = getAspectRatio();

        if ( fovy < 0.0f )
        {
          //  with negative fovy we keep the current
 
          // consider the aspect ratio with default fovy calculation
          float windowSize = (aspectRatio <= 1.0) ? getWindowSize()[0] : getWindowSize()[1];
          fovy = (float)( 2.0 * atan( windowSize / ( 2.0 * getFocusDistance() ) ) );
        }

        float alpha = fovy / 2.0f;
        float p = (float)( 1.0f / sinf( alpha ) );
        float q = (float)( 1.0f / cosf( alpha ) );

        // from the center go p*radius steps along the direction as the new position
        setPosition( sphere.getCenter() - p * sphere.getRadius() * getDirection() );

        float radius = sphere.getRadius();
        setFocusDistance( p * radius );

        float size = q * 2.0f * radius;
        if ( aspectRatio <= 1.0f )
        {
          //  the window is higher than wide, so fit to the width and keep the aspect ratio
          setWindowSize( Vec2f( size, size / aspectRatio ) );
        }
        else
        {
          //  the window is wider than high, so fit to the height and keep the aspect ratio
          setWindowSize( Vec2f( size / aspectRatio, size ) );
        }

        // note: don't touch near/far distance if AutoClipPlanes is off
        if ( adjustClipPlanes )
        { 
          //  adjust the near and far distances to best fit
          m_nearDist = ( p - 1.0f ) * radius;
          m_farDist  = ( p + 1.0f ) * radius;

          notify( PropertyEvent( this, PID_NearDistance ) );
          notify( PropertyEvent( this, PID_FarDistance ) );
        }
      }
Example #3
0
      void  generateTexCoordsPlane( VertexAttributeSetSharedPtr const& vas, const Sphere3f &sphere, unsigned int tu )
      {
        Buffer::ConstIterator<Vec3f>::Type vertices = vas->getVertices();

        // get the bounding box of vas and determine the axes u,v to use to texture along
        unsigned int u, v, w;
        getSortedAxes( vertices, vas->getNumberOfVertices(), u, v, w );

        // create the texture coordinates
        std::vector<Vec2f> texCoords( vas->getNumberOfVertices() );
        Vec2f tp;
        float oneOverTwoR = 0.5f / sphere.getRadius();
        Vec2f tpMin( 1.0f, 1.0f );
        Vec2f tpMax( 0.0f, 0.0f );
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          Vec3f p = vertices[i] - sphere.getCenter();
          tp[0] = p[u] * oneOverTwoR + 0.5f;  // 0.0 <= tp[0] <= 1.0
          if ( tp[0] < tpMin[0] )
          {
            tpMin[0] = tp[0];
          }
          else if ( tp[0] > tpMax[0] )
          {
            tpMax[0] = tp[0];
          }

          tp[1] = p[v] * oneOverTwoR + 0.5f;   //  0.0 <= tp[1] <= 1.0
          if ( tp[1] < tpMin[1] )
          {
            tpMin[1] = tp[1];
          }
          else if ( tp[1] > tpMax[1] )
          {
            tpMax[1] = tp[1];
          }

          texCoords[i] = tp;
        }

        // scale the texcoords to [0..1]
        DP_ASSERT( ( FLT_EPSILON < ( tpMax[0] - tpMin[0] ) ) && ( FLT_EPSILON < ( tpMax[1] - tpMin[1] ) ) );
        Vec2f tpScale( 1.0f / ( tpMax[0] - tpMin[0] ), 1.0f / ( tpMax[1] - tpMin[1] ) );
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          texCoords[i] = Vec2f( ( texCoords[i][0] - tpMin[0] ) * tpScale[0],
                                ( texCoords[i][1] - tpMin[1] ) * tpScale[1] );
        }

        vas->setTexCoords( tu, &texCoords[0], vas->getNumberOfVertices() );
      }
Example #4
0
      void  generateTexCoordsCylinder( VertexAttributeSetSharedPtr const& vas, const Sphere3f &sphere, unsigned int tu )
      {
        Buffer::ConstIterator<Vec3f>::Type vertices = vas->getVertices();

        // get the bounding box of vas and determine the axes u,v to use to texture along
        unsigned int u, v, w;
        getSortedAxes( vertices, vas->getNumberOfVertices(), u, v, w );

        // create the texture coordinates
        std::vector<Vec2f> texCoords( vas->getNumberOfVertices() );
        Vec2f tp;
        float oneOverTwoR = 0.5f / sphere.getRadius();
        float tpuMin = 1.0f;
        float tpuMax = 0.0f;
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          Vec3f p = vertices[i] - sphere.getCenter();

          // largest axis as the cylinder axis
          tp[0] = p[u] * oneOverTwoR + 0.5f;   //  0.0 <= tp[1] <= 1.0
          if ( tp[0] < tpuMin )
          {
            tpuMin = tp[0];
          }
          else if ( tpuMax < tp[0] )
          {
            tpuMax = tp[0];
          }

          if ( FLT_EPSILON < fabsf( p[v] ) )
          {
            tp[1] = 0.5f * atan2f( p[w], -p[v] ) / (float) PI + 0.5f;
          }
          else
          {
            tp[1] = (float)( ( 0.0f <= p[w] ) ? 0.75f : 0.25f );
          }

          texCoords[i] = tp;
        }

        // scale the texcoords to [0..1]
        DP_ASSERT( FLT_EPSILON < ( tpuMax - tpuMin ) );
        float tpuScale = 1.0f / ( tpuMax - tpuMin );
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          texCoords[i][0] = ( texCoords[i][0] - tpuMin ) * tpuScale;
        }
        vas->setTexCoords( tu, &texCoords[0], vas->getNumberOfVertices() );
      }
Example #5
0
      void generateTexCoordsSphere( VertexAttributeSetSharedPtr const& vas, const Sphere3f &sphere, unsigned int tu )
      {
        Buffer::ConstIterator<Vec3f>::Type vertices = vas->getVertices();
        std::vector<Vec2f> texCoords( vas->getNumberOfVertices() );
        Vec2f tp;

        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          Vec3f p = vertices[i] - sphere.getCenter();
          if ( fabsf( p[1] ) > FLT_EPSILON )
          {
            tp[0] = 0.5f * atan2f( p[0], -p[1] ) / (float) PI + 0.5f;
          }
          else
          {
            tp[0] = (float)( ( p[0] >= 0.0f ) ? 0.75f : 0.25f );
          }

          float d = sqrtf( square( p[0] ) + square( p[1] ) );
          if ( d > FLT_EPSILON )
          {
            tp[1] = atan2f( p[2], d ) / (float) PI + 0.5f;
          }
          else
          {
            tp[1] = (float)( ( p[2] >= 0.0f ) ? 1.0f : 0.0f );
          }

          texCoords[i] = tp;
        }

        vas->setTexCoords( tu, &texCoords[0], vas->getNumberOfVertices() );
      }
Example #6
0
Ego::Math::Relation sphere_intersects_sphere(const Sphere3f& lhs, const Sphere3f& rhs)
{
	Ego::Math::Relation retval = Ego::Math::Relation::error;

    // Get the separating axis
    Vector3f vdiff = lhs.getCenter() - rhs.getCenter();

    // Get the distance squared.
    float dist2 = vdiff.length_2();

    if (rhs.getRadius() < lhs.getRadius())
    {
        if (dist2 < lhs.getRadius() * lhs.getRadius())
        {
			retval = Ego::Math::Relation::inside;
        }
    }

	if (Ego::Math::Relation::inside != retval)
    {
        // Get the sum of the radii.
        float fRadiiSum = lhs.getRadius() + rhs.getRadius();

        // If the distance between the centers is less than the sum of the radii,
        // then we have an intersection we calculate lhs using the squared lengths for speed.
        if (dist2 < fRadiiSum * fRadiiSum)
        {
			retval = Ego::Math::Relation::intersect;
        }
        else
        {
			retval = Ego::Math::Relation::outside;
        }
    }

    return retval;
}
Example #7
0
      CullCode PerspectiveCamera::determineCullCode( const Sphere3f &sphere ) const
      {
        //  For each of the six frustum planes determine the signed distance of the center to the plane.
        //  Take the plane equation n*x + d = 0, with n the plane normal, x a point on the plane, and d
        //  the negative distance of the plane to the origin.
        //  With p an arbitrary point, we get n*p + d = c, with c the signed distance of p from the plane.
        //  c > 0   <=> p is 'above' the plane (the normal points from the plane to the point)
        //  c < 0   <=> p is 'below' the plane (the normal points from the point to the plane)
        //  Determine for each of the six frustum planes a plane equation with the normal pointing
        //  inward, meaning positive values of c are in, negative are out.
        //  Taking as the arbitrary point p the center of the bounding sphere, we get the following
        //  results (with r the radius of the bounding sphere):
        //  c + r < 0   <=> center is more than radius below the plane  <=> bounding sphere is completely outside
        //  c - r > 0   <=> center is more than radius above the plane  <=> bounding sphere is completely inside
        //  otherwise   <=> bounding sphere intersects the frustum at this plane.
        //  If the bounding sphere is completely outside relative to at least one plane, it is out.
        //  If the bounding sphere is completely inside relative to all planes, it is in.
        //  Otherwise it is partial.

        const Box2f & region = getWindowRegion();
        //  Determine the (signed) distances of the left and right window border from the target point.
        float hl = getWindowOffset()[0] + getWindowSize()[0] * ( region.getLower()[0] - 0.5f );
        float hr = getWindowOffset()[0] + getWindowSize()[0] * ( region.getUpper()[0] - 0.5f );
        //  Determine the (signed) distances of the bottom and top window border from the target point.
        float hb = getWindowOffset()[1] + getWindowSize()[1] * ( region.getLower()[1] - 0.5f );
        float ht = getWindowOffset()[1] + getWindowSize()[1] * ( region.getUpper()[1] - 0.5f );

        //  Each of the four side planes are determined by two of the window vertices and the origin
        //  (apex of the frustum. The normals of the right and left side are in the x-z-plane; the
        //  normals of the top and bottom side are in the y-z-plane.
        //  With t the target distance, sx the window size in x, we get d = sqrt( t*t + 0.25*sx*sx ),
        //  the distance from the camera to the right border of the window. With alpha horizontal
        //  field of view, we get sinAlpha = 0.5 * sx / d, cosAlpha = t / d.
        //  We also have to take the window offset and window region into account (e.g. in a cluster). 

        //  front plane: n = 0,0,-1, p = 0,0,-near => n*p + d = near + d = 0 => d = -near
        //    => cf = n * c + d = -center.z - near
        //  back plane : n = 0,0,+1, p = 0,0,-far  => n*p + d = -far + d = 0 => d = far
        //    => cb = n * c + d =  center.z + far

        //  Determine the distances from the camera to those points.
        float tSquare = square( getFocusDistance() );
        float dl = sqrt( tSquare + square( hl ) );
        float dr = sqrt( tSquare + square( hr ) );

        //  Determine sine and cosine of the vector from the camera along the border of the frustum.
        float sal = hl / dl;
        float cal = getFocusDistance() / dl;
        float sar = hr / dr;
        float car = getFocusDistance() / dr;

        //  Now the vectors from the camera to the left and right borders are
        //  vl = [sal,0,-cal]    => nl = [cal,0,sal]
        //  vr = [sar,0,-car]    => nr = [-car,0,-sar]
        //  left plane: nl = [-cal,0,sal], p = 0,0,0 => n*p + d = 0 + d = 0 => d = 0
        //    => cl = nl * c + d = cal * center.x + sal * center.z
        //  right plane: nr = [-car,0,-sar], p = 0,0,0 => n*p + d = 0 + d = 0 => d = 0
        //    => cr = nr * c + d = -car * center.x - sar * center.z
        float cl =   cal * sphere.getCenter()[0] + sal * sphere.getCenter()[2];
        float cr = - car * sphere.getCenter()[0] - sar * sphere.getCenter()[2];

        //  Determine the distances from the camera to those points.
        float db = sqrt( tSquare + square( hb ) );
        float dt = sqrt( tSquare + square( ht ) );

        //  Determine sine and cosine of the vector from the camera along the border of the frustum.
        float sab = hb / db;
        float cab = getFocusDistance() / db;
        float sat = ht / dt;
        float cat = getFocusDistance() / dt;

        //  Now the vectors from the camera to the bottom and top borders are
        //  vb = [0,sab,-cab]    => nb = [0,cab,sab]
        //  vt = [0,sat,-cat]    => nt = [0,-cat,-sat]
        //  bottom plane: nb = [0,cab,sab], ... => d = 0
        //    => cb = nb * c + d = cab * center.y + sab * center.z
        //  top plane: nt = [0,-cat,-sat], ... => d = 0
        //    => ct = nt * c + d = -cat * center.y - sat * center.z
        float cb =   cab * sphere.getCenter()[1] + sab * sphere.getCenter()[2];
        float ct = - cat * sphere.getCenter()[1] - sat * sphere.getCenter()[2];

        CullCode  cc;
        if (    ( - sphere.getCenter()[2] - getNearDistance() + sphere.getRadius() < 0.0f )
            ||  (   sphere.getCenter()[2] + getFarDistance()  + sphere.getRadius() < 0.0f )
            ||  ( cl + sphere.getRadius() < 0.0f ) || ( cr + sphere.getRadius() < 0.0f )
            ||  ( cb + sphere.getRadius() < 0.0f ) || ( ct + sphere.getRadius() < 0.0f ) )
        {
          cc = CC_OUT;
        }
        else if (     ( 0.0f < - sphere.getCenter()[2] - getNearDistance() - sphere.getRadius() )
                  &&  ( 0.0f <   sphere.getCenter()[2] + getFarDistance()  - sphere.getRadius() )
                  &&  ( 0.0f < cl - sphere.getRadius() ) && ( 0.0f < cr - sphere.getRadius() )
                  &&  ( 0.0f < cb - sphere.getRadius() ) && ( 0.0f < ct - sphere.getRadius() ) )
        {
          cc = CC_IN;
        }
        else
        {
          cc = CC_PART;
        }

        return( cc );
      }