📄 mapnormaler.cpp
字号:
#include "MapUtil.h"
#include "MapNormaler.h"
#include "OgrePagingLandScapeOptions.h"
namespace Ogre
{
MapNormaler::MapNormaler()
{
reset();
}
MapNormaler::~MapNormaler()
{
delete[] Normals;
}
//----------------------------------------------------------------------
Image *MapNormaler::getNormalMap()
{
if (mAlreadyComputed == false)
{
CalcNormalMap();
mAlreadyComputed = true;
}
return &NormalMap;
}
//----------------------------------------------------------------------
void MapNormaler::reset()
{
mAlreadyComputed = false;
}
//----------------------------------------------------------------------
const Vector3 MapNormaler::getNormalAt (const uint x, const uint z)
{
if (mAlreadyComputed == false)
{
CalcNormalMap();
mAlreadyComputed = true;
}
return Normals[( z * mWidth) + x];
}
#define getHeight(A,B) (MapUtil::getSingleton().getHeight(A, B))
//----------------------------------------------------------------------
void MapNormaler::CalcNormalMap()
{
uint height = MapUtil::getSingleton().getMapHeight ();
uint width = MapUtil::getSingleton().getMapWidth ();
mHeight = height;
mWidth = width;
DataChunk dc;
dc.allocate(width * height * 3);
uchar *NormalData = dc.getPtr();
Normals = new Vector3 [width * height];
std::cout << "normal Map Calc : ";
// First General method : (9 adds and 6 muls + a normalization)
// *---v3--*
// | | |
// | | |
// v1--X--v2
// | | |
// | | |
// *---v4--*
//
// U = v2 - v1;
// V = v4 - v3;
// N = Cross(U, V);
// N.normalise;
//
// BUT IN CASE OF A HEIGHTMAP :
//
// if you do some math by hand before you code,
// you can see that N is immediately given by
// Approximation (2 adds and a normalization)
//
// N = Vector3(z[x-1][y] - z[x+1][y], z[x][y-1] - z[x][y+1], 2);
// N.normalise();
//
// or even using SOBEL operator VERY accurate!
// (14 adds and a normalization)
//
// N = Vector3 (z[x-1][y-1] + z[x-1][y] + z[x-1][y] + z[x-1][y+1] - z[x+1][y-1] - z[x+1][y] - z[x+1][y] - z[x+1][y+1],
// z[x-1][y-1] + z[x][y-1] + z[x][y-1] + z[x+1][y-1] - z[x-1][y+1] - z[x][y+1] - z[x][y+1] - z[x+1][y+1],
// 8);
// N.normalize();
uint j = 0;
uint k = 0;
for (uint z = 0; z < height; z++)
{
DEBUG_PROGRESS_OUTPUT(".")
for (uint x = 0; x < width; x++)
{
// Fast SOBEL filter and mathematically correct
Normals[k].x = getHeight(x-1,z-1) + getHeight (x-1, z) + getHeight (x-1, z) + getHeight (x-1, z+1) - getHeight (x+1, z-1) - getHeight (x+1, z) - getHeight (x+1, z) - getHeight (x+1, z+1);
Normals[k].z = getHeight (x-1, z-1) + getHeight (x, z-1) + getHeight (x, z-1) + getHeight (x+1, z-1) - getHeight (x-1, z+1) - getHeight (x, z+1) - getHeight (x, z+1) - getHeight (x+1, z+1);
Normals[k].y = 8.0f;
// very Fast SOBEL filter
// (not mathematically correct, approximation)
// But gives same result as above
//Normals[k].x = getHeight (x - 1 , z) - getHeight (x + 1, z);
//Normals[k].z = getHeight (x, z-1) - getHeight (x , z + 1);
//Normals[k].y = 2.0f;
Normals[k].normalise ();
NormalData[j++] = (uchar)((Normals[k].x + 1.0f) * 127.5f);
NormalData[j++] = (uchar)((Normals[k].y + 1.0f) * 127.5f);
NormalData[j++] = (uchar)((Normals[k].z + 1.0f) * 127.5f);
k++;
}
}
NormalMap.loadRawData(dc, width, height, PF_R8G8B8);
dc.clear();
std::cout << "\n";
}
}//namespace Ogre
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -