コード例 #1
0
ファイル: OgreOctreeCamera.cpp プロジェクト: Kanma/Ogre
OctreeCamera::Visibility OctreeCamera::getVisibility( const AxisAlignedBox &bound )
{

    // Null boxes always invisible
    if ( bound.isNull() )
        return NONE;

    // Get centre of the box
    Vector3 centre = bound.getCenter();
    // Get the half-size of the box
    Vector3 halfSize = bound.getHalfSize();

    bool all_inside = true;

    for ( int plane = 0; plane < 6; ++plane )
    {

        // Skip far plane if infinite view frustum
        if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
            continue;

        // This updates frustum planes and deals with cull frustum
        Plane::Side side = getFrustumPlane(plane).getSide(centre, halfSize);
        if(side == Plane::NEGATIVE_SIDE) return NONE;
        // We can't return now as the box could be later on the negative side of a plane.
        if(side == Plane::BOTH_SIDE)
                all_inside = false;
    }

    if ( all_inside )
        return FULL;
    else
        return PARTIAL;

}
コード例 #2
0
ファイル: Frustum.cpp プロジェクト: Nicussus/3dengine
//-----------------------------------------------------------------------
bool Frustum::IsVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy)
{
	// Null boxes always invisible
	if (bound.isNull()) return false;

	// Infinite boxes always visible
	if (bound.isInfinite()) return true;

	// Make any pending updates to the calculated frustum planes
	_UpdateFrustumPlanes();

	// Get centre of the box
	Vector3f centre = bound.getCenter();
	// Get the half-size of the box
	Vector3f halfSize = bound.getHalfSize();

	// For each plane, see if all points are on the negative side
	// If so, object is not visible
	for (int plane = 0; plane < 6; ++plane)
	{
		// Skip far plane if infinite view frustum
		if (plane == FRUSTUM_PLANE_FAR && m_farDist == 0)
			continue;

		Plane::Side side = m_frustumPlanes[plane].getSide(centre, halfSize);
		if (side == Plane::NEGATIVE_SIDE)
		{
			// ALL corners on negative side therefore out of view
			if (culledBy)
				*culledBy = (FrustumPlane)plane;
			return false;
		}
	}
	return true;
}
コード例 #3
0
	//-----------------------------------------------------------------------
	Plane::Side Plane::getSide (const AxisAlignedBox& box) const
	{
		if (box.isNull()) 
			return NO_SIDE;
		if (box.isInfinite())
			return BOTH_SIDE;

        return getSide(box.getCenter(), box.getHalfSize());
	}
コード例 #4
0
ファイル: OgreShadowCaster.cpp プロジェクト: yiliu1203/OGRE
    // ------------------------------------------------------------------------
    static bool isBoundOkForMcGuire(const AxisAlignedBox& lightCapBounds, const Ogre::Vector3& lightPosition)
    {
        // If light position is inside light cap bound then extrusion could be in opposite directions
        // and McGuire cap could intersect near clip plane of camera frustum without being noticed
        if(lightCapBounds.contains(lightPosition))
            return false;

        // If angular size of object is too high then extrusion could be in almost opposite directions,
        // interpolated points would be extruded by shorter distance, and strange geometry of McGuire cap
        // could be visible even for well tesselated meshes. As a heuristic we will avoid McGuire cap if
        // angular size is larger than 60 degrees - it guarantees that interpolated points would be
        // extruded by at least cos(60deg/2) ~ 86% of the original extrusion distance.
        if(lightCapBounds.getHalfSize().length() / (lightCapBounds.getCenter() - lightPosition).length() > 0.5) // if boundingSphereAngularSize > 60deg
        {
            // Calculate angular size one more time using edge corners angular distance comparision,
            // Determine lit sides of the bound, store in mask
            enum { L = 1, R = 2, B = 4, T = 8, F = 16, N = 32 }; // left, right, bottom, top, far, near
            unsigned lightSidesMask = 
                (lightPosition.x < lightCapBounds.getMinimum().x ? L : 0) | // left
                (lightPosition.x > lightCapBounds.getMaximum().x ? R : 0) | // right
                (lightPosition.y < lightCapBounds.getMinimum().y ? B : 0) | // bottom
                (lightPosition.y > lightCapBounds.getMaximum().y ? T : 0) | // top
                (lightPosition.z < lightCapBounds.getMinimum().z ? F : 0) | // far
                (lightPosition.z > lightCapBounds.getMaximum().z ? N : 0);  // near
            
            // find corners on lit/unlit edge (should not be more than 6 simultaneously, but better be safe than sorry)
            Ogre::Vector3 edgeCorners[8]; 
            unsigned edgeCornersCount = 0;
            std::pair<unsigned, AxisAlignedBox::CornerEnum> cornerMap[8] = {
                { F|L|B, AxisAlignedBox::FAR_LEFT_BOTTOM }, { F|R|B, AxisAlignedBox::FAR_RIGHT_BOTTOM },
                { F|L|T, AxisAlignedBox::FAR_LEFT_TOP },    { F|R|T, AxisAlignedBox::FAR_RIGHT_TOP },
                { N|L|B, AxisAlignedBox::NEAR_LEFT_BOTTOM },{ N|R|B, AxisAlignedBox::NEAR_RIGHT_BOTTOM },
                { N|L|T, AxisAlignedBox::NEAR_LEFT_TOP },   { N|R|T, AxisAlignedBox::NEAR_RIGHT_TOP }};
            for(auto& c : cornerMap)
                if((lightSidesMask & c.first) != 0 && (lightSidesMask & c.first) != c.first) // if adjacent sides not all lit or all unlit
                    edgeCorners[edgeCornersCount++] = lightCapBounds.getCorner(c.second);
            
            // find max angular size in range [0..pi] by finding min cos of angular size, range [1..-1]
            Real cosAngle = 1.0;
            for(unsigned i0 = 0; i0 + 1 < edgeCornersCount; ++i0)
                for(unsigned i1 = i0 + 1; i1 < edgeCornersCount; ++i1)
                {
                    // 4~6 edge corners, 6~15 angular distance calculations
                    Vector3 a = (edgeCorners[i0] - lightPosition).normalisedCopy();
                    Vector3 b = (edgeCorners[i1] - lightPosition).normalisedCopy();
                    Real cosAB = a.dotProduct(b);
                    if(cosAngle > cosAB)
                        cosAngle  = cosAB;
                }
            
            if(cosAngle < 0.5) // angularSize > 60 degrees
                return false;
        }

        return true;
    }
コード例 #5
0
	/* A 'more detailed' check for visibility of an AAB.  This function returns
	  none, partial, or full for visibility of the box.  This is useful for 
	  stuff like Octree leaf culling */
	PCZFrustum::Visibility PCZFrustum::getVisibility( const AxisAlignedBox &bound )
	{

		// Null boxes always invisible
		if ( bound.isNull() )
			return NONE;

		// Get centre of the box
		Vector3 centre = bound.getCenter();
		// Get the half-size of the box
		Vector3 halfSize = bound.getHalfSize();

		bool all_inside = true;

        // Check originplane if told to
        if (mUseOriginPlane)
        {
            Plane::Side side = mOriginPlane.getSide(centre, halfSize);
            if (side == Plane::NEGATIVE_SIDE)
            {
				return NONE;
            }
			// We can't return now as the box could be later on the negative side of another plane.
			if(side == Plane::BOTH_SIDE) 
            {
                all_inside = false;
            }
        }

        // For each active culling plane, see if the entire aabb is on the negative side
        // If so, object is not visible
        PCPlaneList::iterator pit = mActiveCullingPlanes.begin();
        while ( pit != mActiveCullingPlanes.end() )
        {
            PCPlane * plane = *pit;
            Plane::Side xside = plane->getSide(centre, halfSize);
			if(xside == Plane::NEGATIVE_SIDE) 
            {
                return NONE;
            }
			// We can't return now as the box could be later on the negative side of a plane.
			if(xside == Plane::BOTH_SIDE) 
            {
                all_inside = false;
				break;
            }
            pit++;
        }

		if ( all_inside )
			return FULL;
		else
			return PARTIAL;

	}
コード例 #6
0
    bool PCZFrustum::isVisible( const AxisAlignedBox & bound) const
    {
        // Null boxes are always invisible
        if (bound.isNull()) return false;

        // Infinite boxes are always visible
        if (bound.isInfinite()) return true;

		// Get centre of the box
        Vector3 centre = bound.getCenter();
        // Get the half-size of the box
        Vector3 halfSize = bound.getHalfSize();

        // Check originplane if told to
        if (mUseOriginPlane)
        {
            Plane::Side side = mOriginPlane.getSide(centre, halfSize);
            if (side == Plane::NEGATIVE_SIDE)
            {
				return false;
            }
        }

        // For each extra active culling plane, see if the entire aabb is on the negative side
        // If so, object is not visible
        PCPlaneList::const_iterator pit = mActiveCullingPlanes.begin();
        while ( pit != mActiveCullingPlanes.end() )
        {
            PCPlane * plane = *pit;
            Plane::Side xside = plane->getSide(centre, halfSize);
            if (xside == Plane::NEGATIVE_SIDE)
            {
				return false;
            }
            pit++;
        }
		return true;
    }
コード例 #7
0
	//-----------------------------------------------------------------------
	bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
	{
		// AABB盒子是个空盒子,不可见
		if (bound.isNull()) return false;

		// AABB盒子无限大
		if (bound.isInfinite()) return true;

		// 进行必要的更新
		updateFrustumPlanes();

		// 获取AABB盒子的中心
		Vector3 centre = bound.getCenter();
		// 获取盒子半大小向量
		Vector3 halfSize = bound.getHalfSize();

		// 遍历视锥体的每个平面,对每个平面, 见如果所有的点都在反面
		// 如果这样,对象不可见
		for (int plane = 0; plane < 6; ++plane)
		{
			// 如果视锥体无限,跳过远裁平面
			if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
				continue;

			Plane::Side side = mFrustumPlanes[plane].getSide(centre, halfSize);
			if (side == Plane::NEGATIVE_SIDE)
			{
				// 所有的角都在反面,那么在视域之外
				if (culledBy)
					*culledBy = (FrustumPlane)plane;
				return false;
			}

		}

		return true;
	}
コード例 #8
0
/** Checks how the second box intersects with the first.
*/
Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
{
    OctreeSceneManager::intersect_call++;
    // Null box?
    if (two.isNull()) return OUTSIDE;
    // Infinite box?
    if (two.isInfinite()) return INTERSECT;

    // Get centre of the box
    Vector3 centre = two.getCenter();
    // Get the half-size of the box
    Vector3 halfSize = two.getHalfSize();

    // For each plane, see if all points are on the negative side
    // If so, object is not visible.
    // If one or more are, it's partial.
    // If all aren't, full
    bool all_inside = true;
    PlaneList::const_iterator i, iend;
    iend = one.planes.end();
    for (i = one.planes.begin(); i != iend; ++i)
    {
        const Plane& plane = *i;

        Plane::Side side = plane.getSide(centre, halfSize);
        if(side == one.outside)
                return OUTSIDE;
        if(side == Plane::BOTH_SIDE)
                all_inside = false; 
    }

    if ( all_inside )
        return INSIDE;
    else
        return INTERSECT;

}