2010-04-15 22:46:06 +02:00
|
|
|
/*-------------------------------------------------------------------------------------
|
|
|
|
|
Copyright (c) 2006 John Judnich
|
|
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
-------------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "PropertyMaps.h"
|
|
|
|
|
#include "PagedGeometry.h"
|
|
|
|
|
|
|
|
|
|
#include <OgreRoot.h>
|
|
|
|
|
#include <OgrePrerequisites.h>
|
|
|
|
|
#include <OgrePixelFormat.h>
|
|
|
|
|
#include <OgreTexture.h>
|
|
|
|
|
#include <OgreTextureManager.h>
|
|
|
|
|
#include <OgreHardwarePixelBuffer.h>
|
|
|
|
|
#include <OgreRenderSystem.h>
|
|
|
|
|
#include <OgreString.h>
|
2008-02-23 Erik Hjortsberg <erik.hjortsberg@iteam.se>
* src/components/ogre/environment/pagedgeometry/include/BatchPage.h, src/components/ogre/environment/pagedgeometry/include/BatchedGeometry.h, src/components/ogre/environment/pagedgeometry/include/GrassLoader.h, src/components/ogre/environment/pagedgeometry/include/ImpostorPage.h, src/components/ogre/environment/pagedgeometry/include/PagedGeometry.h, src/components/ogre/environment/pagedgeometry/include/PropertyMaps.h, src/components/ogre/environment/pagedgeometry/include/StaticBillboardSet.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader2D.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader3D.h, src/components/ogre/environment/pagedgeometry/source/BatchPage.cpp, src/components/ogre/environment/pagedgeometry/source/BatchedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/GrassLoader.cpp, src/components/ogre/environment/pagedgeometry/source/ImpostorPage.cpp, src/components/ogre/environment/pagedgeometry/source/PagedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/PropertyMaps.cpp, src/components/ogre/environment/pagedgeometry/source/StaticBillboardSet.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader2D.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader3D.cpp: fixed include directives
2008-02-23 11:21:51 +00:00
|
|
|
#include <OgreStringConverter.h>
|
2008-02-02 Erik Hjortsberg <erik.hjortsberg@iteam.se>
* src/components/ogre/environment/Makefile.am, src/components/ogre/environment/pagedgeometry/GettingStarted.txt, src/components/ogre/environment/pagedgeometry/Makefile.am, src/components/ogre/environment/pagedgeometry/include/BatchPage.h, src/components/ogre/environment/pagedgeometry/include/BatchedGeometry.h, src/components/ogre/environment/pagedgeometry/include/GrassLoader.h, src/components/ogre/environment/pagedgeometry/include/ImpostorPage.h, src/components/ogre/environment/pagedgeometry/include/PagedGeometry.h, src/components/ogre/environment/pagedgeometry/include/PropertyMaps.h, src/components/ogre/environment/pagedgeometry/include/StaticBillboardSet.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader2D.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader3D.h, src/components/ogre/environment/pagedgeometry/source/BatchPage.cpp, src/components/ogre/environment/pagedgeometry/source/BatchedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/GrassLoader.cpp, src/components/ogre/environment/pagedgeometry/source/ImpostorPage.cpp, src/components/ogre/environment/pagedgeometry/source/PagedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/PropertyMaps.cpp, src/components/ogre/environment/pagedgeometry/source/StaticBillboardSet.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader2D.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader3D.cpp, configure.ac: added paging geometry enging, to be used for grass and trees and other parts of the the environment which will benefit from imposters and batching
2008-02-02 20:01:02 +00:00
|
|
|
using namespace Ogre;
|
|
|
|
|
|
2009-07-06 22:12:17 +02:00
|
|
|
namespace Forests {
|
2008-02-02 Erik Hjortsberg <erik.hjortsberg@iteam.se>
* src/components/ogre/environment/Makefile.am, src/components/ogre/environment/pagedgeometry/GettingStarted.txt, src/components/ogre/environment/pagedgeometry/Makefile.am, src/components/ogre/environment/pagedgeometry/include/BatchPage.h, src/components/ogre/environment/pagedgeometry/include/BatchedGeometry.h, src/components/ogre/environment/pagedgeometry/include/GrassLoader.h, src/components/ogre/environment/pagedgeometry/include/ImpostorPage.h, src/components/ogre/environment/pagedgeometry/include/PagedGeometry.h, src/components/ogre/environment/pagedgeometry/include/PropertyMaps.h, src/components/ogre/environment/pagedgeometry/include/StaticBillboardSet.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader2D.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader3D.h, src/components/ogre/environment/pagedgeometry/source/BatchPage.cpp, src/components/ogre/environment/pagedgeometry/source/BatchedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/GrassLoader.cpp, src/components/ogre/environment/pagedgeometry/source/ImpostorPage.cpp, src/components/ogre/environment/pagedgeometry/source/PagedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/PropertyMaps.cpp, src/components/ogre/environment/pagedgeometry/source/StaticBillboardSet.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader2D.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader3D.cpp, configure.ac: added paging geometry enging, to be used for grass and trees and other parts of the the environment which will benefit from imposters and batching
2008-02-02 20:01:02 +00:00
|
|
|
|
2009-05-16 01:09:46 +02:00
|
|
|
std::map<String, DensityMap*> DensityMap::selfList;
|
2008-02-02 Erik Hjortsberg <erik.hjortsberg@iteam.se>
* src/components/ogre/environment/Makefile.am, src/components/ogre/environment/pagedgeometry/GettingStarted.txt, src/components/ogre/environment/pagedgeometry/Makefile.am, src/components/ogre/environment/pagedgeometry/include/BatchPage.h, src/components/ogre/environment/pagedgeometry/include/BatchedGeometry.h, src/components/ogre/environment/pagedgeometry/include/GrassLoader.h, src/components/ogre/environment/pagedgeometry/include/ImpostorPage.h, src/components/ogre/environment/pagedgeometry/include/PagedGeometry.h, src/components/ogre/environment/pagedgeometry/include/PropertyMaps.h, src/components/ogre/environment/pagedgeometry/include/StaticBillboardSet.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader2D.h, src/components/ogre/environment/pagedgeometry/include/TreeLoader3D.h, src/components/ogre/environment/pagedgeometry/source/BatchPage.cpp, src/components/ogre/environment/pagedgeometry/source/BatchedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/GrassLoader.cpp, src/components/ogre/environment/pagedgeometry/source/ImpostorPage.cpp, src/components/ogre/environment/pagedgeometry/source/PagedGeometry.cpp, src/components/ogre/environment/pagedgeometry/source/PropertyMaps.cpp, src/components/ogre/environment/pagedgeometry/source/StaticBillboardSet.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader2D.cpp, src/components/ogre/environment/pagedgeometry/source/TreeLoader3D.cpp, configure.ac: added paging geometry enging, to be used for grass and trees and other parts of the the environment which will benefit from imposters and batching
2008-02-02 20:01:02 +00:00
|
|
|
|
2010-04-15 22:46:06 +02:00
|
|
|
DensityMap *DensityMap::load(const String &fileName, MapChannel channel)
|
|
|
|
|
{
|
|
|
|
|
//Load image
|
|
|
|
|
TexturePtr map = TextureManager::getSingleton().load(fileName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
|
|
|
|
|
|
|
|
|
//Copy image to pixelbox
|
|
|
|
|
return load(map, channel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DensityMap *DensityMap::load(TexturePtr texture, MapChannel channel)
|
|
|
|
|
{
|
|
|
|
|
const String key = texture->getName() + StringConverter::toString((int)channel);
|
|
|
|
|
|
|
|
|
|
std::map<String, DensityMap*>::iterator i;
|
|
|
|
|
i = selfList.find(key);
|
|
|
|
|
|
|
|
|
|
DensityMap *m;
|
|
|
|
|
if (i != selfList.end())
|
|
|
|
|
m = i->second;
|
|
|
|
|
else
|
|
|
|
|
m = new DensityMap(texture, channel);
|
|
|
|
|
|
|
|
|
|
++(m->refCount);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DensityMap::unload()
|
|
|
|
|
{
|
|
|
|
|
--refCount;
|
|
|
|
|
if (refCount == 0)
|
|
|
|
|
delete this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DensityMap::~DensityMap()
|
|
|
|
|
{
|
|
|
|
|
assert(pixels);
|
|
|
|
|
delete[] static_cast<uint8*>(pixels->data);
|
|
|
|
|
delete pixels;
|
|
|
|
|
|
|
|
|
|
//Remove self from selfList
|
|
|
|
|
selfList.erase(selfKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DensityMap::DensityMap(TexturePtr map, MapChannel channel)
|
|
|
|
|
{
|
2017-08-16 23:16:31 +02:00
|
|
|
assert(map);
|
2010-04-15 22:46:06 +02:00
|
|
|
filter = MAPFILTER_BILINEAR;
|
|
|
|
|
|
|
|
|
|
//Add self to selfList
|
|
|
|
|
selfKey = map->getName() + StringConverter::toString((int)channel);
|
|
|
|
|
selfList.insert(std::pair<String, DensityMap*>(selfKey, this));
|
|
|
|
|
refCount = 0;
|
|
|
|
|
|
|
|
|
|
//Get the texture buffer
|
|
|
|
|
HardwarePixelBufferSharedPtr buff = map->getBuffer();
|
|
|
|
|
|
|
|
|
|
//Prepare a PixelBox (8-bit greyscale) to receive the density values
|
|
|
|
|
pixels = new PixelBox(Box(0, 0, buff->getWidth(), buff->getHeight()), PF_BYTE_L);
|
|
|
|
|
pixels->data = new uint8[pixels->getConsecutiveSize()];
|
|
|
|
|
|
|
|
|
|
if (channel == CHANNEL_COLOR){
|
|
|
|
|
//Copy to the greyscale density map directly if no channel extraction is necessary
|
|
|
|
|
buff->blitToMemory(*pixels);
|
|
|
|
|
} else {
|
|
|
|
|
//If channel extraction is necessary, first convert to a PF_R8G8B8A8 format PixelBox
|
|
|
|
|
//This is necessary for the code below to properly extract the desired channel
|
|
|
|
|
PixelBox tmpPixels(Box(0, 0, buff->getWidth(), buff->getHeight()), PF_R8G8B8A8);
|
|
|
|
|
tmpPixels.data = new uint8[tmpPixels.getConsecutiveSize()];
|
|
|
|
|
buff->blitToMemory(tmpPixels);
|
|
|
|
|
|
|
|
|
|
//Pick out a channel from the pixel buffer
|
|
|
|
|
size_t channelOffset;
|
|
|
|
|
switch (channel){
|
|
|
|
|
case CHANNEL_RED: channelOffset = 3; break;
|
|
|
|
|
case CHANNEL_GREEN: channelOffset = 2; break;
|
|
|
|
|
case CHANNEL_BLUE: channelOffset = 1; break;
|
|
|
|
|
case CHANNEL_ALPHA: channelOffset = 0; break;
|
2014-08-12 22:08:04 +02:00
|
|
|
default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid channel", "GrassLayer::setDensityMap()"); break;
|
2010-04-15 22:46:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//And copy that channel into the density map
|
|
|
|
|
uint8 *inputPtr = (uint8*)tmpPixels.data + channelOffset;
|
|
|
|
|
uint8 *outputPtr = (uint8*)pixels->data;
|
|
|
|
|
uint8 *outputEndPtr = outputPtr + pixels->getConsecutiveSize();
|
|
|
|
|
while (outputPtr != outputEndPtr){
|
|
|
|
|
*outputPtr++ = *inputPtr;
|
|
|
|
|
inputPtr += 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Finally, delete the temporary PF_R8G8B8A8 pixel buffer
|
|
|
|
|
delete[] static_cast<uint8*>(tmpPixels.data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Returns the density map value at the given location
|
|
|
|
|
//Make sure a density map exists before calling this.
|
|
|
|
|
float DensityMap::_getDensityAt_Unfiltered(float x, float z, const TRect<Real> &mapBounds)
|
|
|
|
|
{
|
|
|
|
|
assert(pixels);
|
|
|
|
|
|
|
|
|
|
// Early out if the coordinates are outside map bounds.
|
|
|
|
|
if(x < mapBounds.left || x >= mapBounds.right || z < mapBounds.top || z >= mapBounds.bottom)
|
|
|
|
|
{
|
|
|
|
|
return 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 mapWidth = (uint32)pixels->getWidth();
|
|
|
|
|
uint32 mapHeight = (uint32)pixels->getHeight();
|
|
|
|
|
float boundsWidth = mapBounds.width();
|
|
|
|
|
float boundsHeight = mapBounds.height();
|
|
|
|
|
|
|
|
|
|
//Patch incorrect PixelBox::getWidth() in OpenGL mode
|
|
|
|
|
if (Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem")
|
|
|
|
|
--mapWidth;
|
|
|
|
|
|
|
|
|
|
uint32 xindex = mapWidth * (x - mapBounds.left) / boundsWidth;
|
|
|
|
|
uint32 zindex = mapHeight * (z - mapBounds.top) / boundsHeight;
|
|
|
|
|
|
|
|
|
|
uint8 *data = (uint8*)pixels->data;
|
|
|
|
|
float val = data[mapWidth * zindex + xindex] / 255.0f;
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Returns the density map value at the given location with bilinear filtering
|
|
|
|
|
//Make sure a density map exists before calling this.
|
|
|
|
|
float DensityMap::_getDensityAt_Bilinear(float x, float z, const TRect<Real> &mapBounds)
|
|
|
|
|
{
|
|
|
|
|
assert(pixels);
|
|
|
|
|
|
|
|
|
|
// Early out if the coordinates are outside map bounds.
|
|
|
|
|
if(x < mapBounds.left || x >= mapBounds.right || z < mapBounds.top || z >= mapBounds.bottom)
|
|
|
|
|
{
|
|
|
|
|
return 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 mapWidth = (uint32)pixels->getWidth();
|
|
|
|
|
uint32 mapHeight = (uint32)pixels->getHeight();
|
|
|
|
|
float boundsWidth = mapBounds.width();
|
|
|
|
|
float boundsHeight = mapBounds.height();
|
|
|
|
|
|
|
|
|
|
//Patch incorrect PixelBox::getWidth() in OpenGL mode
|
|
|
|
|
if (Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem")
|
|
|
|
|
--mapWidth;
|
|
|
|
|
|
|
|
|
|
float xIndexFloat = (mapWidth * (x - mapBounds.left) / boundsWidth) - 0.5f;
|
|
|
|
|
float zIndexFloat = (mapHeight * (z - mapBounds.top) / boundsHeight) - 0.5f;
|
|
|
|
|
|
|
|
|
|
uint32 xIndex = xIndexFloat;
|
|
|
|
|
uint32 zIndex = zIndexFloat;
|
2014-01-02 20:50:06 +01:00
|
|
|
if (xIndex >= mapWidth-1 || zIndex >= mapHeight-1)
|
2010-04-15 22:46:06 +02:00
|
|
|
return 0.0f;
|
|
|
|
|
|
|
|
|
|
float xRatio = xIndexFloat - xIndex;
|
|
|
|
|
float xRatioInv = 1 - xRatio;
|
|
|
|
|
float zRatio = zIndexFloat - zIndex;
|
|
|
|
|
float zRatioInv = 1 - zRatio;
|
|
|
|
|
|
|
|
|
|
uint8 *data = (uint8*)pixels->data;
|
|
|
|
|
|
|
|
|
|
float val11 = data[mapWidth * zIndex + xIndex] / 255.0f;
|
|
|
|
|
float val21 = data[mapWidth * zIndex + xIndex + 1] / 255.0f;
|
|
|
|
|
float val12 = data[mapWidth * ++zIndex + xIndex] / 255.0f;
|
|
|
|
|
float val22 = data[mapWidth * zIndex + xIndex + 1] / 255.0f;
|
|
|
|
|
|
|
|
|
|
float val1 = xRatioInv * val11 + xRatio * val21;
|
|
|
|
|
float val2 = xRatioInv * val12 + xRatio * val22;
|
|
|
|
|
|
|
|
|
|
float val = zRatioInv * val1 + zRatio * val2;
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
std::map<String, ColorMap*> ColorMap::selfList;
|
|
|
|
|
|
|
|
|
|
ColorMap *ColorMap::load(const String &fileName, MapChannel channel)
|
|
|
|
|
{
|
|
|
|
|
//Load image
|
|
|
|
|
TexturePtr map = TextureManager::getSingleton().load(fileName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
|
|
|
|
|
|
|
|
|
//Copy image to pixelbox
|
|
|
|
|
return load(map, channel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ColorMap *ColorMap::load(TexturePtr texture, MapChannel channel)
|
|
|
|
|
{
|
|
|
|
|
const String key = texture->getName() + StringConverter::toString((int)channel);
|
|
|
|
|
|
|
|
|
|
std::map<String, ColorMap*>::iterator i;
|
|
|
|
|
i = selfList.find(key);
|
|
|
|
|
|
|
|
|
|
ColorMap *m;
|
|
|
|
|
if (i != selfList.end())
|
|
|
|
|
m = i->second;
|
|
|
|
|
else
|
|
|
|
|
m = new ColorMap(texture, channel);
|
|
|
|
|
|
|
|
|
|
++(m->refCount);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ColorMap::unload()
|
|
|
|
|
{
|
|
|
|
|
--refCount;
|
|
|
|
|
if (refCount == 0)
|
|
|
|
|
delete this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ColorMap::~ColorMap()
|
|
|
|
|
{
|
|
|
|
|
assert(pixels);
|
|
|
|
|
delete[] static_cast<uint8*>(pixels->data);
|
|
|
|
|
delete pixels;
|
|
|
|
|
|
|
|
|
|
//Remove self from selfList
|
|
|
|
|
selfList.erase(selfKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ColorMap::ColorMap(TexturePtr map, MapChannel channel)
|
|
|
|
|
{
|
2017-08-16 23:16:31 +02:00
|
|
|
assert(map);
|
2010-04-15 22:46:06 +02:00
|
|
|
filter = MAPFILTER_BILINEAR;
|
|
|
|
|
|
|
|
|
|
//Add self to selfList
|
|
|
|
|
selfKey = map->getName() + StringConverter::toString((int)channel);
|
|
|
|
|
selfList.insert(std::pair<String, ColorMap*>(selfKey, this));
|
|
|
|
|
refCount = 0;
|
|
|
|
|
|
|
|
|
|
//Get the texture buffer
|
|
|
|
|
HardwarePixelBufferSharedPtr buff = map->getBuffer();
|
|
|
|
|
|
|
|
|
|
//Prepare a PixelBox (24-bit RGB) to receive the color values
|
2022-03-22 23:29:32 +01:00
|
|
|
VertexElementType format = VET_UBYTE4_NORM;
|
2010-04-15 22:46:06 +02:00
|
|
|
switch (format){
|
2022-03-19 21:24:27 +01:00
|
|
|
case VET_UBYTE4_NORM:
|
2010-04-15 22:46:06 +02:00
|
|
|
//OpenGL
|
|
|
|
|
pixels = new PixelBox(Box(0, 0, buff->getWidth(), buff->getHeight()), PF_A8B8G8R8);
|
|
|
|
|
//Patch for Ogre's incorrect blitToMemory() when copying from PF_L8 in OpenGL
|
|
|
|
|
if (buff->getFormat() == PF_L8)
|
|
|
|
|
channel = CHANNEL_RED;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2014-08-12 22:08:04 +02:00
|
|
|
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Unknown RenderSystem color format", "GrassLayer::setColorMap()");
|
2010-04-15 22:46:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pixels->data = new uint8[pixels->getConsecutiveSize()];
|
|
|
|
|
|
|
|
|
|
if (channel == CHANNEL_COLOR){
|
|
|
|
|
//Copy to the color map directly if no channel extraction is necessary
|
|
|
|
|
buff->blitToMemory(*pixels);
|
|
|
|
|
} else {
|
|
|
|
|
//If channel extraction is necessary, first convert to a PF_R8G8B8A8 format PixelBox
|
|
|
|
|
//This is necessary for the code below to properly extract the desired channel
|
|
|
|
|
PixelBox tmpPixels(Box(0, 0, buff->getWidth(), buff->getHeight()), PF_R8G8B8A8);
|
|
|
|
|
tmpPixels.data = new uint8[tmpPixels.getConsecutiveSize()];
|
|
|
|
|
buff->blitToMemory(tmpPixels);
|
|
|
|
|
|
|
|
|
|
//Pick out a channel from the pixel buffer
|
|
|
|
|
size_t channelOffset;
|
|
|
|
|
switch (channel){
|
|
|
|
|
case CHANNEL_RED: channelOffset = 3; break;
|
|
|
|
|
case CHANNEL_GREEN: channelOffset = 2; break;
|
|
|
|
|
case CHANNEL_BLUE: channelOffset = 1; break;
|
|
|
|
|
case CHANNEL_ALPHA: channelOffset = 0; break;
|
2014-08-12 22:08:04 +02:00
|
|
|
default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid channel", "ColorMap::ColorMap()"); break;
|
2010-04-15 22:46:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//And copy that channel into the density map
|
|
|
|
|
uint8 *inputPtr = (uint8*)tmpPixels.data + channelOffset;
|
|
|
|
|
uint8 *outputPtr = (uint8*)pixels->data;
|
|
|
|
|
uint8 *outputEndPtr = outputPtr + pixels->getConsecutiveSize();
|
|
|
|
|
while (outputPtr != outputEndPtr){
|
|
|
|
|
*outputPtr++ = *inputPtr;
|
|
|
|
|
*outputPtr++ = *inputPtr;
|
|
|
|
|
*outputPtr++ = *inputPtr;
|
|
|
|
|
*outputPtr++ = 0xFF; //Full alpha
|
|
|
|
|
inputPtr += 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Finally, delete the temporary PF_R8G8B8A8 pixel buffer
|
|
|
|
|
delete[] static_cast<uint8*>(tmpPixels.data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Returns the color map value at the given location
|
|
|
|
|
uint32 ColorMap::_getColorAt(float x, float z, const TRect<Real> &mapBounds)
|
|
|
|
|
{
|
|
|
|
|
assert(pixels);
|
|
|
|
|
|
|
|
|
|
// Early out if the coordinates are outside map bounds.
|
|
|
|
|
if(x < mapBounds.left || x >= mapBounds.right || z < mapBounds.top || z >= mapBounds.bottom)
|
|
|
|
|
{
|
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 mapWidth = (uint32)pixels->getWidth();
|
|
|
|
|
uint32 mapHeight = (uint32)pixels->getHeight();
|
|
|
|
|
float boundsWidth = mapBounds.width();
|
|
|
|
|
float boundsHeight = mapBounds.height();
|
|
|
|
|
|
|
|
|
|
uint32 xindex = mapWidth * (x - mapBounds.left) / boundsWidth;
|
|
|
|
|
uint32 zindex = mapHeight * (z - mapBounds.top) / boundsHeight;
|
|
|
|
|
|
|
|
|
|
uint32 *data = (uint32*)pixels->data;
|
|
|
|
|
return data[mapWidth * zindex + xindex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 ColorMap::_interpolateColor(uint32 color1, uint32 color2, float ratio, float ratioInv)
|
|
|
|
|
{
|
|
|
|
|
uint8 a1, b1, c1, d1;
|
|
|
|
|
a1 = (color1 & 0xFF);
|
|
|
|
|
b1 = (color1 >> 8 & 0xFF);
|
|
|
|
|
c1 = (color1 >> 16 & 0xFF);
|
|
|
|
|
d1 = (color1 >> 24 & 0xFF);
|
|
|
|
|
|
|
|
|
|
uint8 a2, b2, c2, d2;
|
|
|
|
|
a2 = (color2 & 0xFF);
|
|
|
|
|
b2 = (color2 >> 8 & 0xFF);
|
|
|
|
|
c2 = (color2 >> 16 & 0xFF);
|
|
|
|
|
d2 = (color2 >> 24 & 0xFF);
|
|
|
|
|
|
|
|
|
|
uint8 a, b, c, d;
|
|
|
|
|
a = ratioInv * a1 + ratio * a2;
|
|
|
|
|
b = ratioInv * b1 + ratio * b2;
|
|
|
|
|
c = ratioInv * c1 + ratio * c2;
|
|
|
|
|
d = ratioInv * d1 + ratio * d2;
|
|
|
|
|
|
|
|
|
|
uint32 clr = a | (b << 8) | (c << 16) | (d << 24);
|
|
|
|
|
return clr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 ColorMap::_getColorAt_Bilinear(float x, float z, const TRect<Real> &mapBounds)
|
|
|
|
|
{
|
|
|
|
|
assert(pixels);
|
|
|
|
|
|
|
|
|
|
// Early out if the coordinates are outside map bounds.
|
|
|
|
|
if(x < mapBounds.left || x >= mapBounds.right || z < mapBounds.top || z >= mapBounds.bottom)
|
|
|
|
|
{
|
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 mapWidth = (uint32)pixels->getWidth();
|
|
|
|
|
uint32 mapHeight = (uint32)pixels->getHeight();
|
|
|
|
|
float boundsWidth = mapBounds.width();
|
|
|
|
|
float boundsHeight = mapBounds.height();
|
|
|
|
|
|
|
|
|
|
float xIndexFloat = (mapWidth * (x - mapBounds.left) / boundsWidth) - 0.5f;
|
|
|
|
|
float zIndexFloat = (mapHeight * (z - mapBounds.top) / boundsHeight) - 0.5f;
|
|
|
|
|
|
|
|
|
|
uint32 xIndex = xIndexFloat;
|
|
|
|
|
uint32 zIndex = zIndexFloat;
|
2014-01-02 20:50:06 +01:00
|
|
|
if (xIndex > mapWidth-1 || zIndex > mapHeight-1)
|
2010-04-15 22:46:06 +02:00
|
|
|
return 0xFFFFFFFF;
|
|
|
|
|
|
|
|
|
|
float xRatio = xIndexFloat - xIndex;
|
|
|
|
|
float xRatioInv = 1 - xRatio;
|
|
|
|
|
float zRatio = zIndexFloat - zIndex;
|
|
|
|
|
float zRatioInv = 1 - zRatio;
|
|
|
|
|
|
|
|
|
|
uint32 *data = (uint32*)pixels->data;
|
|
|
|
|
|
|
|
|
|
uint32 val11 = data[mapWidth * zIndex + xIndex];
|
|
|
|
|
uint32 val21 = data[mapWidth * zIndex + xIndex + 1];
|
|
|
|
|
uint32 val12 = data[mapWidth * ++zIndex + xIndex];
|
|
|
|
|
uint32 val22 = data[mapWidth * zIndex + xIndex + 1];
|
|
|
|
|
|
|
|
|
|
uint32 val1 = _interpolateColor(val11, val21, xRatio, xRatioInv);
|
|
|
|
|
uint32 val2 = _interpolateColor(val12, val22, xRatio, xRatioInv);
|
|
|
|
|
|
|
|
|
|
uint32 val = _interpolateColor(val1, val2, zRatio, zRatioInv);
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
}
|