📄 terrrender.cc
字号:
{
pmid->z = fixedToFloat(mCurrentBlock->getHeight(x + dx + dx, y + dy + dy));
if(maxLevel == 1) // interp the z and haze
pmid->z = pmid->z + growFactor * (((p1->z + p2->z) * 0.5) - pmid->z);
pmid->distance = (*pmid - mCamPos).len();
gClientSceneGraph->getFogCoordPair(pmid->distance, pmid->z, pmid->fogRed, pmid->fogGreen);
if(maxLevel == 1) // interp the z and haze
{
pmid->fogRed = pmid->fogRed + growFactor * (((p1->fogRed + p2->fogRed) * 0.5) - pmid->fogRed);
pmid->fogGreen = pmid->fogGreen + growFactor * (((p1->fogGreen + p2->fogGreen) * 0.5) - pmid->fogGreen);
}
if(minLevel >= 0)
{
edge->pointCount = 1;
return;
}
}
// last case - minLevel == -1, midPoint calc'd
edge->pointCount = 3;
EdgePoint *pm1 = &edge->pt[0];
EdgePoint *pm2 = &edge->pt[2];
pm1->x = (p1->x + pmid->x) * 0.5;
pm1->y = (p1->y + pmid->y) * 0.5;
pm2->x = (p2->x + pmid->x) * 0.5;
pm2->y = (p2->y + pmid->y) * 0.5;
if(maxLevel != -1)
{
// clamp it:
pm1->z = (p1->z + pmid->z) * 0.5;
pm1->distance = (*pm1 - mCamPos).len();
pm1->fogRed = (p1->fogRed + pmid->fogRed) * 0.5;
pm1->fogGreen = (p1->fogGreen + pmid->fogGreen) * 0.5;
pm2->z = (p2->z + pmid->z) * 0.5;
pm2->distance = (*pm2 - mCamPos).len();
pm2->fogRed = (p2->fogRed + pmid->fogRed) * 0.5;
pm2->fogGreen = (p2->fogGreen + pmid->fogGreen) * 0.5;
return;
}
// compute the real deals:
pm1->z = fixedToFloat(mCurrentBlock->getHeight(x + dx, y + dy));
pm2->z = fixedToFloat(mCurrentBlock->getHeight(x + dx + dx + dx, y + dy + dy + dy));
if(growFactor)
{
pm1->z = pm1->z + growFactor * (((p1->z + pmid->z) * 0.5) - pm1->z);
pm2->z = pm2->z + growFactor * (((p2->z + pmid->z) * 0.5) - pm2->z);
}
pm1->distance = (*pm1 - mCamPos).len();
gClientSceneGraph->getFogCoordPair(pm1->distance, pm1->z, pm1->fogRed, pm1->fogGreen);
pm2->distance = (*pm2 - mCamPos).len();
gClientSceneGraph->getFogCoordPair(pm2->distance, pm2->z, pm2->fogRed, pm2->fogGreen);
if(growFactor)
{
pm1->fogRed = pm1->fogRed + growFactor * (((p1->fogRed + pmid->fogRed) * 0.5) - pm1->fogRed);
pm1->fogGreen = pm1->fogGreen + growFactor * (((p1->fogGreen + pmid->fogGreen) * 0.5) - pm1->fogGreen);
pm2->fogRed = pm2->fogRed + growFactor * (((p2->fogRed + pmid->fogRed) * 0.5) - pm2->fogRed);
pm2->fogGreen = pm2->fogGreen + growFactor * (((p2->fogGreen + pmid->fogGreen) * 0.5) - pm2->fogGreen);
}
}
EdgePoint *mXFVertices = NULL;
U16 *mXFIndexBuffer;
U16 *mXFIndexPtr;
U32 mXFIndexCount;
U32 mXFPointCount;
U32 mXFIndex;
inline U32 clipPoint(EdgePoint *p1, EdgePoint *p2, F32 dist)
{
F32 frac = (dist - p1->distance) / (p2->distance - p1->distance);
F32 onefrac = 1.0 - frac;
U32 clipIndex = mXFPointCount++;
EdgePoint *ip = mXFVertices + clipIndex;
ip->x = (p2->x * frac) + (p1->x * onefrac);
ip->y = (p2->y * frac) + (p1->y * onefrac);
ip->z = (p2->z * frac) + (p1->z * onefrac);
ip->fogRed = (p2->fogRed * frac) + (p1->fogRed * onefrac);
ip->fogGreen = (p2->fogGreen * frac) + (p1->fogGreen * onefrac);
ip->distance = dist;
return clipIndex;
}
void TerrainRender::clip(U32 indexStart)
{
static U16 dest[16 * 3 * 2];
U32 vertexCount = mXFIndexBuffer[indexStart + 1];
U32 centerPoint = mXFIndexBuffer[indexStart + 2];
U16 *source = mXFIndexBuffer + indexStart + 3;
EdgePoint *center = mXFVertices + centerPoint;
U32 destIndex = 0;
if(mXFVertices[centerPoint].distance > mFarDistance)
{
// loop through all the tris and clip em:
// there are vertexCount - 1 triangles.
EdgePoint *p1 = mXFVertices + source[0];
bool p1out = p1->distance >= mFarDistance;
U32 p1idx = source[0];
U32 clip1;
if(!p1out)
clip1 = clipPoint(p1, center, mFarDistance);
for(U32 i = 0; i < vertexCount - 2; i++)
{
U32 p2idx = source[i+1];
EdgePoint *p2 = mXFVertices + p2idx;
bool p2out = p2->distance >= mFarDistance;
if(!p2out)
{
U32 clip2 = clipPoint(p2, center, mFarDistance);
if(p1out)
{
// p2 is the only "in" point:
dest[destIndex++] = p2idx;
dest[destIndex++] = clip2;
dest[destIndex++] = clipPoint(p1, p2, mFarDistance);
}
else
{
dest[destIndex++] = clip2;
dest[destIndex++] = clip1;
dest[destIndex++] = p1idx;
dest[destIndex++] = p2idx;
dest[destIndex++] = clip2;
dest[destIndex++] = p1idx;
}
clip1 = clip2;
}
else if(!p1out)
{
dest[destIndex++] = p1idx;
dest[destIndex++] = clipPoint(p1, p2, mFarDistance);
dest[destIndex++] = clip1;
}
p1idx = p2idx;
p1out = p2out;
p1 = p2;
}
if(destIndex)
{
// copy this in..
mXFIndexBuffer[indexStart] = GL_TRIANGLES;
mXFIndexBuffer[indexStart + 1] = destIndex;
for(U32 i = 0; i < destIndex; i++)
mXFIndexBuffer[indexStart + i + 2] = dest[i];
mXFIndexCount = destIndex + indexStart + 2;
}
else
mXFIndexCount = indexStart;
}
else
{
EdgePoint *prev = mXFVertices + source[0];
bool prevIn = prev->distance <= mFarDistance;
U32 i;
for(i = 1; i < vertexCount - 1; i++)
{
EdgePoint *pt = mXFVertices + source[i];
bool curIn = pt->distance <= mFarDistance;
if((curIn && !prevIn) || (!curIn && prevIn))
dest[destIndex++] = clipPoint(pt, prev, mFarDistance);
if(curIn)
dest[destIndex++] = source[i];
else
dest[destIndex++] = clipPoint(pt, center, mFarDistance);
prev = pt;
prevIn = curIn;
}
for(i = 0; i < destIndex; i++)
mXFIndexBuffer[indexStart + i + 3] = dest[i];
mXFIndexBuffer[indexStart + destIndex + 3] = dest[0];
mXFIndexBuffer[indexStart + 1] = destIndex + 2;
mXFIndexCount = indexStart + destIndex + 4;
}
}
inline U32 TerrainRender::constructPoint(S32 x, S32 y)
{
U32 ret = mXFPointCount++;
EdgePoint *pt = mXFVertices + ret;
pt->x = x * mSquareSize;
pt->y = y * mSquareSize;
pt->z = fixedToFloat(mCurrentBlock->getHeight(x, y));
pt->distance = (*pt - mCamPos).len();
gClientSceneGraph->getFogCoordPair(pt->distance, pt->z, pt->fogRed, pt->fogGreen);
return ret;
}
inline U32 TerrainRender::interpPoint(U32 p1, U32 p2, S32 x, S32 y, F32 growFactor)
{
U32 ret = mXFPointCount++;
EdgePoint *pt = mXFVertices + ret;
pt->x = x * mSquareSize;
pt->y = y * mSquareSize;
pt->z = fixedToFloat(mCurrentBlock->getHeight(x, y));
pt->z = pt->z + growFactor * (((mXFVertices[p1].z + mXFVertices[p2].z) * 0.5) - pt->z);
pt->distance = (*pt - mCamPos).len();
gClientSceneGraph->getFogCoordPair(pt->distance, pt->z, pt->fogRed, pt->fogGreen);
return ret;
}
inline void TerrainRender::addEdge(ChunkEdge *edge)
{
if(edge->pointCount == 1)
{
edge->pointIndex = mXFPointCount;
mXFVertices[mXFPointCount++] = * ((EdgePoint *) &edge->pt[1]);
}
else if(edge->pointCount == 3)
{
edge->pointIndex = mXFPointCount;
mXFVertices[mXFPointCount++] = *((EdgePoint *) &edge->pt[0]);
mXFVertices[mXFPointCount++] = *((EdgePoint *) &edge->pt[1]);
mXFVertices[mXFPointCount++] = *((EdgePoint *) &edge->pt[2]);
}
edge->xfIndex = mXFIndex;
}
inline void emitTri(U32 i1, U32 i2, U32 i3)
{
mXFIndexBuffer[mXFIndexCount] = i1;
mXFIndexBuffer[mXFIndexCount + 1] = i2;
mXFIndexBuffer[mXFIndexCount + 2] = i3;
mXFIndexCount += 3;
}
inline U32 emitCornerPoint(ChunkCornerPoint *p)
{
if(p->xfIndex != mXFIndex)
{
p->pointIndex = mXFPointCount;
p->xfIndex = mXFIndex;
mXFVertices[mXFPointCount++] = *((EdgePoint *) p);
}
return p->pointIndex;
}
void buildLightTri(LightTriangle* pTri, TerrLightInfo* pInfo)
{
// Get the plane normal
Point3F normal;
mCross((pTri->point1 - pTri->point2), (pTri->point3 - pTri->point2), &normal);
if (normal.lenSquared() < 1e-7)
{
pTri->flags = 0;
return;
}
PlaneF plane(pTri->point2, normal); // Assumes that mPlane.h normalizes incoming point
Point3F centerPoint;
F32 d = plane.distToPlane(pInfo->pos);
centerPoint = pInfo->pos - plane * d;
d = mFabs(d);
if (d >= pInfo->radius) {
pTri->flags = 0;
return;
}
F32 mr = mSqrt(pInfo->radiusSquared - d*d);
Point3F normalS;
Point3F normalT;
mCross(plane, Point3F(0, 1, 0), &normalS);
mCross(plane, normalS, &normalT);
PlaneF splane(centerPoint, normalS); // Assumes that mPlane.h normalizes incoming point
PlaneF tplane(centerPoint, normalT); // Assumes that mPlane.h normalizes incoming point
pTri->color.red = pInfo->r;
pTri->color.green = pInfo->g;
pTri->color.blue = pInfo->b;
pTri->color.alpha = (pInfo->radius - d) / pInfo->radius;
pTri->texco1.set(((splane.distToPlane(pTri->point1) / mr) + 1.0) / 2.0,
((tplane.distToPlane(pTri->point1) / mr) + 1.0) / 2.0);
pTri->texco2.set(((splane.distToPlane(pTri->point2) / mr) + 1.0) / 2.0,
((tplane.distToPlane(pTri->point2) / mr) + 1.0) / 2.0);
pTri->texco3.set(((splane.distToPlane(pTri->point3) / mr) + 1.0) / 2.0,
((tplane.distToPlane(pTri->point3) / mr) + 1.0) / 2.0);
pTri->flags = 1;
}
void TerrainRender::renderChunkCommander(EmitChunk *chunk)
{
U32 ll = mXFPointCount;
for(U32 y = 0; y <= 64; y += 4)
for(U32 x = (y & 4) ? 4 : 0; x <= 64; x += 8)
constructPoint(chunk->x + x,chunk->y + y);
for(U32 y = 0; y < 8; y++)
{
for(U32 x = 0; x < 8; x++)
{
U16 *ib = mXFIndexBuffer + mXFIndexCount;
ib[0] = GL_TRIANGLE_FAN;
ib[1] = 6;
ib[2] = ll + 9;
ib[3] = ll;
ib[4] = ll + 17;
ib[5] = ll + 18;
ib[6] = ll + 1;
ib[7] = ll;
mXFIndexCount += 8;
ll++;
}
ll += 9;
}
}
void TerrainRender::renderChunkOutline(EmitChunk *chunk)
{
U32 startXFIndex = mXFIndexCount;
ChunkEdge *e0 = chunk->edge[0];
ChunkEdge *e1 = chunk->edge[1];
ChunkEdge *e2 = chunk->edge[2];
ChunkEdge *e3 = chunk->edge[3];
if(e0->xfIndex != mXFIndex)
{
if(!e0->xfIndex)
fixEdge(e0, chunk->x, chunk->y + 4, 1, 0);
addEdge(e0);
}
if(e1->xfIndex != mXFIndex)
{
if(!e1->xfIndex)
fixEdge(e1, chunk->x + 4, chunk->y + 4, 0, -1);
addEdge(e1);
}
if(e2->xfIndex != mXFIndex)
{
if(!e2->xfIndex)
fixEdge(e2, chunk->x, chunk->y, 1, 0);
addEdge(e2);
}
if(e3->xfIndex != mXFIndex)
{
if(!e3->xfIndex)
fixEdge(e3, chunk->x, chunk->y + 4, 0, -1);
addEdge(e3);
}
U32 p0 = emitCornerPoint(e0->p1);
U32 p1 = emitCornerPoint(e0->p2);
U32 p2 = emitCornerPoint(e2->p2);
U32 p3 = emitCornerPoint(e2->p1);
// build the interior points:
U32 ip0 = constructPoint(chunk->x + 2, chunk->y + 2);
F32 growFactor = chunk->growFactor;
if(chunk->subDivLevel >= 1)
{
// just emit the fan for the whole square:
S32 i;
mXFIndexBuffer[mXFIndexCount++] = GL_TRIANGLE_FAN;
U32 indexStart = mXFIndexCount++;
mXFIndexBuffer[mXFIndexCount++] = ip0;
mXFIndexBuffer[mXFIndexCount++] = p0;
for(i = 0; i < e0->pointCount; i++)
mXFIndexBuffer[mXFIndexCount++] = e0->pointIndex + i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -