Esempio n. 1
0
void QuadNode::generateLists() {

    if(items.size() > 0) {
        if(!listid) listid = glGenLists(1);

        glNewList(listid, GL_COMPILE);

        for(std::list<QuadItem*>::iterator it = items.begin(); it != items.end(); it++) {
            QuadItem* oi = (*it);
            oi->drawQuadItem();
        }

        glEndList();
        return;
    }

    if(children.size() > 0) {
        for(int i=0;i<4;i++) {
            QuadNode* c = children[i];
            if(!c->empty()) {
                c->generateLists();
            }
        }
    }
}
Esempio n. 2
0
void QuadNode::outline() {
    bounds.draw();

    if(children.size()==0) return;

    for(int i=0;i<4;i++) {
        QuadNode* c = children[i];
        if(c!=0) {
            c->outline();
        }
    }
}
Esempio n. 3
0
void QuadNode::release()
{
	for (int i = eQuadNode_LeftBottom; i != eQuadNode_Size; ++i)
	{
		QuadNode* c = children_[i];
		if (c)
		{
			c->release();
		}
	}
	releaseImp_();
}
Esempio n. 4
0
 bool isChildOf(const QuadNode& node) const
 {
     if (level() < node.level())
     {
         for (size_t i = totalLevels - 1; i >= node.level(); --i)
         {
             if (nodeCode.x[i] != node.locationCode().x[i] ||
                 nodeCode.y[i] != node.locationCode().y[i])
             {
                 return false;
             }
         }
         return true;
     }
     return false;
 }
void QuadNode::outlineItems() {
    if(items.empty() && children.empty()) return;

    for(std::list<QuadItem*>::iterator it = items.begin(); it != items.end(); it++) {
        QuadItem* oi = (*it);
        oi->quadItemBounds.draw();
    }

    if(children.empty()) return;

    for(int i=0;i<4;i++) {
        QuadNode* c = children[i];
        if(c!=0) {
            c->outlineItems();
        }
    }
}
void QuadNode::outline() {
    //bounds.draw();

    if(!items.empty()) {
        bounds.draw();
        /*glBegin(GL_LINES);
            glVertex2fv(bounds.min);
            glVertex2fv(bounds.max);
        glEnd();*/
    }

    if(children.empty()) return;

    for(int i=0;i<4;i++) {
        QuadNode* c = children[i];
        if(c!=0) {
            c->outline();
        }
    }
}
Esempio n. 7
0
int QuadNode::draw(Frustum& frustum) {

    if(listid && items.size()) {
        glPushMatrix();
            glCallList(listid);
        glPopMatrix();
        return 1;
    }

    int drawn = 0;

    if(children.size() > 0) {
        for(int i=0;i<4;i++) {
            QuadNode* c = children[i];
            if(!c->empty() && frustum.boundsInFrustum(c->bounds)) {
                drawn += c->draw(frustum);
            }
        }
    }

    return drawn;
}
Esempio n. 8
0
QuadNode<T, lev>& nextNode(QuadNode<T, lev>& node)
{
    if (node.hasChildren())
    {
        if (node.childExists(0, 0)) return node.child(0, 0);
        else if (node.childExists(0, 1)) return node.child(0, 1);
        else if (node.childExists(1, 0)) return node.child(1, 0);
        else return node.child(1, 1);
    }
    else
    {
        QuadNode<T, lev>* refNode = &node;

        // initial prepare for the first check of parent node
        bool x = refNode->locationCode().x[refNode->level()];
        bool y = refNode->locationCode().y[refNode->level()];
        while (*refNode != refNode->parent())
        {
            refNode = &(refNode->parent());
            // evaluate node number in node->parent() child list and check only children with
            // higher index.
            for (uint32_t i = QuadNode<T, lev>::locToInt(x, y) + 1; i < 4; ++i)
            {
                bool cx = (i & 2) >> 1;
                bool cy = i & 1;
                if (refNode->childExists(cx, cy))
                {
                    return refNode->child(cx, cy);
                }
            }

            // prepare the next (parent) node to check
            x = refNode->locationCode().x[refNode->level()];
            y = refNode->locationCode().y[refNode->level()];
        }

        // At this point refNode == refNode.parent(), so it's a header. We'll return it as
        // nextNode() of the last (rightmost) node in a tree.
        return *refNode;
    }
}
Esempio n. 9
0
QuadNode<T, lev>& previousNode(QuadNode<T, lev>& node)
{
    // If header node is given, then its previousNode is the rightmost one.
    // requirement: --end()
    if (node.parent() == node)
        return node.rightMostNode();

    QuadNode<T, lev>* refNode = &node;

    bool x = refNode->locationCode().x[refNode->level()];
    bool y = refNode->locationCode().y[refNode->level()];
    refNode = &(refNode->parent());
    for (int i = QuadNode<T, lev>::locToInt(x, y) - 1; i >= 0; --i)
    {
        bool cx = (i & 2) >> 1;
        bool cy = i & 1;
        if (refNode->childExists(cx, cy))
        {
            refNode = &(refNode->child(cx, cy));
            while (refNode->hasChildren())
            {
                if (refNode->childExists(1, 1)) refNode = &(refNode->child(1, 1));
                else if (refNode->childExists(1, 0)) refNode = &(refNode->child(1, 0));
                else if (refNode->childExists(0, 1)) refNode = &(refNode->child(0, 1));
                else refNode = &(refNode->child(0, 0));
            }
            return *refNode;
        }
    }

    // If no previous sibling has been found, this will actually return node.parent()
    // The special case is root: its previousNode is header node and previousNode(header) is
    // rightmost node. It's some kind of circular buffer and we'll let iterators handle this case to
    // avoid it (e.g by setting (--begin())::node to nullptr)
    return *refNode;
}
Esempio n. 10
0
void
PatchMap::initialize( PatchTable const & patchTable ) {

    int nfaces = 0,
        narrays = (int)patchTable.GetNumPatchArrays(),
        npatches = (int)patchTable.GetNumPatchesTotal();

    if (! narrays || ! npatches)
        return;

    // populate subpatch handles vector
    _handles.resize(npatches);

    for (int parray=0, current=0; parray<narrays; ++parray) {

        ConstPatchParamArray params = patchTable.GetPatchParams(parray);

        int ringsize = patchTable.GetPatchArrayDescriptor(parray).GetNumControlVertices();

        for (Index j=0; j < patchTable.GetNumPatches(parray); ++j) {

            Handle & h = _handles[current];

            h.arrayIndex = parray;
            h.patchIndex = current;
            h.vertIndex  = j * ringsize;

            nfaces = std::max(nfaces, (int)params[j].GetFaceId());

            ++current;
        }
    }
    ++nfaces;
    // temporary vector to hold the quadtree while under construction
    std::vector<QuadNode> quadtree;

    // reserve memory for the octree nodes (size is a worse-case approximation)
    quadtree.reserve( nfaces + npatches );

    // each coarse face has a root node associated to it that we need to initialize
    quadtree.resize(nfaces);

    // populate the quadtree from the FarPatchArrays sub-patches
    for (Index parray=0, handleIndex=0; parray<narrays; ++parray) {

        ConstPatchParamArray params = patchTable.GetPatchParams(parray);

        for (int i=0; i < patchTable.GetNumPatches(parray); ++i, ++handleIndex) {

            PatchParam const & param = params[i];

            unsigned short depth = param.GetDepth();

            QuadNode * node = &quadtree[ params[i].GetFaceId() ];

            if (depth==(param.NonQuadRoot() ? 1 : 0)) {
                // special case : regular BSpline face w/ no sub-patches
                node->SetChild( handleIndex );
                continue;
            }

            int u = param.GetU(),
                v = param.GetV(),
                pdepth = param.NonQuadRoot() ? depth-2 : depth-1,
                half = 1 << pdepth;

            for (unsigned char j=0; j<depth; ++j) {

                int delta = half >> 1;

                int quadrant = resolveQuadrant(half, u, v);
                assert(quadrant>=0);

                half = delta;

                if (j==pdepth) {
                    // we have reached the depth of the sub-patch : add a leaf
                    assert( ! node->children[quadrant].isSet );
                    node->SetChild(quadrant, handleIndex, true);
                    break;
                } else {
                    // travel down the child node of the corresponding quadrant
                    if (! node->children[quadrant].isSet) {
                        // create a new branch in the quadrant
                        node = addChild(quadtree, node, quadrant);
                    } else {
                        // travel down an existing branch
                        node = &(quadtree[ node->children[quadrant].idx ]);
                    }
                }
            }
        }
    }

    // copy the resulting quadtree to eliminate un-unused vector capacity
    _quadtree = quadtree;
}
Esempio n. 11
0
void SceneManager::Update()
{
	RenderLayerManager & renderManager = RenderLayerManager::GetRenderLayerManager();
	const PVRTVec3 center = renderManager.GetCenter();
	float occlusionRadius = renderManager.GetOcclusionRadius();


    PVRTVec4 vecA( mLookMtx->f[12], 0.0f,  mLookMtx->f[14], 1);
	PVRTVec4 vecB( GLOBAL_SCALE *  FRUSTUM_W, 0.0f,  GLOBAL_SCALE * FRUSTUM_D, 1);
	PVRTVec4 vecC( GLOBAL_SCALE * -FRUSTUM_W, 0.0f,  GLOBAL_SCALE * FRUSTUM_D, 1);
	
    vecB = *mLookMtx * vecB;
    vecC = *mLookMtx * vecC;

	PVRTVec2 A(vecA.x, vecA.z);
	PVRTVec2 B(vecB.x, vecB.z);
	PVRTVec2 C(vecC.x, vecC.z);



	mToApplyCount = 0;

	if (mQuadTree)
	{
		static QuadNode * quadNodes[256]={0}; 
		int quadNodeCount = 0;

		//mQuadTree->GetQuads(center.x, center.z, occlusionRadius, quadNodes, quadNodeCount);
		mQuadTree->GetQuadsCameraFrustum(quadNodes, quadNodeCount,  mLookMtx);
		quadNodeCount--;

		bool useFrustumCulling = true; //!!!!!!!!!!!!!!!!!!!!!

		for (int quad = quadNodeCount ; quad >=0 ; quad--)
		{
			QuadNode * pQuadNode = quadNodes[quad];

			List & dataList = pQuadNode->GetDataList();
			ListIterator listIter(dataList);
			while( Node * pRootNode = (Node*)listIter.GetPtr() )	
			{			
				if (!pRootNode->IsVisible())
					continue;

				//pRootNode->UpdateWithoutChildren();
				bool useOcclusionRadius  = pRootNode->GetUseOcclusionCulling();
				PVRTVec3 worldPos = pRootNode->GetWorldTranslation();

				if (!useFrustumCulling && useOcclusionRadius)
				{
					PVRTVec3 distVec = worldPos - center;

					if ( distVec.lenSqr() < MM(occlusionRadius) ) 
					{
						pRootNode->SetInFrustum(true);
						pRootNode->Update();
						mToApply[mToApplyCount] = pRootNode;
						mToApplyCount++;
					}
					else
					{
						pRootNode->SetInFrustum(false);
					}
				}
				else if (useFrustumCulling)
				{
					PVRTVec2 P(worldPos.x, worldPos.z);

					PVRTVec2 v0 = C - A;
					PVRTVec2 v1 = B - A;
					PVRTVec2 v2 = P - A;

					// Compute dot products
					float dot00 = v0.dot(v0);
					float dot01 = v0.dot(v1);
					float dot02 = v0.dot(v2);
					float dot11 = v1.dot(v1);
					float dot12 = v1.dot(v2);

					// Compute barycentric coordinates
					float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
					float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
					float v = (dot00 * dot12 - dot01 * dot02) * invDenom;

					bool addToList = false;
					// Check if point is in triangle
					//PVRTVec3 distVec = worldPos - center;
					//if ( distVec.lenSqr() < MM(occlusionRadius) ) 
					{
						if ( (u > 0) && (v > 0) && (u + v < 1))
						{
							addToList = true;
						}
						else if ( Collision::CircleTriangleEdgeIntersection(A,B,P, pRootNode->GetRadius() ) )
						{
							addToList = true;
						}
						else if ( Collision::CircleTriangleEdgeIntersection(A,C,P, pRootNode->GetRadius() ))
						{
							addToList = true;
						}

						if (addToList)
						{
							pRootNode->SetInFrustum(true);
							//pRootNode->Update();
							mToApply[mToApplyCount] = pRootNode;
							mToApplyCount++;
						}
                        else
                        {
                            pRootNode->SetInFrustum(false);
                        }
					}
					//else
					//{
					//	pRootNode->SetInFrustum(false);
					//}
				}
				else
				{
					pRootNode->SetInFrustum(true);
					//pRootNode->Update();
					mToApply[mToApplyCount] = pRootNode;
					mToApplyCount++;
				}

			}
		}
	}
	
	
	for (int n=0;n<mNodeCount;n++)
	{
		Node * pRootNode = mRootNodes[n];
		if (!pRootNode->IsVisible())
			continue;

		pRootNode->UpdateWithoutChildren();

		bool useOcclusionRadius  = pRootNode->GetUseOcclusionCulling();

		PVRTVec3 worldPos = pRootNode->GetWorldTranslation();
		PVRTVec3 distVec = worldPos - center;

		if (useOcclusionRadius)
		{
			if ( distVec.lenSqr() < MM(occlusionRadius) ) 
			{

				PVRTVec2 P(worldPos.x, worldPos.z);

				PVRTVec2 v0 = C - A;
				PVRTVec2 v1 = B - A;
				PVRTVec2 v2 = P - A;

				// Compute dot products
				float dot00 = v0.dot(v0);
				float dot01 = v0.dot(v1);
				float dot02 = v0.dot(v2);
				float dot11 = v1.dot(v1);
				float dot12 = v1.dot(v2);

				// Compute barycentric coordinates
				float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
				float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
				float v = (dot00 * dot12 - dot01 * dot02) * invDenom;

				bool addToList = false;
				// Check if point is in triangle
				//PVRTVec3 distVec = worldPos - center;
				//if ( distVec.lenSqr() < MM(occlusionRadius) ) 
				{
					if ( (u > 0) && (v > 0) && (u + v < 1))
					{
						addToList = true;
					}
					else if ( Collision::CircleTriangleEdgeIntersection(A,B,P, pRootNode->GetRadius() ) )
					{
						addToList = true;
					}
					else if ( Collision::CircleTriangleEdgeIntersection(A,C,P, pRootNode->GetRadius() ))
					{
						addToList = true;
					}

					if (addToList)
					{
						pRootNode->SetInFrustum(true);
						pRootNode->Update();
						mToApply[mToApplyCount] = pRootNode;
						mToApplyCount++;
					}
                    else
                    {
                        pRootNode->SetInFrustum(false);
                    }
				}
/*
				pRootNode->SetInFrustum(true);
				pRootNode->Update();
				mToApply[mToApplyCount] = pRootNode;
				mToApplyCount++;
*/
			}
			else
			{
				pRootNode->SetInFrustum(false);
			}
		}
		else
		{
			pRootNode->SetInFrustum(true);
			pRootNode->Update();
			mToApply[mToApplyCount] = pRootNode;
			mToApplyCount++;
		}

		/*

		PVRTVec3 worldPos = pRootNode->GetWorldTranslation();
		PVRTVec3 distVec = worldPos - center;

		if (!pRootNode->GetUseOcclusionCulling())
		{
		pRootNode->SetInFrustum(true);
		}
		else if ( distVec.lenSqr() < occlusionRadius ) 
		{
		pRootNode->SetInFrustum(true);		
		}
		else
		{
		pRootNode->SetInFrustum(false);
		}
		*/

	}

}