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

📄 natureterrainpatch.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	// add the quads center vertex
	v[0] = addVertex(cx, mHeight[cIdx], cz);

	// render north triangles
	neighbor = mManager->mNorthNeighbor[node];
	if ((neighbor > 0 && mQuadTree[neighbor].isEnabled()))
	{
	    // add a center vertex on the base of the north triangle,
	    // splitting it into 2 triangles
	    v[5] = addVertex(cx, mHeight[cIdx - zAdd], cz - w2);

	    // add indexes for the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[2];
	    *indexBuffer++ = v[5];

	    // add indexes for the second triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[5];
	    *indexBuffer++ = v[1];
	}
	else if (neighbor <= 0 && mNorthNeighbor != 0)
	{
	    // add the first 2 indexes of the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[2];

	    // iterate through the vertices on the neighbor edge to find which ones are enabled
	    for (int pos = cx + w2 - 2; pos > cx - w2; pos -= 2)
	    {
		// check if neighborvertex on south edge at pos is enabled
		if (mNorthNeighbor->isSouthEdgeVertexEnabled(pos))
		{
		    // add a vertex matching the vertex on the neighbor edge, close the open triangle and add the first 2 indexes of the next triangle
		    v[5] = addVertex(pos, mHeight[(cz - w2) * mData->terrain.heightMapWidth + pos], cz - w2);
		    *indexBuffer++ = v[5];
		    *indexBuffer++ = v[0];
		    *indexBuffer++ = v[5];
		}
	    }

	    // close the open triangle
	    *indexBuffer++ = v[1];
	}
	else
	{
	    // neighbor quad is disabled, just render 1 triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[2];
	    *indexBuffer++ = v[1];
	}

	// render south triangles
	neighbor = mManager->mSouthNeighbor[node];
	if ((neighbor > 0 && mQuadTree[neighbor].isEnabled()))
	{
	    // add a center vertex on the base of the south triangle,
	    // splitting it into 2 triangles
	    v[5] = addVertex(cx, mHeight[cIdx + zAdd], cz + w2);

	    // add indexes for the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[3];
	    *indexBuffer++ = v[5];

	    // add indexes for the second triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[5];
	    *indexBuffer++ = v[4];
	}
	else if (neighbor <= 0 && mSouthNeighbor != 0)
	{
	    // add the first 2 indexes of the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[3];

	    // iterate through the vertices on the neighbor edge to find which ones are enabled
	    for (int pos = cx - w2 + 2; pos < cx + w2; pos += 2)
	    {
		// check if neighborvertex on north edge at pos is enabled
		if (mSouthNeighbor->isNorthEdgeVertexEnabled(pos))
		{
		    // add a vertex matching the vertex on the neighbor edge, close the open triangle and add the first 2 indexes of the next triangle
		    v[5] = addVertex(pos, mHeight[(cz + w2) * mData->terrain.heightMapWidth + pos], cz + w2);
		    *indexBuffer++ = v[5];
		    *indexBuffer++ = v[0];
		    *indexBuffer++ = v[5];
		}
	    }

	    // close the open triangle
	    *indexBuffer++ = v[4];
	}
	else
	{
	    // neighbor quad is disabled, just render 1 triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[3];
	    *indexBuffer++ = v[4];
	}

	// render west triangles
	neighbor = mManager->mWestNeighbor[node];
	if ((neighbor > 0 && mQuadTree[neighbor].isEnabled()))
	{
	    // add a center vertex on the base of the west triangle,
	    // splitting it into 2 triangles
	    v[5] = addVertex(cx - w2, mHeight[cIdx - xAdd], cz);

	    // add indexes for the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[1];
	    *indexBuffer++ = v[5];

	    // add indexes for the second triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[5];
	    *indexBuffer++ = v[3];
	}
	else if (neighbor <= 0 && mWestNeighbor != 0)
	{
	    // add the first 2 indexes of the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[1];

	    // iterate through the vertices on the neighbor edge to find which ones are enabled
	    for (int pos = cz - w2 + 2; pos < cz + w2; pos += 2)
	    {
		// check if neighborvertex on east edge at pos is enabled
		if (mWestNeighbor->isEastEdgeVertexEnabled(pos))
		{
		    // add a vertex matching the vertex on the neighbor edge, close the open triangle and add the first 2 indexes of the next triangle
		    v[5] = addVertex(cx - w2, mHeight[pos * mData->terrain.heightMapWidth + (cx - w2)], pos);
		    *indexBuffer++ = v[5];
		    *indexBuffer++ = v[0];
		    *indexBuffer++ = v[5];
		}
	    }

	    // close the open triangle
	    *indexBuffer++ = v[3];
	}
	else
        {
	    // neighbor quad is disabled, just render 1 triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[1];
	    *indexBuffer++ = v[3];
	}

	// render east triangles
	neighbor = mManager->mEastNeighbor[node];
	if ((neighbor > 0 && mQuadTree[neighbor].isEnabled()))
	{
	    // add a center vertex on the base of the east triangle,
	    // splitting it into 2 triangles
	    v[5] = addVertex(cx + w2, mHeight[cIdx + xAdd], cz);

	    // add indexes for the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[4];
	    *indexBuffer++ = v[5];

	    // add indexes for the second triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[5];
	    *indexBuffer++ = v[2];
	}
	else if (neighbor <= 0 && mEastNeighbor != 0)
	{
	    // add the first 2 indexes of the first triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[4];

	    // iterate through the vertices on the neighbor edge to find which ones are enabled
	    for (int pos = cz + w2 - 2; pos > cz - w2; pos -= 2)
	    {
		// check if neighborvertex on west edge at pos is enabled
		if (mEastNeighbor->isWestEdgeVertexEnabled(pos))
		{
		    // add a vertex matching the vertex on the neighbor edge, close the open triangle and add the first 2 indexes of the next triangle
		    v[5] = addVertex(cx + w2, mHeight[pos * mData->terrain.heightMapWidth + (cx + w2)], pos);
		    *indexBuffer++ = v[5];
		    *indexBuffer++ = v[0];
		    *indexBuffer++ = v[5];
		}
	    }

	    // close the open triangle
	    *indexBuffer++ = v[2];
	}
	else
        {
	    // neighbor quad is disabled, just render 1 triangle
	    *indexBuffer++ = v[0];
	    *indexBuffer++ = v[4];
	    *indexBuffer++ = v[2];
	}

    }
    else // quad disabled, just render 2 tri's
    {
	// find how we should draw the diagonal
	int child = (node - 1) & 0x03;

	if (child == 0 || child == 3)
	{
	    *indexBuffer++ = v[2];
	    *indexBuffer++ = v[1];
	    *indexBuffer++ = v[4];

	    *indexBuffer++ = v[1];
	    *indexBuffer++ = v[3];
	    *indexBuffer++ = v[4];
	}
	else
	{
	    *indexBuffer++ = v[2];
	    *indexBuffer++ = v[1];
	    *indexBuffer++ = v[3];

	    *indexBuffer++ = v[3];
	    *indexBuffer++ = v[4];
	    *indexBuffer++ = v[2];
	}
    }

    // update index counter
    mIndexCount += (indexBuffer - (&mManager->mIndexBuffer[mIndexCount]));
}


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

void NatureTerrainPatch::render(int cx, int cz, int node, int level)
{
    int width = EDGE_LENGTH >> level;

    // if not quad is enabled and not at lowest level, descend
    if (mQuadTree[node].isEnabled() && level < (QUADTREE_DEPTH - 1))
    {
	int w4 = (width >> 2);

	render(cx - w4, cz - w4, (node<<2)+1, level + 1);
	render(cx + w4, cz - w4, (node<<2)+2, level + 1);
	render(cx - w4, cz + w4, (node<<2)+3, level + 1);
	render(cx + w4, cz + w4, (node<<2)+4, level + 1);
    } 
    else
    {
	// if quad at lowest level or disabled, render it
	renderQuad(cx, cz, node, width);
    }
}

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

// TODO: move errorMatrix to manager?
void NatureTerrainPatch::computeError()
{
    unsigned char errorMatrix[QUADTREE_SIZE * QUADTREE_SIZE];
    int width = 2, w2 = 1;

    memset(errorMatrix, 0, QUADTREE_SIZE * QUADTREE_SIZE);

    // go through all nodes of all levels, bottom -> top
    while (width <= EDGE_LENGTH)
    {
	int zAdd = w2 * QUADTREE_SIZE;

	for (int z = w2; z <= (EDGE_LENGTH - w2); z += width)
	{
	    int cIdx = z * QUADTREE_SIZE + w2;

	    for (int x = w2; x <= (EDGE_LENGTH - w2); x += width, cIdx += width)
	    {
		// get the errorvalue for this node
		int err = calculateError(x, z, width), perr, pIdx;

		// get errorvalues from lower level nodes
		if (width > 2)
		{
		    perr = errorMatrix[cIdx - zAdd];
		    if (perr > err) err = perr;

		    perr = errorMatrix[cIdx + zAdd];
		    if (perr > err) err = perr;

		    perr = errorMatrix[cIdx - w2];
		    if (perr > err) err = perr;

		    perr = errorMatrix[cIdx + w2];
		    if (perr > err) err = perr;
		}

		// propagate the error to the corners
		pIdx = cIdx - zAdd - w2;
		if (err > errorMatrix[pIdx]) errorMatrix[pIdx] = err;

		pIdx = cIdx - zAdd + w2;
		if (err > errorMatrix[pIdx]) errorMatrix[pIdx] = err;

		pIdx = cIdx + zAdd - w2;
		if (err > errorMatrix[pIdx]) errorMatrix[pIdx] = err;

		pIdx = cIdx + zAdd + w2;
		if (err > errorMatrix[pIdx]) errorMatrix[pIdx] = err;

		// set the errorvalue for this node
		mQuadTree[mManager->mQuadNodeLookup[cIdx]].setError(err);
	    }
	}

	w2    = width;
	width = width << 1;
    }
}

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

void NatureTerrainPatch::triangulate(int cx, int cz, int node, int level)
{
    int width = EDGE_LENGTH >> level;

    // calculate d2 * desired quality
    Real d2c = static_cast<Real>(mQuadTree[node].getError())
	     * mManager->mTargetQuality;
    if (d2c < 1.0f) d2c = 1.0f;

    // calculate subdivide value
    Real f = mDistance / (mManager->mMinimumQuality * d2c);

    if (f < 1.0)
    {
	mQuadTree[node].enable();

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

	    triangulate(cx - w4, cz - w4, (node<<2)+1, level + 1);
	    triangulate(cx + w4, cz - w4, (node<<2)+2, level + 1);
	    triangulate(cx - w4, cz + w4, (node<<2)+3, level + 1);
	    triangulate(cx + w4, cz + w4, (node<<2)+4, level + 1);
	}
    }

    // use f for geomorph?
//    return f;
}

//----------------------------------------------------------------------------
void NatureTerrainPatch::getNormal(int x, int z, Vector3 *normal)
{   
    Vector3 here, left, down;
                
    here.x = x;
    here.y = mHeight[z * mData->terrain.heightMapWidth + x]
        * mScale.y + mWorld.y;
    here.z = z;
    
    left.x = x - 1;
    if (x > 0)
        left.y = mHeight[z * mData->terrain.heightMapWidth + (x - 1)]
            * mScale.y + mWorld.y;
    else if (mWestNeighbor != 0)
        left.y = mWestNeighbor->getHeightAt(EDGE_LENGTH - 1, z);
    else
        left.y = here.y;

    left.z = z;

    down.x = x;
    if (z < EDGE_LENGTH)
        down.y = mHeight[(z + 1) * mData->terrain.heightMapWidth + x]
            * mScale.y + mWorld.y;
    else if (mSouthNeighbor != 0)
        down.y = mSouthNeighbor->getHeightAt(x, 1);
    else
        down.y = here.y;

    down.z = z + 1;

    left = left - here;
    down = down - here;

    left.normalise();
    down.normalise();

    *normal = left.crossProduct(down);
    normal->normalise();
}
//----------------------------------------------------------------------------

void NatureTerrainPatch::getRenderOperation(RenderOperation& op)
{
    op.useIndexes = true;
    op.operationType = RenderOperation::OT_TRIANGLE_LIST;

    op.vertexData = mVertexData;
    op.vertexData->vertexStart = 0;
    op.vertexData->vertexCount = mVertexCount;

    op.indexData = mIndexData;
    op.indexData->indexStart = 0;
    op.indexData->indexCount = mIndexCount;

    //std::cerr << "index count = " << mIndexCount << std::endl;
}

void NatureTerrainPatch::_notifyCurrentCamera(Camera *cam)
{
    // TODO: fix this...

    Vector3 diff = mWorld + Vector3(32, 0, 32) - cam->getPosition();
    Real dist = diff.length();

    if (dist < 300) dist = 300;
    else if (dist > 700) dist = 700;
    dist -= 200;

    if (fabs(dist - mDistance) > 100 || (dist == 300 && dist != mDistance))
    {
	mDistance = dist;
	mManager->addToRenderQueue(this);
    }

}

} // namespace Ogre

⌨️ 快捷键说明

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