📄 terrdata.cc
字号:
if(py < 0)
py += BlockSize;
GridSquare *sq = findSquare(0, px, py);
sq->minHeight = 0xFFFF;
sq->maxHeight = 0;
getMinMax(sq->minHeight, sq->maxHeight, getHeight(x, y));
getMinMax(sq->minHeight, sq->maxHeight, getHeight(x+1, y));
getMinMax(sq->minHeight, sq->maxHeight, getHeight(x, y+1));
getMinMax(sq->minHeight, sq->maxHeight, getHeight(x+1, y+1));
}
}
// ok, all the level 0 grid squares are updated:
// now update all the parent grid squares that need to be updated:
for(S32 level = 1; level <= TerrainBlock::BlockShift; level++)
{
S32 size = 1 << level;
S32 halfSize = size >> 1;
for(S32 y = (min.y - 1) >> level; y < (max.y + size) >> level; y++)
{
for(S32 x = (min.x - 1) >> level; x < (max.x + size) >> level; x++)
{
S32 px = x << level;
S32 py = y << level;
GridSquare *square = findSquare(level, px, py);
square->minHeight = 0xFFFF;
square->maxHeight = 0;
checkSquareMinMax(square, findSquare(level - 1, px, py));
checkSquareMinMax(square, findSquare(level - 1, px + halfSize, py));
checkSquareMinMax(square, findSquare(level - 1, px, py + halfSize));
checkSquareMinMax(square, findSquare(level - 1, px + halfSize, py + halfSize));
}
}
}
}
//--------------------------------------
/// TGE_Collision
bool TerrainBlock::getHeights(const Point2F &pos, F32 *pHeights)
{
float invSquareSize = 1.0f / (float)squareSize;
float xp = 0.;
float yp = 0.;
/// x,y偏移修正
#ifndef TGE_RPG /// TGE_Collision
S32 sOffset = squareSize * (BlockSize >> 1);
int x = (S32)mFloor((pos.x + sOffset) * invSquareSize);
int y = (S32)mFloor((pos.y + sOffset) * invSquareSize);
#else
int x = (S32)mFloor(pos.x * invSquareSize);
int y = (S32)mFloor(pos.y * invSquareSize);
#endif
S32 squareSize1 = squareSize+1;
x &= TerrainBlock::BlockMask;
y &= TerrainBlock::BlockMask;
float zBottomLeft = fixedToFloat(getHeight(x, y));
float zBottomRight = fixedToFloat(getHeight(x + 1, y));
float zTopLeft = fixedToFloat(getHeight(x, y + 1));
float zTopRight = fixedToFloat(getHeight(x + 1, y + 1));
GridSquare * gs = findSquare(0, Point2I(x,y));
if (gs->flags & GridSquare::Empty)
return false;
for(U32 row=0; row < squareSize1; row++)
{
yp = (float)row * invSquareSize;
U32 uBase = row * squareSize1;
for(U32 col=0; col < squareSize1; col++)
{
xp = (float)col * invSquareSize;
if(gs->flags & GridSquare::Split45)
{
if (xp>yp)
// bottom half
pHeights[uBase + col] = zBottomLeft + xp * (zBottomRight-zBottomLeft) + yp * (zTopRight-zBottomRight);
else
// top half
pHeights[uBase + col] = zBottomLeft + xp * (zTopRight-zTopLeft) + yp * (zTopLeft-zBottomLeft);
}
else
{
if (1.0f-xp>yp)
// bottom half
pHeights[uBase + col] = zBottomRight + (1.0f-xp) * (zBottomLeft-zBottomRight) + yp * (zTopLeft-zBottomLeft);
else
// top half
pHeights[uBase + col] = zBottomRight + (1.0f-xp) * (zTopLeft-zTopRight) + yp * (zTopRight-zBottomRight);
}
}//for
}//for
return true;
}
//--------------------------------------
bool TerrainBlock::getHeight(const Point2F &pos, F32 *height)
{
float invSquareSize = 1.0f / (float)squareSize;
/// x,y偏移修正
#ifndef TGE_RPG /// TGE_Collision
S32 sOffset = squareSize * (BlockSize >> 1);
float xp = (pos.x + sOffset) * invSquareSize;
float yp = (pos.y + sOffset) * invSquareSize;
#else
float xp = pos.x * invSquareSize;
float yp = pos.y * invSquareSize;
#endif
int x = (S32)mFloor(xp);
int y = (S32)mFloor(yp);
xp -= (float)x;
yp -= (float)y;
x &= BlockMask;
y &= BlockMask;
GridSquare * gs = findSquare(0, Point2I(x,y));
if (gs->flags & GridSquare::Empty)
return false;
float zBottomLeft = fixedToFloat(getHeight(x, y));
float zBottomRight = fixedToFloat(getHeight(x + 1, y));
float zTopLeft = fixedToFloat(getHeight(x, y + 1));
float zTopRight = fixedToFloat(getHeight(x + 1, y + 1));
if(gs->flags & GridSquare::Split45)
{
if (xp>yp)
// bottom half
*height = zBottomLeft + xp * (zBottomRight-zBottomLeft) + yp * (zTopRight-zBottomRight);
else
// top half
*height = zBottomLeft + xp * (zTopRight-zTopLeft) + yp * (zTopLeft-zBottomLeft);
}
else
{
if (1.0f-xp>yp)
// bottom half
*height = zBottomRight + (1.0f-xp) * (zBottomLeft-zBottomRight) + yp * (zTopLeft-zBottomLeft);
else
// top half
*height = zBottomRight + (1.0f-xp) * (zTopLeft-zTopRight) + yp * (zTopRight-zBottomRight);
}
return true;
}
bool TerrainBlock::getNormal(const Point2F & pos, Point3F * normal, bool normalize)
{
float invSquareSize = 1.0f / (float)squareSize;
/// x,y偏移修正
#ifndef TGE_RPG /// TGE_Collision
S32 sOffset = squareSize * (BlockSize >> 1);
float xp = (pos.x + sOffset) * invSquareSize;
float yp = (pos.y + sOffset) * invSquareSize;
#else
float xp = pos.x * invSquareSize;
float yp = pos.y * invSquareSize;
#endif
int x = (S32)mFloor(xp);
int y = (S32)mFloor(yp);
xp -= (float)x;
yp -= (float)y;
x &= BlockMask;
y &= BlockMask;
GridSquare * gs = findSquare(0, Point2I(x,y));
if (gs->flags & GridSquare::Empty)
return false;
float zBottomLeft = fixedToFloat(getHeight(x, y));
float zBottomRight = fixedToFloat(getHeight(x + 1, y));
float zTopLeft = fixedToFloat(getHeight(x, y + 1));
float zTopRight = fixedToFloat(getHeight(x + 1, y + 1));
if(gs->flags & GridSquare::Split45)
{
if (xp>yp)
// bottom half
normal->set(zBottomLeft-zBottomRight,zBottomRight-zTopRight,squareSize);
else
// top half
normal->set(zTopLeft-zTopRight,zBottomLeft-zTopLeft,squareSize);
}
else
{
if (1.0f-xp>yp)
// bottom half
normal->set(zBottomLeft-zBottomRight,zBottomLeft-zTopLeft,squareSize);
else
// top half
normal->set(zTopLeft-zTopRight,zBottomRight-zTopRight,squareSize);
}
if (normalize)
normal->normalize();
return true;
}
bool TerrainBlock::getNormalAndHeight(const Point2F & pos, Point3F * normal, F32 * height, bool normalize)
{
float invSquareSize = 1.0f / (float)squareSize;
/// x,y偏移修正
#ifndef TGE_RPG /// TGE_Collision
//Point3F offset = getRenderPosition();
S32 sOffset = squareSize * (BlockSize >> 1);
float xp = (pos.x + sOffset) * invSquareSize;
float yp = (pos.y + sOffset) * invSquareSize;
#else
float xp = pos.x * invSquareSize;
float yp = pos.y * invSquareSize;
#endif
int x = (S32)mFloor(xp);
int y = (S32)mFloor(yp);
xp -= (float)x;
yp -= (float)y;
x &= BlockMask;
y &= BlockMask;
GridSquare * gs = findSquare(0, Point2I(x,y));
if (gs->flags & GridSquare::Empty)
return false;
float zBottomLeft = fixedToFloat(getHeight(x, y));
float zBottomRight = fixedToFloat(getHeight(x + 1, y));
float zTopLeft = fixedToFloat(getHeight(x, y + 1));
float zTopRight = fixedToFloat(getHeight(x + 1, y + 1));
if(gs->flags & GridSquare::Split45)
{
if (xp>yp)
{
// bottom half
normal->set(zBottomLeft-zBottomRight,zBottomRight-zTopRight,squareSize);
*height = zBottomLeft + xp * (zBottomRight-zBottomLeft) + yp * (zTopRight-zBottomRight);
}
else
{
// top half
normal->set(zTopLeft-zTopRight,zBottomLeft-zTopLeft,squareSize);
*height = zBottomLeft + xp * (zTopRight-zTopLeft) + yp * (zTopLeft-zBottomLeft);
}
}
else
{
if (1.0f-xp>yp)
{
// bottom half
normal->set(zBottomLeft-zBottomRight,zBottomLeft-zTopLeft,squareSize);
*height = zBottomRight + (1.0f-xp) * (zBottomLeft-zBottomRight) + yp * (zTopLeft-zBottomLeft);
}
else
{
// top half
normal->set(zTopLeft-zTopRight,zBottomRight-zTopRight,squareSize);
*height = zBottomRight + (1.0f-xp) * (zTopLeft-zTopRight) + yp * (zTopRight-zBottomRight);
}
}
if (normalize)
normal->normalize();
return true;
}
//------------------------------------------------------------------------------
void TerrainBlock::setBaseMaterials(S32 argc, const char *argv[])
{
for (S32 i = 0; i < argc; i++)
mMaterialFileName[i] = StringTable->insert(argv[i]);
for (S32 j = argc; j < MaterialGroups; j++)
mMaterialFileName[j] = NULL;
}
//------------------------------------------------------------------------------
//--------------------------------------
bool TerrainBlock::buildMaterialMap()
{
TerrainRender::flushCache();
return initMMXBlender();
}
// This routine takes 256x256 bitmap and makes
// sure that each 128 x 128 grid has borders that
// match adjacent 128 x 128 grids. This fixes a
// terrain blending error/defect.
void tweakTerrainBmp(GBitmap * pBitmap)
{
AssertFatal(pBitmap->getWidth() == pBitmap->getHeight() &&
pBitmap->getFormat()==GBitmap::RGB,
"tweakTerrainBmp - This should have been caught before, but this is an invalid terrain texture.");
S32 size = pBitmap->getWidth();
for (int k = 0; k < pBitmap->getNumMipLevels() - 4; k++)
{
U8 * bits = pBitmap->getWritableBits(k);
S32 offset1 = -1;
S32 offset2 = 0;
S32 base;
for (base=0; base<size; base += size / 2)
{
S32 top1 = (base + offset1 + size) % size;
top1 *= 3;
S32 top2 = (base + offset2 + size) % size;
top2 *= 3;
// slide down column
for (S32 i=0; i<size; i++)
{
for (S32 j=0; j<3; j++)
{
U8 val1 = bits[top1 + i*size*3 + j];
U8 val2 = bits[top2 + i*size*3 + j];
U8 val = (val1 >> 1) + (val2 >> 1);
if (val1 & val2 & 1)
++val;
bits[top1 + i*size*3 + j] = bits[top2 + i*size*3 + j] = val;
}
}
}
for (base=0; base<size; base += size / 2)
{
S32 left1 = (base + offset1 + size) % size;
left1 *= size * 3;
S32 left2 = (base + offset2 + size) % size;
left2 *= size * 3;
// slide across row
for (S32 i=0; i<size; i++)
{
for (S32 j=0; j<3; j++)
{
U8 val1 = bits[left1 + i*3 + j];
U8 val2 = bits[left2 + i*3 + j];
U8 val = (val1 >> 1) + (val2 >> 1);
if (val1 & val2 & 1)
++val;
bits[left1+i*3 + j] = bits[left2 + i*3 + j] = val;
}
}
}
size /= 2;
}
}
bool TerrainBlock::initMMXBlender()
{
// DMMNOTE: come back to this
delete mBlender;
mBlender = NULL;
char fileBuf[256];
U32 validMaterials = 0;
S32 i;
for (i = 0; i < MaterialGroups; i++)
{
if (mMaterialFileName[i] && *mMaterialFileName[i])
validMaterials++;
else
break;
}
AssertFatal(validMaterials != 0, "Error, must have SOME materials here!");
// Submit alphamaps
U8* alphaMaterials[MaterialGroups];
dMemset(alphaMaterials, 0, sizeof(alphaMaterials));
for (i = 0; i < validMaterials; i++) {
if (getMaterialAlphaMap(i) == NULL) {
AssertFatal(getMaterialAlphaMap(i) != NULL, "Error, need an alpha map here!");
return false;
}
alphaMaterials[i] = getMaterialAlphaMap(i);
}
mBlender = new Blender(validMaterials, 5, alphaMaterials);
// Ok, we have validMaterials set correctly
bool matsValid = true;
for(i = 0; i < validMaterials; i++)
{
AssertFatal(mMaterialFileName[i] && *mMaterialFileName[i], "Error, something wacky here");
StringTableEntry fn = mMaterialFileName[i];
GBitmap* pBitmap = TextureManager::loadBitmapInstance(fn);
if (!pBitmap)
{
dStrcpyl(fileBuf, sizeof(fileBuf), mFile.getFilePath(), "/", fn, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -