📄 etsplattingmanager.cpp
字号:
}
}
}
void updateTextures()
{
// update all map textures
for (uint i = 0; i < numMaps; ++i)
maps[i]->updateTexture();
}
// helper function for createBaseTexture
float interpolateWeight(size_t x, size_t y, size_t maxX, size_t maxY, size_t channel)
{
// get base position and interpolation
float realPosX = float(x) * width / maxX;
float realPosY = float(y) * height / maxY;
uint posX = (uint)realPosX, posY = (uint)realPosY;
float interpX = realPosX - posX, interpY = realPosY - posY;
// adjust if at borders
if (posX == width-1)
{
--posX;
interpX = 1.0f;
}
if (posY == height-1)
{
--posY;
interpY = 1.0f;
}
float interpXi = 1.0f-interpX, interpYi = 1.0f-interpY;
size_t m = channel/channels;
uint c = (uint) (channel%channels);
float val = maps[m]->getValue(posX, posY, c) * interpXi * interpYi;
val += maps[m]->getValue(posX+1, posY, c) * interpX * interpYi;
val += maps[m]->getValue(posX+1, posY+1, c) * interpX * interpY;
val += maps[m]->getValue(posX, posY+1, c) * interpXi * interpY;
val /= 255;
return val;
}
};
}
SplattingManager::SplattingManager(const string& baseName, const string& group, uint width, uint height, uint channels)
{
if (channels < 1 || channels > 4)
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Number of channels per texture must be between 1 and 4", "SplattingManager::SplattingManager");
mImpl = new Impl::SplattingImpl();
mImpl->baseName = baseName;
mImpl->group = group;
mImpl->width = width;
mImpl->height = height;
mImpl->channels = channels;
mImpl->numTextures = 0;
mImpl->numMaps = 0;
}
SplattingManager::~SplattingManager()
{
for (uint i = 0; i < mImpl->numMaps; ++i)
delete mImpl->maps[i];
delete mImpl;
}
void SplattingManager::setNumTextures(uint numTextures)
{
// the number of maps needed depends on the number of channels per texture
if (numTextures == 0)
setNumMaps(0);
else
setNumMaps((numTextures-1) / mImpl->channels + 1);
}
uint SplattingManager::getNumTextures() const
{
return mImpl->numTextures;
}
void SplattingManager::setNumMaps(uint numMaps)
{
mImpl->numMaps = numMaps;
mImpl->numTextures = mImpl->numMaps * mImpl->channels;
// add maps if we don't have enough
for (size_t i = mImpl->maps.size(); i <= mImpl->numMaps; ++i)
{
mImpl->maps.push_back(new Impl::CoverageMap(mImpl->baseName+StringConverter::toString(i),
mImpl->group, mImpl->width, mImpl->height, mImpl->channels, i != 0));
}
// remove maps if there are too many
for (size_t i = mImpl->maps.size(); i > mImpl->numMaps; --i)
{
delete *mImpl->maps.rbegin();
mImpl->maps.pop_back();
}
}
uint SplattingManager::getNumMaps() const
{
return mImpl->numMaps;
}
NameList SplattingManager::getMapTextureNames() const
{
NameList names;
for (size_t i = 0; i < mImpl->maps.size(); ++i)
names.push_back(mImpl->maps[i]->getName());
return names;
}
void SplattingManager::loadMapFromImage(uint mapNum, const Image& image)
{
mImpl->maps[mapNum]->loadFromImage(image);
}
void SplattingManager::saveMapToImage(uint mapNum, Image& image)
{
mImpl->maps[mapNum]->saveToImage(image);
}
void SplattingManager::paint(uint textureNum, int x, int y, const Brush& brush, float intensity)
{
// positions given are supposed to be the mid of the brush
// so adjust accordingly
x -= (int)brush.getWidth()/2;
y -= (int)brush.getHeight()/2;
// iterate over all fields of the brush array and apply them to the map textures
// if they lie within the bounds
for (size_t i = 0; i < brush.getWidth(); ++i)
{
int posX = x + (int)i;
if (posX < 0 || posX >= (int)mImpl->width)
continue;
for (size_t j = 0; j < brush.getHeight(); ++j)
{
int posY = y + (int)j;
if (posY < 0 || posY >= (int)mImpl->height)
continue;
mImpl->paint(textureNum, (uint)posX, (uint)posY, brush.at(i, j) * intensity);
}
}
// finally, update the textures
mImpl->updateTextures();
}
void SplattingManager::createColourMap(Image& image, const ColourList& colours)
{
if (colours.size() > mImpl->numTextures)
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given more colours than texture channels available.", __FUNCTION__);
uchar* data = new uchar[mImpl->width*mImpl->height*3];
for (size_t y = 0; y < mImpl->height; ++y)
{
for (size_t x = 0; x < mImpl->width; ++x)
{
ColourValue val (0, 0, 0);
for (size_t i = 0; i < colours.size(); ++i)
{
size_t m = i / mImpl->channels;
uint t = (uint) (i % mImpl->channels);
val += colours[i] * (float(mImpl->maps[m]->getValue((uint)x, (uint)y, t)) / 255);
}
size_t pos = (x + y * mImpl->width) * 3;
data[pos+0] = uchar(255*val.r);
data[pos+1] = uchar(255*val.g);
data[pos+2] = uchar(255*val.b);
}
}
image.loadDynamicImage(data, mImpl->width, mImpl->height, 1, PF_BYTE_RGB, true);
}
void SplattingManager::createBaseTexture(Image& image, size_t width, size_t height,
ImageList textures, float repeatX, float repeatZ)
{
if (textures.size() > mImpl->numTextures)
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given more textures than texture channels available.", "ET::SplattingManager::createBaseTexture");
// first resize the textures according to the desired output size and the repeat values
ushort scaleWidth = (ushort) (width / repeatX);
ushort scaleHeight = (ushort) (height / repeatZ);
for (ImageList::iterator it = textures.begin(); it != textures.end(); ++it)
it->resize(scaleWidth, scaleHeight);
// create the buffer to hold our generated base texture
uchar* data = new uchar[width*height*3];
size_t pos = 0;
for (size_t y = 0; y < height; ++y)
{
for (size_t x = 0; x < width; ++x)
{
ColourValue val (0,0,0);
int texX = (int) (x % scaleWidth);
int texY = (int) (y % scaleHeight);
for (size_t t = 0; t < textures.size(); ++t)
{
// get interpolated part of this texture at the current pixel
float weight = mImpl->interpolateWeight(x, y, width, height, t);
// get colour value of the texture image
ColourValue col = textures[t].getColourAt(texX, texY, 0);
// add to the pixel colour level
val += weight*col;
}
// write colour to our buffer
data[pos+0] = uchar(255*val.r);
data[pos+1] = uchar(255*val.g);
data[pos+2] = uchar(255*val.b);
pos += 3;
}
}
image.loadDynamicImage(data, width, height, 1, PF_BYTE_RGB, true);
}
Image createMinimap(const Image& colourMap, const Image& lightMap)
{
if (colourMap.getWidth() != lightMap.getWidth() || colourMap.getHeight() != lightMap.getHeight())
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Images must have the same dimensions.", __FUNCTION__);
uchar* data = new uchar[colourMap.getWidth()*colourMap.getHeight()*3];
for (size_t y = 0; y < colourMap.getWidth(); ++y)
{
for (size_t x = 0; x < colourMap.getHeight(); ++x)
{
ColourValue val = const_cast<Image&>(colourMap).getColourAt((uint)x, (uint)y, 0) * const_cast<Image&>(lightMap).getColourAt((uint)x, (uint)y, 0);
size_t pos = (x + y*colourMap.getWidth()) * 3;
data[pos+0] = uchar(255*val.r);
data[pos+1] = uchar(255*val.g);
data[pos+2] = uchar(255*val.b);
}
}
Image image;
image.loadDynamicImage(data, colourMap.getWidth(), colourMap.getHeight(), 1, PF_BYTE_RGB, true);
return image;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -