Ejemplo n.º 1
0
//----------------------------------------------------------------------------
BspNode* BspNodes::CreateNode (const Vector2f& v0, const Vector2f& v1,
                               VertexColor3Effect* effect, const Float3& color)
{
	// Create the model-space separating plane.
	Vector2f dir = v1 - v0;
	AVector normal(dir[1], -dir[0], 0.0f);
	normal.Normalize();
	float constant = normal[0]*v0[0] + normal[1]*v0[1];
	HPlane modelPlane(normal, constant);

	// Create the BSP node.
	BspNode* bsp = new0 BspNode(modelPlane);

	VertexFormat* vformat = VertexFormat::Create(2,
	                        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
	                        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);

	// Create the rectangle representation of the model plane and set the
	// vertex colors to the specified color.
	float xExtent = 0.5f*dir.Length();
	float yExtent = 0.125f;
	TriMesh* rect = StandardMesh(vformat).Rectangle(2, 2, xExtent, yExtent);
	VertexBufferAccessor vba(rect);
	for (int i = 0; i < 4; ++i)
	{
		vba.Color<Float3>(0, i) = color;
	}
	rect->SetEffectInstance(effect->CreateInstance());

	// Set the position and orientation for the world-space plane.
	APoint trn(0.5f*(v0[0] + v1[0]), 0.5f*(v0[1] + v1[1]), yExtent + 0.001f);
	HMatrix zRotate(AVector::UNIT_Z, Mathf::ATan2(dir.Y(),dir.X()));
	HMatrix xRotate(AVector::UNIT_X, Mathf::HALF_PI);
	HMatrix rotate = zRotate*xRotate;
	rect->LocalTransform.SetTranslate(trn);
	rect->LocalTransform.SetRotate(rotate);

	bsp->AttachCoplanarChild(rect);
	return bsp;
}
Ejemplo n.º 2
0
//----------------------------------------------------------------------------
Spatial* BspNode::GetContainingNode (const APoint& point)
{
    SpatialPtr posChild = GetPositiveChild();
    SpatialPtr negChild = GetNegativeChild();

    if (posChild || negChild)
    {
        BspNode* bspChild;

        if (mWorldPlane.WhichSide(point) < 0)
        {
            bspChild = DynamicCast<BspNode>(negChild);
            if (bspChild)
            {
                return bspChild->GetContainingNode(point);
            }
            else
            {
                return negChild;
            }
        }
        else
        {
            bspChild = DynamicCast<BspNode>(posChild);
            if (bspChild)
            {
                return bspChild->GetContainingNode(point);
            }
            else
            {
                return posChild;
            }
        }
    }

    return this;
}
Ejemplo n.º 3
0
Spatial* BspNode::GetContainingNode(Vector4<float> const& point)
{
    std::shared_ptr<Spatial> posChild = GetPositiveChild();
    std::shared_ptr<Spatial> negChild = GetNegativeChild();

    if (posChild || negChild)
    {
        BspNode* bspChild;

        if (WhichSide(point) < 0)
        {
            bspChild = dynamic_cast<BspNode*>(negChild.get());
            if (bspChild)
            {
                return bspChild->GetContainingNode(point);
            }
            else
            {
                return negChild.get();
            }
        }
        else
        {
            bspChild = dynamic_cast<BspNode*>(posChild.get());
            if (bspChild)
            {
                return bspChild->GetContainingNode(point);
            }
            else
            {
                return posChild.get();
            }
        }
    }

    return this;
}
    void BspIntersectionSceneQuery::execute(IntersectionSceneQueryListener* listener)
    {
        /*
        Go through each leaf node in BspLevel and check movables against each other and world
        Issue: some movable-movable intersections could be reported twice if 2 movables
        overlap 2 leaves?
        */
        const BspLevelPtr& lvl = ((BspSceneManager*)mParentSceneMgr)->getLevel();
		if (lvl.isNull()) return;

        BspNode* leaf = lvl->getLeafStart();
        int numLeaves = lvl->getNumLeaves();
        
        while (numLeaves--)
        {
            const BspNode::IntersectingObjectSet& objects = leaf->getObjects();
            int numObjects = (int)objects.size();

            BspNode::IntersectingObjectSet::const_iterator a, b, theEnd;
            theEnd = objects.end();
            a = objects.begin();
            for (int oi = 0; oi < numObjects; ++oi, ++a)
            {
                const MovableObject* aObj = *a;
                // Skip this object if collision not enabled
                if (!(aObj->getQueryFlags() & mQueryMask) ||
					!(aObj->getTypeFlags() & mQueryTypeMask) ||
					!aObj->isInScene())
                    continue;

                if (oi < (numObjects-1))
                {
                    // Check object against others in this node
                    b = a;
                    for (++b; b != theEnd; ++b)
                    {
                        const MovableObject* bObj = *b;
                        // Apply mask to b (both must pass)
                        if ((bObj->getQueryFlags() & mQueryMask) && 
							(bObj->getTypeFlags() & mQueryTypeMask) && 
							bObj->isInScene())
                        {
                            const AxisAlignedBox& box1 = aObj->getWorldBoundingBox();
                            const AxisAlignedBox& box2 = bObj->getWorldBoundingBox();

                            if (box1.intersects(box2))
                            {
                                if (!listener->queryResult(const_cast<MovableObject*>(aObj), 
                                    const_cast<MovableObject*>(bObj)))
									return; 
                            }
                        }
                    }
                }
                // Check object against brushes
                if (mQueryTypeMask & SceneManager::WORLD_GEOMETRY_TYPE_MASK)
                {
                    const BspNode::NodeBrushList& brushes = leaf->getSolidBrushes();
                    BspNode::NodeBrushList::const_iterator bi, biend;
                    biend = brushes.end();
                    Real radius = aObj->getBoundingRadius();
                    const Vector3& pos = aObj->getParentNode()->_getDerivedPosition();

                    for (bi = brushes.begin(); bi != biend; ++bi)
                    {
						list<Plane>::type::const_iterator planeit, planeitend;
                        planeitend = (*bi)->planes.end();
                        bool brushIntersect = true; // Assume intersecting for now

                        for (planeit = (*bi)->planes.begin(); planeit != planeitend; ++planeit)
                        {
                            Real dist = planeit->getDistance(pos);
                            if (dist > radius)
                            {
                                // Definitely excluded
                                brushIntersect = false;
                                break;
                            }
                        }
                        if (brushIntersect)
                        {
                            // report this brush as it's WorldFragment
                            assert((*bi)->fragment.fragmentType == SceneQuery::WFT_PLANE_BOUNDED_REGION);
                            if (!listener->queryResult(const_cast<MovableObject*>(aObj), 
                                    const_cast<WorldFragment*>(&((*bi)->fragment))))
								return; 
                        }

                    }
                }


            }

            ++leaf;
        }



    }
    //-----------------------------------------------------------------------
    //-----------------------------------------------------------------------
    //-----------------------------------------------------------------------
    BspNode* BspSceneManager::walkTree(Camera* camera, 
		VisibleObjectsBoundsInfo *visibleBounds, bool onlyShadowCasters)
    {
		if (mLevel.isNull()) return 0;

        // Locate the leaf node where the camera is located
        BspNode* cameraNode = mLevel->findLeaf(camera->getDerivedPosition());

        mMatFaceGroupMap.clear();
        mFaceGroupSet.clear();

        // Scan through all the other leaf nodes looking for visibles
        int i = mLevel->mNumNodes - mLevel->mLeafStart;
        BspNode* nd = mLevel->mRootNode + mLevel->mLeafStart;

        /*
        if (firstTime)
        {
            camera->getViewMatrix(); // Force update view before report
            of.open("BspSceneManager.log");
            of << *camera << std::endl;
            of << "Camera Node: " << *cameraNode << std::endl;
            of << "Vertex Data: " << std::endl;
            for (int testi = 0; testi < mLevel->mNumVertices; ++testi)
            {
                of << " " << testi << ": pos(" <<
                  mLevel->mVertices[testi].position[0] << ", " <<
                    mLevel->mVertices[testi].position[1] << ", " << mLevel->mVertices[testi].position[2] << ")" <<
                    " uv(" << mLevel->mVertices[testi].texcoords[0] << ", " << mLevel->mVertices[testi].texcoords[1] << ")" <<
                    " lm(" << mLevel->mVertices[testi].lightmap[0] << ", " << mLevel->mVertices[testi].lightmap[1] << ")" << std::endl;
            }
            of << "Element data:" << std::endl;
            for (testi = 0; testi < mLevel->mNumElements; ++testi)
            {
                of << " " << testi << ": " << mLevel->mElements[testi] << std::endl;

            }
        }
        */

        while (i--)
        {
            if (mLevel->isLeafVisible(cameraNode, nd))
            {

                // Visible according to PVS, check bounding box against frustum
                FrustumPlane plane;
                if (camera->isVisible(nd->getBoundingBox(), &plane))
                {
                    //if (firstTime)
                    //{
                    //    of << "Visible Node: " << *nd << std::endl;
                    //}
                    processVisibleLeaf(nd, camera, visibleBounds, onlyShadowCasters);
                    if (mShowNodeAABs)
                        addBoundingBox(nd->getBoundingBox(), true);
                }
            }
            nd++;
        }


        // TEST
        //if (firstTime)
        //{
        //    of.close();
        //    firstTime = false;
        //}
        return cameraNode;

    }