📄 roam_naturepatch.cpp
字号:
static_cast<int>(mBaseVertex[2].x),
static_cast<int>(mBaseVertex[2].z),
2, 2);
tesselate(&mBaseRight, static_cast<int>(mBaseVertex[1].x),
static_cast<int>(mBaseVertex[1].z),
static_cast<int>(mBaseVertex[0].x),
static_cast<int>(mBaseVertex[0].z),
static_cast<int>(mBaseVertex[3].x),
static_cast<int>(mBaseVertex[3].z),
3, 2);
#if STITCH_EDGES
memset(mEdgeVertices, 0xffff, (PATCH_SIZE+1) * 4 * sizeof(ushort));
#if DRAW_EDGE_SKIRTS
mUsedSkirts[0] = mUsedSkirts[1] = mUsedSkirts[2] = mUsedSkirts[3] = 0;
#endif
#endif
// Store base vertices
memset(mVertexLookup, 0xffff, ((PATCH_SIZE+1)*(PATCH_SIZE+1))
* sizeof(ushort));
mVertexCount = mIndexCount = 0;
STORE_VERTEX_NEW(static_cast<int>(mBaseVertex[0].x),
static_cast<int>(mBaseVertex[0].y),
static_cast<int>(mBaseVertex[0].z));
STORE_VERTEX_NEW(static_cast<int>(mBaseVertex[1].x),
static_cast<int>(mBaseVertex[1].y),
static_cast<int>(mBaseVertex[1].z));
STORE_VERTEX_NEW(static_cast<int>(mBaseVertex[2].x),
static_cast<int>(mBaseVertex[2].y),
static_cast<int>(mBaseVertex[2].z));
STORE_VERTEX_NEW(static_cast<int>(mBaseVertex[3].x),
static_cast<int>(mBaseVertex[3].y),
static_cast<int>(mBaseVertex[3].z));
// Store base texture coordinates
STORE_TEXCOORD(0, mBaseVertex[0].x, mBaseVertex[0].z);
STORE_TEXCOORD(3, mBaseVertex[1].x, mBaseVertex[1].z);
STORE_TEXCOORD(6, mBaseVertex[2].x, mBaseVertex[2].z);
STORE_TEXCOORD(9, mBaseVertex[3].x, mBaseVertex[3].z);
// Build the vertexbuffers
render(&mBaseLeft, static_cast<int>(mBaseVertex[0].x),
static_cast<int>(mBaseVertex[0].z),
static_cast<int>(mBaseVertex[1].x),
static_cast<int>(mBaseVertex[1].z),
static_cast<int>(mBaseVertex[2].x),
static_cast<int>(mBaseVertex[2].z),
0, 3, 6, 2);
render(&mBaseRight, static_cast<int>(mBaseVertex[1].x),
static_cast<int>(mBaseVertex[1].z),
static_cast<int>(mBaseVertex[0].x),
static_cast<int>(mBaseVertex[0].z),
static_cast<int>(mBaseVertex[3].x),
static_cast<int>(mBaseVertex[3].z),
3, 0, 9, 2);
// Create new buffers
mVertexCacheSize = (mVertexCount * 3);
mIndexCacheSize = mIndexCount;
if (mVertexCache != 0) delete[] mVertexCache;
if (mIndexCache != 0) delete[] mIndexCache;
if (mTexCoordCache[0] != 0) delete[] mTexCoordCache[0];
// if (mTexCoordCache[1] != 0) delete[] mTexCoordCache[1];
// Allocate buffers
#if STITCH_EDGES & DRAW_EDGE_SKIRTS
mVertexCache = new Real[mVertexCacheSize + (MAX_EDGE_SKIRTS*4)*6];
mIndexCache = new ushort[mIndexCacheSize + (MAX_EDGE_SKIRTS*4)*9];
mTexCoordCache[0] = new Real[(mVertexCount + (MAX_EDGE_SKIRTS*4)*2) * 2];
// mTexCoordCache[1] = new Real[(mVertexCount + (MAX_EDGE_SKIRTS*4)*2) * 2];
#else
mVertexCache = new Real[mVertexCacheSize];
mIndexCache = new ushort[mIndexCacheSize];
mTexCoordCache[0] = new Real[mVertexCount * 2];
// mTexCoordCache[1] = new Real[mVertexCount * 2];
#endif
// Copy data to the new buffers for the RenderOperation
memcpy(mVertexCache, vertexBuffer, mVertexCacheSize * sizeof(Real));
memcpy(mIndexCache, indexBuffer, mIndexCacheSize * sizeof(ushort));
memcpy(mTexCoordCache[0], texCoordBuffer[0], mVertexCount*sizeof(Real)*2);
// memcpy(mTexCoordCache[1], texCoordBuffer[1], mVertexCount*sizeof(Real)*2);
#if DRAW_EDGE_SKIRTS
mVertexBuffer = mVertexCache;
mIndexBuffer = mIndexCache;
mTexCoordBuffer[0] = mTexCoordCache[0];
// mTexCoordBuffer[1] = mTexCoordCache[1];
#endif
#if STITCH_EDGES
mNeedsStitching = 0x0f;
#endif
// mNeedsRebuild = false;
*/
// Return number of triangles generated
return (mIndexCount / 3);
}
//---------------------------------------------------------------------------
#if STITCH_EDGES
#if DRAW_EDGE_SKIRTS
// Removes the skirts on an edge by removing its indexes from the indexcache
void NaturePatch::clearSkirtEdge(int direction)
{
if (mUsedSkirts[direction] == 0)
{
return;
}
// Calculate offset to first free index before skirts were added
int count = mUsedSkirts[0] + mUsedSkirts[1]
+ mUsedSkirts[2] + mUsedSkirts[3];
int offset = mIndexCacheSize - (count * 9);
// Clear the edge
mUsedSkirts[direction] = 0;
// Copy the indexes of the remaining skirts
for (int i = 0; i < 4; i++)
{
if (mUsedSkirts[i] != 0)
{
memcpy(&mIndexCache[offset], mSkirtIndexes[i],
mUsedSkirts[i] * 9 * sizeof(ushort));
offset += mUsedSkirts[i] * 9;
}
}
// Update size of the indexcache
mIndexCacheSize = offset;
}
#endif
void NaturePatch::stitch(int direction, NaturePatch *neighborPatch)
{
int neighborDir, lo = 0, ln = 0, i, n;
ushort *neighborEdge;
ushort *ourEdge;
if (!(mNeedsStitching & (1 << direction)))
return;
switch (direction)
{
case EDGE_NORTH: neighborDir = EDGE_SOUTH; break;
case EDGE_SOUTH: neighborDir = EDGE_NORTH; break;
case EDGE_WEST: neighborDir = EDGE_EAST; break;
case EDGE_EAST: neighborDir = EDGE_WEST; break;
default: return;
}
/* printf("STITCHING: %s direction %d with %s direction %d -- ",
(const char *)mName, direction, (const char *)neighborPatch->getName(),
neighborDir); */
ourEdge = &mEdgeVertices[direction * (PATCH_SIZE+1)];
neighborEdge = &neighborPatch->mEdgeVertices[neighborDir * (PATCH_SIZE+1)];
// Reset the ypos of each edge vertex where vertex exists on both patches
for (i = 0; i < PATCH_SIZE+1; i++)
{
if (ourEdge[i] != 0xffff && neighborEdge[i] != 0xffff)
{
int x = static_cast<int>(((mVertexCache[ourEdge[i] + 0] - mWorld.x)
/ mScale.x) + 0.5);
int z = static_cast<int>(((mVertexCache[ourEdge[i] + 2] - mWorld.z)
/ mScale.z) + 0.5);
Real height = (GET_HEIGHT(x, z) * mScale.y) + mWorld.y;
mVertexCache[ourEdge[i] + 1] = height;
neighborPatch->mVertexCache[neighborEdge[i] + 1] = height;
}
}
#if DRAW_EDGE_SKIRTS
// Clear the skirts on the neighbors edge
neighborPatch->clearSkirtEdge(neighborDir);
int idxOff = 0;
#endif
// Find and fix cracks
for (i = 0; i < PATCH_SIZE+1; i++)
{
if (ourEdge[i] != 0xffff)
{
if (neighborEdge[i] == 0xffff)
{
// our edge has a vertex thats not on the neighbors edge,
// find the next neighbor vertex
for (n = i+1; n < (PATCH_SIZE+1); n++)
{
if (neighborEdge[n] != 0xffff)
break;
}
// next vertex found, calculate new heigh of our vertex
Real diffHeight = neighborPatch->mVertexCache[neighborEdge[n] + 1] -
neighborPatch->mVertexCache[neighborEdge[ln] + 1];
Real newHeight = neighborPatch->mVertexCache[neighborEdge[ln] + 1]
+ diffHeight * (Real)((i-ln)/(Real)(n-ln));
// update our vertex to the new height
mVertexCache[ourEdge[i] + 1] = newHeight;
#if DRAW_EDGE_SKIRTS
if (mUsedSkirts[direction] < MAX_EDGE_SKIRTS)
{
register int ni = (mVertexCount++) * 3;
mVertexCache[ni + 0] = mVertexCache[ourEdge[i] + 0];
mVertexCache[ni + 1] = mVertexCache[ourEdge[i] + 1] - 1.0;
mVertexCache[ni + 2] = mVertexCache[ourEdge[i] + 2];
register int ni2 = (mVertexCount++) * 3;
mVertexCache[ni2 + 0] = neighborPatch->
mVertexCache[neighborEdge[n] + 0];
mVertexCache[ni2 + 1] = neighborPatch->
mVertexCache[neighborEdge[n] + 1];
mVertexCache[ni2 + 2] = neighborPatch->
mVertexCache[neighborEdge[n] + 2];
int tx = static_cast<int>((mVertexCache[ni + 0] -
mWorld.x) / mScale.x);
int tz = static_cast<int>((mVertexCache[ni + 2] -
mWorld.z) / mScale.z);
STORE_TEXCOORD(ni, tx, tz);
tx = static_cast<int>((mVertexCache[ni2 + 0] -
mWorld.x) / mScale.x);
tz = static_cast<int>((mVertexCache[ni2 + 2] -
mWorld.z) / mScale.z);
STORE_TEXCOORD(ni2, tx, tz);
if (direction == EDGE_NORTH || direction == EDGE_EAST)
{
mSkirtIndexes[direction][idxOff++] = ourEdge[i] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[i] / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
ADD_TRIANGLE(ourEdge[i], ni, ourEdge[lo]);
ADD_TRIANGLE(ni2, ni, ourEdge[i]);
ADD_TRIANGLE(ourEdge[lo], ni, ni2);
}
else
{
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[i] / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[i] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
ADD_TRIANGLE(ourEdge[lo], ni, ourEdge[i]);
ADD_TRIANGLE(ourEdge[i], ni, ni2);
ADD_TRIANGLE(ni2, ni, ourEdge[lo]);
}
mUsedSkirts[direction]++;
}
#endif
}
lo = i;
}
if (neighborEdge[i] != 0xffff)
{
if (ourEdge[i] == 0xffff)
{
// the neighbor edge has a vertex thats not on our edge
// find our next vertex
for (n = i+1; n < (PATCH_SIZE+1); n++)
{
if (ourEdge[n] != 0xffff)
break;
}
// next vertex found, calculate new heigh of neighbors vertex
Real diffHeight = mVertexCache[ourEdge[n] + 1] -
mVertexCache[ourEdge[lo] + 1];
Real newHeight = mVertexCache[ourEdge[lo] + 1] +
diffHeight * ((Real)(i-lo)/(Real)(n-lo));
// update neighbor vertex to the new height
neighborPatch->mVertexCache[neighborEdge[i] + 1] = newHeight;
#if DRAW_EDGE_SKIRTS
if (mUsedSkirts[direction] < MAX_EDGE_SKIRTS)
{
register int ni = (mVertexCount++) * 3;
mVertexCache[ni + 0] = neighborPatch->
mVertexCache[neighborEdge[i] + 0];
mVertexCache[ni + 1] = neighborPatch->
mVertexCache[neighborEdge[i] + 1] - 1.0;
mVertexCache[ni + 2] = neighborPatch->
mVertexCache[neighborEdge[i] + 2];
register int ni2 = (mVertexCount++) * 3;
mVertexCache[ni2 + 0] = mVertexCache[ni + 0];
mVertexCache[ni2 + 1] = mVertexCache[ni + 1] + 1.0;
mVertexCache[ni2 + 2] = mVertexCache[ni + 2];
int tx = static_cast<int>((mVertexCache[ni + 0] -
mWorld.x) / mScale.x);
int tz = static_cast<int>((mVertexCache[ni + 2] -
mWorld.z) / mScale.z);
STORE_TEXCOORD(ni, tx, tz);
STORE_TEXCOORD(ni2, tx, tz);
if (direction == EDGE_NORTH || direction == EDGE_EAST)
{
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[n] / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[n] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
ADD_TRIANGLE(ourEdge[lo], ni, ni2);
ADD_TRIANGLE(ni2, ni, ourEdge[n]);
ADD_TRIANGLE(ourEdge[n], ni, ourEdge[lo]);
}
else
{
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[n] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ni2 / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[lo] / 3;
mSkirtIndexes[direction][idxOff++] = ni / 3;
mSkirtIndexes[direction][idxOff++] = ourEdge[n] / 3;
ADD_TRIANGLE(ni2, ni, ourEdge[lo]);
ADD_TRIANGLE(ourEdge[n], ni, ni2);
ADD_TRIANGLE(ourEdge[lo], ni, ourEdge[n]);
}
mUsedSkirts[direction]++;
}
#endif
}
ln = i;
}
}
#if DRAW_EDGE_SKIRTS
mVertexCacheSize = (mVertexCount * 3);
mIndexCacheSize = mIndexCount;
#endif
// Update status flags to make sure that edges only gets stitched once
// neighborPatch->mNeedsStitching &= ~(1 << neighborDir);
mNeedsStitching &= ~(1 << direction);
/* std::cout << mUsedSkirts[direction] << " skirts added" << std::endl; */
}
#endif
//----------------------------------------------------------------------------
void NaturePatch::getRenderOperation(RenderOperation& op)
{
/* TODO
rend.useIndexes = true;
rend.vertexOptions = LegacyRenderOperation::VO_TEXTURE_COORDS;
//rend.vertexOptions |= LegacyRenderOperation::VO_DIFFUSE_COLOURS;
rend.operationType = LegacyRenderOperation::OT_TRIANGLE_LIST;
// use colors
rend.pDiffuseColour = 0;
rend.diffuseStride = 0;
// textures
rend.numTextureCoordSets = 1;
rend.numTextureDimensions[0] = 2;
// rend.numTextureDimensions[1] = 2;
rend.pTexCoords[0] = mTexCoordCache[0];
// rend.pTexCoords[1] = mTexCoordCache[1];
rend.texCoordStride[0] = 0;
// rend.texCoordStride[1] = 0;
// vertices & indexes
rend.vertexStride = 0;
rend.pVertices = mVertexCache;
rend.pIndexes = mIndexCache;
rend.numVertices = mVertexCacheSize/3;
rend.numIndexes = mIndexCacheSize;
// lighting
rend.pNormals = 0;
*/
return RenderOperation();
}
//----------------------------------------------------------------------------
void NaturePatch::_notifyCurrentCamera(Camera *cam)
{
Real quality = 1.0;
Vector3 diff = mCenter - cam->getPosition();
Real dist = diff.length();
if (dist > 400) quality = 0.30;
else if (dist > 300) quality = 0.60;
else quality = 1.0;
/* if (dist > 400) quality = 0.15;
else if (dist > 300) quality = 0.30;
else if (dist > 200) quality = 0.60;
else quality = 1.5;
*/
quality = quality * mQualityModifier;
if (mMeshQuality != quality)
{
mMeshQuality = quality;
mNeedsRebuild = true;
}
}
//----------------------------------------------------------------------------
uint NaturePatch::getMemoryUsage()
{
unsigned int memUsage = 0;
// vertexcache
memUsage += ((mVertexCount*3) + ((MAX_EDGE_SKIRTS*4)*6)) * sizeof(Real);
// indexcache
memUsage += (mIndexCount + (MAX_EDGE_SKIRTS*4)*9) * sizeof(Real);
// texturecoordcache
memUsage += ((mVertexCount + (MAX_EDGE_SKIRTS*4)*2)*2) * sizeof(ushort);
memUsage += VARBUF_SIZE * 2;
return memUsage + sizeof(NaturePatch);
}
} // Ogre namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -