⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 naturepatchmanager.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    nz = cz;
    nIdx = (nz * QUADTREE_SIZE) + nx;

    if (nx > EDGE_LENGTH)
    {
	nIdx -= EDGE_LENGTH;
	mEastNeighbor[node] = -mQuadNodeLookup[nIdx];
	mEastEdgeQuad[cz]   = node;
    }
    else
	mEastNeighbor[node] = mQuadNodeLookup[nIdx];

    // if not at lowest level, descend into children
    if (level < (QUADTREE_DEPTH - 1))
    {
	int w4 = EDGE_LENGTH >> (level + 2);

	// northwest child
	computeNeighborLookup(cx - w4, cz - w4, (node<<2)+1, level+1);
	// northeast child
	computeNeighborLookup(cx + w4, cz - w4, (node<<2)+2, level+1);
	// southwest child
	computeNeighborLookup(cx - w4, cz + w4, (node<<2)+3, level+1);
	// southeast child
	computeNeighborLookup(cx + w4, cz + w4, (node<<2)+4, level+1);
    }
}

//----------------------------------------------------------------------------

void NaturePatchManager::setTargetQuality(Real quality)
{
    mTargetQuality = quality;

    for (int i = 0; i < 324; i++)
    {
	if (mPatches[i] != 0)
	    addToRenderQueue(mPatches[i]);
    }
}

//----------------------------------------------------------------------------

void NaturePatchManager::setMinimumQuality(Real quality)
{
    mMinimumQuality = quality;

    for (int i = 0; i < 324; i++)
    {
  	if (mPatches[i] != 0)
	    addToRenderQueue(mPatches[i]);
    }
}

//----------------------------------------------------------------------------

void NaturePatchManager::renderPatches()
{
    queue<NaturePatch *> regenQueue;
    bool empty = mRenderQueue.empty();

    while (!mRenderQueue.empty())
    {
	NaturePatch *patch = mRenderQueue.front();
	mRenderQueue.pop();

	// rebuild mesh
	patch->mNeedRendering = false;
	patch->prepareMesh();

/*	if (patch->mNorthNeighbor != 0) patch->mNorthNeighbor->prepareMesh();
	if (patch->mSouthNeighbor != 0) patch->mSouthNeighbor->prepareMesh();
	if (patch->mWestNeighbor  != 0) patch->mWestNeighbor->prepareMesh();
	if (patch->mEastNeighbor  != 0) patch->mEastNeighbor->prepareMesh();
*/
	if (patch->mNorthNeighbor != 0) patch->mNorthNeighbor->mNeedRendering = true;
	if (patch->mSouthNeighbor != 0) patch->mSouthNeighbor->mNeedRendering = true;
	if (patch->mWestNeighbor  != 0) patch->mWestNeighbor->mNeedRendering = true;
	if (patch->mEastNeighbor  != 0) patch->mEastNeighbor->mNeedRendering = true;

	// add to regen queue
	regenQueue.push(patch);
    }

    while (!regenQueue.empty())
    {
	NaturePatch *patch = regenQueue.front();
	regenQueue.pop();

	// regenerate the mesh
	patch->generateMesh();

	// regenerate neighbors (to keep edges up to date)
	if (patch->mNorthNeighbor != 0) patch->mNorthNeighbor->generateMesh();
	if (patch->mSouthNeighbor != 0) patch->mSouthNeighbor->generateMesh();
	if (patch->mWestNeighbor  != 0) patch->mWestNeighbor->generateMesh();
	if (patch->mEastNeighbor  != 0) patch->mEastNeighbor->generateMesh();
    }
}

//----------------------------------------------------------------------------

void NaturePatchManager::addToRenderQueue(NaturePatch *patch)
{
    mRenderQueue.push(patch);
}

//----------------------------------------------------------------------------

bool NaturePatchManager::loadPatch(int x, int y, int edge)
{
    bool loaded = false;

    // calculate index into patch array
    int ax = (x < 0) ? ((x % mPageSize) + mPageSize) : (x % mPageSize);
    int ay = (y < 0) ? ((y % mPageSize) + mPageSize) : (y % mPageSize);

    int idx = ay * mPageSize + ax;

    if (mPatches[idx] == 0)
    {
        NaturePatch::NaturePatchData *data;
        Vector3 world, zone, scale;

        // request data for this patch from the loader
        data = mMapLoader->requestData(x, y, &world, &zone, &scale);

        if (data != 0)
        {
            switch (data->type)
            {
            case NaturePatch::TYPE_TERRAIN:
                mPatches[idx] = new NatureTerrainPatch();
                break;
	    
            // INFO: ADD MORE PATCH TYPES HERE

            default:
                std::cout << "ERROR: Unsupported patch type!!!\n";
            }

	    if (mPatches[idx] != 0)
	    {
		mPatches[idx]->initialise(world, zone, scale, data);

		addToRenderQueue(mPatches[idx]);

		String name = "NaturePatch["+toString(x)+","+toString(y)+"]";
		SceneNode *sn = mSceneRoot->createChildSceneNode(name);
		sn->attachObject(mPatches[idx]);

//		std::cout << "ADDING: " << name << std::endl;

		// setup neighbor pointers
	    NaturePatch *n = 0, *s = 0, *w = 0, *e = 0;
		int maxIdx = mPageSize * mPageSize;

	        if ((edge & 0x01) == 0)
		{
		    // link north neighbor
		    if (idx >= mPageSize) n = mPatches[idx - mPageSize];
		    else n = mPatches[maxIdx + (idx - mPageSize)];
		}

		if ((edge & 0x02) == 0)
		{
		    // link south neighbor
		    if (idx < (maxIdx - mPageSize)) s = mPatches[idx + mPageSize];
		    else s = mPatches[(idx + mPageSize) - maxIdx];
		}

		if ((edge & 0x04) == 0)
		{
		    // link west neighbor
		    if ((idx % mPageSize) > 0) w = mPatches[idx - 1];
		    else w = mPatches[idx + (mPageSize - 1)];
		}

		if ((edge & 0x08) == 0)
		{
		    // link east neighbor
		    if ((idx % mPageSize) < (mPageSize - 1)) e = mPatches[idx + 1];
		    else e = mPatches[idx - (mPageSize - 1)];
		}

		// attach patch to its neighbors
		mPatches[idx]->attach(n, s, w, e);
	    
		loaded = true;
	    }
	}
    }

    return loaded;
}

//----------------------------------------------------------------------------

void NaturePatchManager::unloadPatch(int x, int y)
{
    // calculate index into patch array
    int ax = (x < 0) ? ((x % mPageSize) + mPageSize) : (x % mPageSize);
    int ay = (y < 0) ? ((y % mPageSize) + mPageSize) : (y % mPageSize);

    int idx = ay * mPageSize + ax;

//    std::cout << "UNLOADING: " << ax << ", " << x << "  idx: " << idx << std::endl;

    if (mPatches[idx] != 0)
    {
	// unlink neighbors
	mPatches[idx]->detach();

	// remove patch from the scene
	String name = "NaturePatch[" + toString(x) + "," + toString(y) + "]";
	mSceneRoot->removeAndDestroyChild(name);

//	std::cout << "REMOVING: " << name << std::endl;

	// inform the patchloader that we no longer need this data
	mMapLoader->releaseData(mPatches[idx]->mData);

	// delete patch
	delete mPatches[idx];
	mPatches[idx] = 0;
    }
}

//----------------------------------------------------------------------------

void NaturePatchManager::updatePatches(Camera *cam)
{
    int cx, cy;
    mMapLoader->getPatchAtPosition(cam->getPosition(), &cx, &cy);


    int diffx = cx - mCenterPatchX;
    int diffy = cy - mCenterPatchY;
    int ps2 = mPageSize / 2, x, y;

    // load in new patches
    for (y = -ps2; y <= ps2; y++)
    {
	for (x = -ps2; x <= ps2; x++)
	{
	    int edge = 0;

	    if (y == -ps2)     edge |= 0x01;
	    else if (y == ps2) edge |= 0x02;
	    if (x == -ps2)     edge |= 0x04;
	    else if (x == ps2) edge |= 0x08;

	    // TODO: move patch loading to separate thread?
	    if (loadPatch(x + mCenterPatchX, y + mCenterPatchY, edge))
		return;
	}
    }

    if (diffy != 0 || diffx != 0)
    {
	// unload patches on x axis
	if (diffy > 0)
	{
	    if (diffy > mPageSize) diffy = mPageSize;

	    for (y = -ps2; y < (-ps2 + diffy); y++)
		for (x = -ps2; x <= ps2; x++)
		    unloadPatch(x + mCenterPatchX, y + mCenterPatchY);
	}
	else if (diffy < 0)
	{
	    if (diffy < -mPageSize) diffy = -mPageSize;
	    
	    for (y = ps2; y > (ps2 + diffy); y--)
		for (x = -ps2; x <= ps2; x++)
		    unloadPatch(x + mCenterPatchX, y + mCenterPatchY);
	}

	// unload patches on y axis
	if (diffx > 0)
	{
	    if (diffx > mPageSize) diffx = mPageSize;
	    
	    for (x = -ps2; x < -ps2 + diffx; x++)
		for (y = -ps2; y <= ps2; y++)
		    unloadPatch(x + mCenterPatchX, y + mCenterPatchY);
	}
	else if (diffx < 0)
	{
	    if (diffx < -mPageSize) diffx = -mPageSize;
	    
	    for (x = ps2; x > (ps2 + diffx); x--)
		for (y = -ps2; y <= ps2; y++)
		    unloadPatch(x + mCenterPatchX, y + mCenterPatchY);
	}

	// update center position
	mCenterPatchX = cx;
	mCenterPatchY = cy;
    }
}

NaturePatch* NaturePatchManager::getPatchAtPosition(const Vector3& pos)
{
    // NB only works if loaded
    // Get location
    int x, y;
    mMapLoader->getPatchAtPosition(pos, &x, &y);

    int idx = y * mPageSize + x;

    return mPatches[idx];

}

void NaturePatchManager::getPatchRenderOpsInBox(const AxisAlignedBox& box, std::list<RenderOperation>& opList)
{
    // Get the patches at the 4 corners at the bottom of the box, ie 0, 3, 6, 7
    std::set<NaturePatch*> uniqueSet;

    const Vector3* corners = box.getAllCorners();

    uniqueSet.insert(getPatchAtPosition(corners[0]));
    uniqueSet.insert(getPatchAtPosition(corners[3]));
    uniqueSet.insert(getPatchAtPosition(corners[6]));
    uniqueSet.insert(getPatchAtPosition(corners[7]));

    // Iterate over uniques
    std::set<NaturePatch*>::iterator i, iend;
	RenderOperation op;
    for (i = uniqueSet.begin(); i != iend; ++i)
    {
		(*i)->getRenderOperation(op);
        opList.push_back(op);
    }


}


} // namespace Ogre

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -