[Python-ogre-commit] SF.net SVN: python-ogre: [408] trunk/python-ogre
Brought to you by:
andy_miller,
roman_yakovenko
|
From: <and...@us...> - 2007-10-05 04:16:05
|
Revision: 408
http://python-ogre.svn.sourceforge.net/python-ogre/?rev=408&view=rev
Author: andy_miller
Date: 2007-10-04 21:16:07 -0700 (Thu, 04 Oct 2007)
Log Message:
-----------
Initial version of Editable Terrain wrapper -- thanks Dermont
Updated QuickGUI
Modified Paths:
--------------
trunk/python-ogre/PythonOgreConfig_nt.py
trunk/python-ogre/PythonOgreConfig_posix.py
trunk/python-ogre/SConstruct
trunk/python-ogre/ThirdParty/quickgui/QuickGUIBorder.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIBorder.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIButton.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIButton.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIComboBox.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIComboBox.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIHorizontalScrollBar.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIHorizontalScrollBar.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIHorizontalTrackBar.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIHorizontalTrackBar.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIImage.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIImage.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUILabel.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUILabel.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIList.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIList.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIListItem.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIListItem.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIManager.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIManager.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIMenu.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIMenu.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIMenuList.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIMenuList.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUINStateButton.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUINStateButton.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIPanel.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIPanel.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIProgressBar.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIProgressBar.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIQuad.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIQuad.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIQuadContainer.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIScrollPane.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIScrollPane.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUISheet.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUISheet.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUISize.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIText.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIText.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUITextBox.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUITextBox.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUITitleBar.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUITitleBar.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIVerticalScrollBar.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIVerticalScrollBar.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIVerticalTrackBar.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIVerticalTrackBar.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIWidget.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIWidget.h
trunk/python-ogre/ThirdParty/quickgui/QuickGUIWindow.cpp
trunk/python-ogre/ThirdParty/quickgui/QuickGUIWindow.h
trunk/python-ogre/environment.py
trunk/python-ogre/setup.py
Added Paths:
-----------
trunk/python-ogre/ThirdParty/et/
trunk/python-ogre/ThirdParty/et/ETBrush.cpp
trunk/python-ogre/ThirdParty/et/ETBrush.h
trunk/python-ogre/ThirdParty/et/ETIndexHandler.cpp
trunk/python-ogre/ThirdParty/et/ETLightmap.cpp
trunk/python-ogre/ThirdParty/et/ETLoadSaveHeightmap.cpp
trunk/python-ogre/ThirdParty/et/ETPrerequisites.h
trunk/python-ogre/ThirdParty/et/ETSplattingManager.cpp
trunk/python-ogre/ThirdParty/et/ETSplattingManager.h
trunk/python-ogre/ThirdParty/et/ETTerrainInfo.cpp
trunk/python-ogre/ThirdParty/et/ETTerrainInfo.h
trunk/python-ogre/ThirdParty/et/ETTerrainManager.cpp
trunk/python-ogre/ThirdParty/et/ETTerrainManager.h
trunk/python-ogre/ThirdParty/et/ETTile.cpp
trunk/python-ogre/ThirdParty/et/Impl/
trunk/python-ogre/ThirdParty/et/Impl/ETIndexHandler.h
trunk/python-ogre/ThirdParty/et/Impl/ETOptions.h
trunk/python-ogre/ThirdParty/et/Impl/ETTerrainImpl.h
trunk/python-ogre/ThirdParty/et/Impl/ETTile.h
trunk/python-ogre/code_generators/et/
trunk/python-ogre/code_generators/et/customization_data.py
trunk/python-ogre/code_generators/et/generate_code.py
trunk/python-ogre/code_generators/et/hand_made_wrappers.py
trunk/python-ogre/code_generators/et/python_et.h
trunk/python-ogre/code_generators/et/python_et_aliases.h
trunk/python-ogre/code_generators/et/python_et_sizeof.h
trunk/python-ogre/demos/et/
trunk/python-ogre/demos/et/CEGUI_framework.py
trunk/python-ogre/demos/et/Demo_CEGUI_ET.py
trunk/python-ogre/demos/et/SampleFramework.py
trunk/python-ogre/demos/et/minimap.material
trunk/python-ogre/demos/et/minimap.overlay
trunk/python-ogre/demos/et/plugins.cfg
trunk/python-ogre/demos/et/resources.cfg
Modified: trunk/python-ogre/PythonOgreConfig_nt.py
===================================================================
--- trunk/python-ogre/PythonOgreConfig_nt.py 2007-10-03 06:30:20 UTC (rev 407)
+++ trunk/python-ogre/PythonOgreConfig_nt.py 2007-10-05 04:16:07 UTC (rev 408)
@@ -41,6 +41,7 @@
PATH_betagui= os.path.join(PATH_THIRDPARTY,'betagui')
PATH_ogredshow = os.path.join(PATH_THIRDPARTY,'dshow')
PATH_plib = os.path.join(PATH_THIRDPARTY, 'plib')
+PATH_et = os.path.join(PATH_THIRDPARTY, 'et')
PATH_ogrevideoffmpeg = os.path.join(PATH_THIRDPARTY,'ffmpeg')
PATH_NxOgre= os.path.join(BASE_DIR, 'nxogre/NxOgre')
PATH_Bullet= os.path.join(BASE_DIR, 'bullet-2.62')
Modified: trunk/python-ogre/PythonOgreConfig_posix.py
===================================================================
--- trunk/python-ogre/PythonOgreConfig_posix.py 2007-10-03 06:30:20 UTC (rev 407)
+++ trunk/python-ogre/PythonOgreConfig_posix.py 2007-10-05 04:16:07 UTC (rev 408)
@@ -48,6 +48,8 @@
PATH_betagui= os.path.join(PATH_THIRDPARTY,'betagui')
PATH_ogredshow = os.path.join(PATH_THIRDPARTY,'dshow')
PATH_plib = os.path.join(PATH_THIRDPARTY, 'plib')
+PATH_et = os.path.join(PATH_THIRDPARTY, 'et')
+
PATH_ogrevideoffmpeg = os.path.join(PATH_THIRDPARTY,'ffmpeg')
PATH_NxOgre= os.path.join(BASE_DIR, 'nxogre/NxOgre')
PATH_Bullet= os.path.join(BASE_DIR, 'bullet-2.62')
Modified: trunk/python-ogre/SConstruct
===================================================================
--- trunk/python-ogre/SConstruct 2007-10-03 06:30:20 UTC (rev 407)
+++ trunk/python-ogre/SConstruct 2007-10-05 04:16:07 UTC (rev 408)
@@ -91,11 +91,11 @@
possible_projects = ['ogre' , 'ois', 'ogrerefapp', 'ogrenewt', 'cegui', 'ode',\
'ogreode', 'ogreal', 'quickgui', 'opcode', 'nxogre', 'bullet', 'physx', 'betagui','theora',\
'ogrevideoffmpeg', 'ogredshow', 'plib', 'ogrebulletc', 'ogrebulletd',
- 'ogreforests' ] # , 'raknet', 'navi',
+ 'ogreforests', 'et' ] # , 'raknet', 'navi',
default_projects = ['ogre' , 'ois', 'ogrerefapp', 'ogrenewt', 'cegui', 'ode',\
'ogreode', 'ogreal', 'quickgui', 'opcode', 'nxogre', 'bullet', 'physx', 'betagui','theora',\
'ogrevideoffmpeg', 'ogredshow', 'plib', 'ogrebulletc', 'ogrebulletd',
- 'ogreforests' ] # 'navi',
+ 'ogreforests', 'et' ] # 'navi',
# This lets you call scons like: 'scons PROJECTS=ogre,cegui'
opts = Options('custom.py')
Added: trunk/python-ogre/ThirdParty/et/ETBrush.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETBrush.cpp (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETBrush.cpp 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,131 @@
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "ETBrush.h"
+
+#include <OgreImage.h>
+#include <OgreException.h>
+
+using namespace std;
+using namespace Ogre;
+using Ogre::uint;
+using Ogre::ushort;
+
+namespace ET
+{
+ Brush::Brush()
+ : mWidth(0), mHeight(0), mBrushArray(0)
+ {
+ }
+
+ Brush::Brush(const float* brush, size_t width, size_t height)
+ : mWidth(width), mHeight(height)
+ {
+ mBrushArray = new float[width*height];
+ memcpy(mBrushArray, brush, width*height*sizeof(float));
+ }
+
+ Brush::Brush(const vector<float>& brush, size_t width, size_t height)
+ : mWidth(width), mHeight(height)
+ {
+ mBrushArray = new float[width*height];
+ copy(brush.begin(), brush.end(), mBrushArray);
+ }
+
+ Brush::Brush(const Brush& other)
+ : mWidth(other.mWidth), mHeight(other.mHeight)
+ {
+ mBrushArray = new float[mWidth*mHeight];
+ memcpy(mBrushArray, other.mBrushArray, mWidth*mHeight*sizeof(float));
+ }
+
+ Brush::~Brush()
+ {
+ delete[] mBrushArray;
+ }
+
+
+ Brush& Brush::operator=(const Brush& other)
+ {
+ Brush tmp (other);
+ tmp.swap(*this);
+ return *this;
+ }
+
+ void Brush::swap(Brush& other)
+ {
+ std::swap(mWidth, other.mWidth);
+ std::swap(mHeight, other.mHeight);
+ std::swap(mBrushArray, other.mBrushArray);
+ }
+
+ Brush loadBrushFromImage(const Image& image)
+ {
+ size_t width = image.getWidth();
+ size_t height = image.getHeight();
+ vector<float> brush (width*height);
+
+ // determine the bytes per pixel used in the image
+ int bpp = int(image.getSize() / (width*height));
+ /*switch (image.getFormat())
+ {
+ case PF_BYTE_A: bpp = 1; break;
+ case PF_BYTE_LA: case PF_L16: bpp = 2; break;
+ case PF_BYTE_RGB: case PF_BYTE_BGR: bpp = 3; break;
+ case PF_BYTE_RGBA: case PF_BYTE_BGRA: bpp = 4; break;
+ default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Don't know what to do with the given image format, sorry.", "loadBrushFromImage");
+ }*/
+ // from the bpp, calculate the relevant max value for one pixel
+ uint maxValue = (1 << (bpp*8)) - 1;
+
+ // now fill the brush array
+ const uchar* imageData = image.getData();
+ for (size_t i = 0; i < brush.size(); ++i)
+ {
+ uint val = 0;
+ memcpy(&val, imageData, bpp);
+ imageData += bpp;
+ brush[i] = float(val) / maxValue;
+ }
+
+ return Brush(brush, width, height);
+ }
+
+
+ void saveBrushToImage(const Brush& brush, Image& image)
+ {
+ // save brush as a 16bit grayscale image
+ ushort* data = new ushort[brush.getWidth()*brush.getHeight()];
+ for (size_t x = 0; x < brush.getWidth(); ++x)
+ for (size_t y = 0; y < brush.getHeight(); ++y)
+ data[y*brush.getWidth() + x] = ushort(brush.at(x, y) * 0xffff);
+
+ // pass the data to the image, image takes over ownership
+ image.loadDynamicImage((uchar*)data, brush.getWidth(), brush.getHeight(), 1, PF_L16, true);
+ }
+}
Added: trunk/python-ogre/ThirdParty/et/ETBrush.h
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETBrush.h (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETBrush.h 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,94 @@
+#ifndef __ETBRUSH_H__
+#define __ETBRUSH_H__
+
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "ETPrerequisites.h"
+
+#include <vector>
+
+// forward declarations
+namespace Ogre
+{
+ class Image;
+}
+
+
+namespace ET
+{
+ /** This class represents a brush used to deform terrain or edit splatting coverage */
+ class _ETManagerExport Brush
+ {
+ public:
+ /** Default constructor */
+ Brush();
+ /** Constructs a brush from a given array of floats */
+ Brush(const float* brush, size_t width, size_t height);
+ /** Constructs a brush from a given vector of floats */
+ Brush(const std::vector<float>& brush, size_t width, size_t height);
+ /** Copy constructor */
+ Brush(const Brush& other);
+ ~Brush();
+
+ /** Copy assignment */
+ Brush& operator=(const Brush& other);
+
+ size_t getWidth() const { return mWidth; }
+ size_t getHeight() const { return mHeight; }
+
+ /** Access to the brush array */
+ float& at(size_t x, size_t y)
+ {
+ return mBrushArray[x + y*mWidth];
+ }
+ /** Const access to the brush array */
+ const float at(size_t x, size_t y) const
+ {
+ return mBrushArray[x + y*mWidth];
+ }
+
+ /** Exception-safe swap function */
+ void swap(Brush& other);
+
+ private:
+ /** The actual brush array containing the brush values */
+ float* mBrushArray; // would have used vector<float>, but gives warnings with dll export
+ /** The brush's dimensions */
+ size_t mWidth, mHeight;
+ };
+
+ /** Loads a brush from a grayscale image */
+ Brush _ETManagerExport loadBrushFromImage(const Ogre::Image& image);
+
+ /** Saves a brush to a grayscale image */
+ void _ETManagerExport saveBrushToImage(const Brush& brush, Ogre::Image& image);
+}
+
+
+#endif
Added: trunk/python-ogre/ThirdParty/et/ETIndexHandler.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETIndexHandler.cpp (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETIndexHandler.cpp 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,257 @@
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "Impl/ETIndexHandler.h"
+
+#include <OgreHardwareBufferManager.h>
+
+using namespace Ogre;
+using Ogre::uint;
+using Ogre::ushort;
+
+namespace ET
+{
+ namespace Impl
+ {
+ IndexHandler::IndexHandler(size_t tileSize, unsigned int maxLOD)
+ : mTileSize(tileSize), mIndexes(maxLOD)
+ {
+ }
+
+ IndexHandler::~IndexHandler()
+ {
+ for (size_t i = 0; i < mIndexes.size(); ++i)
+ {
+ for (IndexMap::iterator it = mIndexes[i].begin(); it != mIndexes[i].end(); ++it)
+ delete it->second;
+ }
+ }
+
+ IndexData* IndexHandler::requestIndexData(unsigned int lod, unsigned int neighbourState)
+ {
+ assert(lod < mIndexes.size() && "Requested unexpected LOD level");
+ IndexData* data;
+ IndexMap::iterator it = mIndexes[lod].find(neighbourState);
+ if (it != mIndexes[lod].end())
+ data = it->second;
+ else
+ {
+ data = createIndexes(lod, neighbourState);
+ mIndexes[lod].insert(IndexMap::value_type(neighbourState, data));
+ }
+ return data;
+ }
+
+
+ unsigned short IndexHandler::index(size_t x, size_t z) const
+ {
+ return ushort(x + z * mTileSize);
+ }
+
+
+ IndexData* IndexHandler::createIndexes(unsigned int lod, unsigned int neighbourState)
+ {
+ unsigned int numIndexes = 0;
+ unsigned int step = 1 << lod;
+
+ unsigned int northLOD = neighbourState >> 24;
+ unsigned int eastLOD = (neighbourState >> 16) & 0xFF;
+ unsigned int southLOD = (neighbourState >> 8) & 0xFF;
+ unsigned int westLOD = neighbourState & 0xFF;
+ unsigned int north = northLOD ? step : 0;
+ unsigned int east = eastLOD ? step : 0;
+ unsigned int south = southLOD ? step : 0;
+ unsigned int west = westLOD ? step : 0;
+
+ size_t newLength = (mTileSize/step) * (mTileSize/step) * 2 * 2 * 2;
+ IndexData* indexData = new IndexData;
+ indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(
+ HardwareIndexBuffer::IT_16BIT, newLength, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+ unsigned short* pIdx = static_cast<unsigned short*>(indexData->indexBuffer->lock(
+ 0, indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD));
+
+ // go over all vertices and combine them to triangles in trilist format.
+ // leave out the edges if we need to stitch those in case over lower LOD at the
+ // neighbour.
+ for (unsigned int j = north; j < mTileSize-1 - south; j += step)
+ {
+ for (unsigned int i = west; i < mTileSize-1 - east; i += step)
+ {
+ // triangles
+ *pIdx++ = index(i, j);
+ *pIdx++ = index(i, j+step);
+ *pIdx++ = index(i+step, j);
+
+ *pIdx++ = index(i, j+step);
+ *pIdx++ = index(i+step, j+step);
+ *pIdx++ = index(i+step, j);
+
+ numIndexes += 6;
+ }
+ }
+
+ // stitching edges to neighbours where needed
+ if (northLOD)
+ numIndexes += stitchEdge(NORTH, lod, northLOD, westLOD > 0, eastLOD > 0, &pIdx);
+ if (eastLOD)
+ numIndexes += stitchEdge(EAST, lod, eastLOD, northLOD > 0, southLOD > 0, &pIdx);
+ if (southLOD)
+ numIndexes += stitchEdge(SOUTH, lod, southLOD, eastLOD > 0, westLOD > 0, &pIdx);
+ if (westLOD)
+ numIndexes += stitchEdge(WEST, lod, westLOD, southLOD > 0, northLOD > 0, &pIdx);
+
+ indexData->indexBuffer->unlock();
+ indexData->indexCount = numIndexes;
+ indexData->indexStart = 0;
+
+ return indexData;
+ }
+
+
+ int IndexHandler::stitchEdge(int direction, unsigned int hiLOD, unsigned int loLOD, bool omitFirstTri,
+ bool omitLastTri, unsigned short** ppIdx)
+ {
+ assert(loLOD > hiLOD);
+
+ // code taken from Ogre's TSM
+
+ unsigned short* pIdx = *ppIdx;
+
+ int step = 1 << hiLOD;
+ int superstep = 1 << loLOD;
+ int halfsuperstep = superstep >> 1;
+ int rowstep = 0;
+ size_t startx = 0, starty = 0, endx = 0;
+ bool horizontal = false;
+ switch (direction)
+ {
+ case NORTH:
+ startx = starty = 0;
+ endx = mTileSize - 1;
+ rowstep = step;
+ horizontal = true;
+ break;
+
+ case SOUTH:
+ startx = starty = mTileSize-1;
+ endx = 0;
+ rowstep = -step;
+ step = -step;
+ superstep = -superstep;
+ halfsuperstep = -halfsuperstep;
+ horizontal = true;
+ break;
+
+ case EAST:
+ startx = 0;
+ endx = mTileSize-1;
+ starty = mTileSize-1;
+ rowstep = -step;
+ horizontal = false;
+ break;
+
+ case WEST:
+ startx = mTileSize-1;
+ endx = 0;
+ starty = 0;
+ rowstep = step;
+ step = -step;
+ superstep = -superstep;
+ halfsuperstep = -halfsuperstep;
+ horizontal = false;
+ break;
+ }
+
+ unsigned int numIndexes = 0;
+
+ for (size_t j = startx; j != endx; j += superstep)
+ {
+ int k;
+ for (k = 0; k != halfsuperstep; k += step)
+ {
+ size_t jk = j + k;
+ if (j != startx || k != 0 || !omitFirstTri)
+ {
+ if (horizontal)
+ {
+ *pIdx++ = index(j, starty);
+ *pIdx++ = index(jk, starty + rowstep);
+ *pIdx++ = index(jk + step, starty + rowstep);
+ }
+ else
+ {
+ *pIdx++ = index(starty, j);
+ *pIdx++ = index(starty+rowstep, jk);
+ *pIdx++ = index(starty+rowstep, jk+step);
+ }
+ numIndexes += 3;
+ }
+ }
+
+ if (horizontal)
+ {
+ *pIdx++ = index(j, starty);
+ *pIdx++ = index(j+halfsuperstep, starty+rowstep);
+ *pIdx++ = index(j+superstep, starty);
+ }
+ else
+ {
+ *pIdx++ = index(starty, j);
+ *pIdx++ = index(starty+rowstep, j+halfsuperstep);
+ *pIdx++ = index(starty, j+superstep);
+ }
+ numIndexes += 3;
+
+ for (k = halfsuperstep; k != superstep; k += step)
+ {
+ size_t jk = j + k;
+ if (j != endx - superstep || k != superstep - step || !omitLastTri)
+ {
+ if (horizontal)
+ {
+ *pIdx++ = index(j+superstep, starty);
+ *pIdx++ = index(jk, starty+rowstep);
+ *pIdx++ = index(jk+step, starty+rowstep);
+ }
+ else
+ {
+ *pIdx++ = index(starty, j+superstep);
+ *pIdx++ = index(starty+rowstep, jk);
+ *pIdx++ = index(starty+rowstep, jk+step);
+ }
+ numIndexes += 3;
+ }
+ }
+ }
+
+ *ppIdx = pIdx;
+
+ return numIndexes;
+ }
+ }
+}
Added: trunk/python-ogre/ThirdParty/et/ETLightmap.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETLightmap.cpp (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETLightmap.cpp 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,327 @@
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "ETTerrainInfo.h"
+#include <OgreImage.h>
+#include <OgreColourValue.h>
+#include <OgreVector3.h>
+#include <OgreAxisAlignedBox.h>
+#include <OgreException.h>
+
+using namespace Ogre;
+using namespace std;
+
+namespace ET
+{
+ namespace Impl
+ {
+ /** Add terrain shadows to lightmap. */
+ void addTerrainShadowsToLightmap(uchar* lightMap, const TerrainInfo& info,
+ size_t width, size_t height, const Vector3& lightDir, const ColourValue& ambient)
+ {
+ // algorithm for ray traced shadow map as described here:
+ // http://gpwiki.org/index.php/Faster_Ray_Traced_Terrain_Shadow_Maps
+ size_t i, j;
+ size_t *x, *z;
+ int iDir, jDir;
+ size_t iSize, jSize;
+ float lDirXAbs = fabs(lightDir.x);
+ float lDirZAbs = fabs(lightDir.z);
+
+ // based on the direction of light, decide in which order to traverse
+ // to speed up calculations
+ if (lDirXAbs > lDirZAbs)
+ {
+ z = &i;
+ x = &j;
+ iSize = height;
+ jSize = width;
+ if (lightDir.x < 0)
+ {
+ j = jSize - 1;
+ jDir = -1;
+ }
+ else
+ {
+ j = 0;
+ jDir = 1;
+ }
+ if (lightDir.z < 0)
+ {
+ i = iSize - 1;
+ iDir = -1;
+ }
+ else
+ {
+ i = 0;
+ iDir = 1;
+ }
+ }
+ else
+ {
+ x = &i;
+ z = &j;
+ jSize = height;
+ iSize = width;
+ if (lightDir.x < 0)
+ {
+ i = iSize - 1;
+ iDir = -1;
+ }
+ else
+ {
+ i = 0;
+ iDir = 1;
+ }
+ if (lightDir.z < 0)
+ {
+ j = jSize - 1;
+ jDir = -1;
+ }
+ else
+ {
+ j = 0;
+ jDir = 1;
+ }
+ }
+
+ // calculate the step size to use
+ AxisAlignedBox extents = info.getExtents();
+ Vector3 pos = extents.getMinimum();
+ Vector3 step = extents.getMaximum() - extents.getMinimum();
+ step.x /= width;
+ step.z /= height;
+
+ float* flagMap = new float[width*height];
+ memset(flagMap, 0, width*height*sizeof(float));
+
+ while (1)
+ {
+ while (1)
+ {
+ // travel along terrain until we:
+ // (1) intersect another point
+ // (2) find another point with previous collision data
+ // (3) reach the edge of the map
+ float px = *x;
+ float pz = *z;
+ size_t index = (*z) * width + (*x);
+
+ // travel along ray
+ while (1)
+ {
+ px -= lightDir.x;
+ pz -= lightDir.z;
+
+ // check if we've reached the boundary
+ if (px < 0 || px >= width || pz < 0 || pz >= height)
+ {
+ flagMap[index] = -1.0f;
+ break;
+ }
+
+ // calculate interpolated values
+ int x0 = (int)floor(px);
+ int x1 = (int)ceil(px);
+ int z0 = (int)floor(pz);
+ int z1 = (int)ceil(pz);
+
+ float du = px - x0;
+ float dv = pz - z0;
+ float invdu = 1.0 - du;
+ float invdv = 1.0 - dv;
+ float w0 = invdu * invdv;
+ float w1 = invdu * dv;
+ float w2 = du * invdv;
+ float w3 = du * dv;
+
+ // get interpolated height at position
+ Vector3 curPos = pos + Vector3(px*step.x, 0, pz*step.z);
+ float ipHeight = info.getHeightAt(curPos.x, curPos.z) - pos.y;
+
+ // compute interpolated flagmap value
+ float pixels[4];
+ pixels[0] = flagMap[z0*width+x0];
+ pixels[1] = flagMap[z1*width+x0];
+ pixels[2] = flagMap[z0*width+x1];
+ pixels[3] = flagMap[z1*width+x1];
+ float ipFlag = w0*pixels[0] + w1*pixels[1] + w2*pixels[2] + w3*pixels[3];
+
+ // get distance from original point to current point
+ float realXDist = (px - *x) * step.x;
+ float realZDist = (pz - *z) * step.z;
+ float distance = sqrt(realXDist*realXDist + realZDist*realZDist);
+
+ // calculate ray height at current point
+ float height = info.getHeightAt(pos.x + (*x)*step.x, pos.z + (*z)*step.z) - pos.y - lightDir.y*distance;
+
+ // check intersection with either terrain or flagMap
+ // if ipHeight < ipFlag check against flagMap value
+ float val = (ipHeight < ipFlag ? ipFlag : ipHeight);
+ if (height < val)
+ {
+ // point in shadow
+ flagMap[index] = val - height;
+ lightMap[index*3+0] = (uchar) (255*ambient.r);
+ lightMap[index*3+1] = (uchar) (255*ambient.g);
+ lightMap[index*3+2] = (uchar) (255*ambient.b);
+ break;
+ }
+
+ // check if pixel we moved to is unshadowed
+ // since the flagMap value is interpolated, we use an epsilon value to check
+ // if it's close enough to -1 to indicate non-shadow
+ const float epsilon = 0.5f;
+ if (ipFlag < -1.0f+epsilon && ipFlag > -1.0f-epsilon)
+ {
+ flagMap[index] = -1.0f;
+ break;
+ }
+ }
+
+ // update inner loop
+ j += jDir;
+ if (j >= jSize) // due to size_t, if j < 0, will wrap around and be > jSize ;)
+ break;
+ }
+
+ // reset inner loop starting point
+ if (jDir < 0)
+ j = jSize-1;
+ else
+ j = 0;
+
+ // update outer loop variable
+ i += iDir;
+ if (i >= iSize)
+ break;
+
+ }
+
+ delete[] flagMap;
+ }
+
+
+ void boxFilterLightmap(uchar* lightMap, size_t width, size_t height)
+ {
+ // this box filter assigns to a pixel the average of itself and all
+ // surrounding pixels in a 5x5 grid
+ for (size_t i = 0; i < width; ++i)
+ {
+ for (size_t j = 0; j < height; ++j)
+ {
+ int col[3] = {0, 0, 0};
+ // sum up all colours from 5x5 grid around the current pixel
+ int cnt = 0;
+ for (int x = -1; x <= 1; ++x)
+ {
+ if ((int)i+x < 0 || i+x >= width)
+ continue;
+ for (int y = -1; y <= 1; ++y)
+ {
+ if ((int)j+y < 0 || j+y >= height)
+ continue;
+ size_t index = (i+x + (j+y)*width)*3;
+ col[0] += lightMap[index+0];
+ col[1] += lightMap[index+1];
+ col[2] += lightMap[index+2];
+ ++cnt;
+ }
+ }
+ // building average
+ col[0] /= cnt;
+ col[1] /= cnt;
+ col[2] /= cnt;
+ // write back
+ size_t index = (i + j*width)*3;
+ lightMap[index+0] = (uchar)col[0];
+ lightMap[index+1] = (uchar)col[1];
+ lightMap[index+2] = (uchar)col[2];
+ }
+ }
+ }
+ }
+
+
+
+ void createTerrainLightmap(const TerrainInfo& info, Image& image,
+ size_t width, size_t height, Vector3 lightDir, const ColourValue& lightCol,
+ const ColourValue& ambient, bool shadowed)
+ {
+ lightDir.normalise();
+
+ // calculate lightmap by multiplying light dir with terrain normals
+
+ // calculate the step size to use
+ AxisAlignedBox extents = info.getExtents();
+ Vector3 startPos = extents.getMinimum();
+ Vector3 step = extents.getMaximum() - extents.getMinimum();
+ step.x /= width;
+ step.z /= height;
+ Vector3 pos = startPos;
+
+ uchar* lightMap = new uchar[width*height * 3];
+ memset(lightMap, 255, width*height*3);
+
+ for (size_t z = 0; z < height; ++z)
+ {
+ for (size_t x = 0; x < width; ++x)
+ {
+ size_t index = (z * width + x)*3;
+ // calculate diffuse light from light source
+ Vector3 norm = info.getNormalAt(pos.x, pos.z);
+ float l = std::max(0.0f, -lightDir.dotProduct(norm));
+
+ ColourValue v = ambient;
+ v.r = std::min(1.0f, v.r+l*lightCol.r);
+ v.g = std::min(1.0f, v.g+l*lightCol.g);
+ v.b = std::min(1.0f, v.b+l*lightCol.b);
+ lightMap[index+0] = (uchar) (255*v.r);
+ lightMap[index+1] = (uchar) (255*v.g);
+ lightMap[index+2] = (uchar) (255*v.b);
+
+ pos.x += step.x;
+ }
+ pos.x = startPos.x;
+ pos.z += step.z;
+ }
+
+ if (shadowed && (lightDir.x != 0 || lightDir.z != 0))
+ {
+ // add terrain shadows
+ Impl::addTerrainShadowsToLightmap(lightMap, info, width, height, lightDir, ambient);
+ }
+
+ // use a box filter to smoothen the lightmap
+ Impl::boxFilterLightmap(lightMap, width, height);
+
+ // save lightmap to image
+ image.loadDynamicImage(lightMap, width, height, 1, PF_BYTE_RGB, true);
+ // ownership of lightMap was transfered to image, don't need to delete
+ }
+}
Added: trunk/python-ogre/ThirdParty/et/ETLoadSaveHeightmap.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETLoadSaveHeightmap.cpp (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETLoadSaveHeightmap.cpp 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,167 @@
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "ETTerrainInfo.h"
+
+#include <OgreDataStream.h>
+#include <OgreImage.h>
+#include <OgreException.h>
+
+#include <iostream>
+
+using namespace Ogre;
+using namespace std;
+using Ogre::uint;
+using Ogre::ushort;
+
+namespace ET
+{
+ void loadHeightmapFromImage(TerrainInfo& info, const Image& image)
+ {
+ uint bpp = 0;
+ bool flip = false;
+
+ switch (image.getFormat())
+ {
+ case PF_BYTE_A: case PF_BYTE_L:
+ bpp = 1; break;
+ case PF_BYTE_LA: case PF_L16:
+ bpp = 2; break;
+ case PF_BYTE_RGB:
+ bpp = 3; break;
+ case PF_BYTE_BGR:
+ bpp = 3; flip = true; break;
+ case PF_BYTE_RGBA:
+ bpp = 4; break;
+ case PF_BYTE_BGRA:
+ bpp = 4; flip = true; break;
+ default:
+ OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Can't use the given image's format.", "loadHeightmapFromImage");
+ }
+
+ size_t size = image.getWidth() * image.getHeight();
+ unsigned int maxVal = (1 << (bpp*8)) - 1;
+ vector<float> data (size);
+ const uchar* imageData = image.getData();
+
+ for (size_t i = 0; i < size; ++i)
+ {
+ uchar read[4] = {0, 0, 0, 0};
+ // TODO: Make this big endian aware/compatible
+ memcpy(read, imageData, bpp);
+ imageData += bpp;
+ if (flip)
+ swap(read[0], read[2]);
+ unsigned int val = * ((unsigned int*)read);
+ data[i] = float(val) / maxVal;
+ }
+
+ info.setHeightmap(image.getWidth(), image.getHeight(), data);
+ }
+
+
+ void saveHeightmapToImage(const TerrainInfo& info, Ogre::Image& image, unsigned int bpp)
+ {
+ PixelFormat pf;
+ // decide on the image format to use
+ switch (bpp)
+ {
+ case 1:
+ pf = PF_BYTE_L; break;
+ case 2:
+ pf = PF_L16; break;
+ case 3:
+ pf = PF_BYTE_RGB; break;
+ case 4:
+ pf = PF_BYTE_RGBA; break;
+ default:
+ OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Bpp must be between 1 and 4.", "saveHeightmapToImage");
+ }
+
+ uint maxVal = (1 << (bpp*8)) - 1;
+
+ uchar* data = new uchar[info.getWidth()*info.getHeight()*bpp];
+ uchar* pos = data;
+
+ // fill data array
+ for (size_t j = 0; j < info.getHeight(); ++j)
+ {
+ for (size_t i = 0; i < info.getWidth(); ++i)
+ {
+ uint val = uint (maxVal * info.at(i, j));
+ memcpy(pos, &val, bpp);
+ pos += bpp;
+ }
+ }
+
+ image.loadDynamicImage(data, info.getWidth(), info.getHeight(), 1, pf, true);
+ // given ownership of data to image
+ }
+
+
+
+
+ void loadHeightmapFromRawData(TerrainInfo& info, DataStream& stream, size_t width, size_t height)
+ {
+ size_t size = width*height;
+ size_t bpp = stream.size() / size;
+ if (bpp < 1 || bpp > 4 || stream.size() % size != 0)
+ OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Size of the given data stream does not match with specified dimensions.", "loadHeightmapFromRawData");
+
+ unsigned int maxVal = (1 << (bpp*8)) - 1;
+ vector<float> data (size);
+
+ for (size_t i = 0; i < size; ++i)
+ {
+ unsigned int val = 0;
+ // TODO: What about big endian compatibility?
+ stream.read((void*)&val, bpp);
+ data[i] = float(val) / maxVal;
+ }
+
+ info.setHeightmap(width, height, data);
+ }
+
+
+ void saveHeightmapToRawData(const TerrainInfo& info, ostream& stream, uint bpp)
+ {
+ if (bpp < 1 || bpp > 4)
+ OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Bpp must be between 1 and 4.", "saveHeightmapToRawData");
+
+ uint maxVal = (1 << (bpp*8)) - 1;
+ for (size_t j = 0; j < info.getHeight(); ++j)
+ {
+ for (size_t i = 0; i < info.getWidth(); ++i)
+ {
+ uint val = (uint) (maxVal * info.at(i, j));
+ stream.write(reinterpret_cast<char*>(&val), bpp);
+ }
+ }
+ }
+
+}
Added: trunk/python-ogre/ThirdParty/et/ETPrerequisites.h
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETPrerequisites.h (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETPrerequisites.h 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,28 @@
+#ifndef __ETPREREQUISITES_H__
+#define __ETPREREQUISITES_H__
+
+#include <OgrePlatform.h>
+
+#define _ETManagerExport
+
+// // #ifndef _ETManagerExport
+
+// // #if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32 )
+// // # ifdef ET_MANAGER_EXPORTS
+// // # define _ETManagerExport __declspec(dllexport)
+// // # else
+// // # if defined( __MINGW32__ )
+// // # define _ETManagerExport
+// // # else
+// // # define _ETManagerExport __declspec(dllimport)
+// // # endif
+// // # endif
+// // #elif defined ( OGRE_GCC_VISIBILITY )
+// // # define _ETManagerExport __attribute__ ((visibility("default")))
+// // #else
+// // # define _ETManagerExport
+// // #endif
+
+// // #endif
+
+#endif
Added: trunk/python-ogre/ThirdParty/et/ETSplattingManager.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETSplattingManager.cpp (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETSplattingManager.cpp 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,518 @@
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "ETSplattingManager.h"
+#include "ETBrush.h"
+
+#include <OgreResource.h>
+#include <OgreImage.h>
+#include <OgreTextureManager.h>
+#include <OgreStringConverter.h>
+#include <OgreHardwarePixelBuffer.h>
+#include <OgreException.h>
+
+#include <OgreLogManager.h>
+#include <sstream>
+
+using namespace Ogre;
+using namespace std;
+using Ogre::uint;
+using Ogre::ushort;
+
+
+namespace ET
+{
+ namespace Impl
+ {
+ /** Handles a single alpha coverage map texture */
+ class CoverageMap : public ManualResourceLoader
+ {
+ public:
+ CoverageMap(const String& name, const String& group, uint width, uint height, int channels, bool black = true);
+ ~CoverageMap();
+
+ /** Retrieve coverage map from image. */
+ void loadFromImage(const Image& image);
+ /** Save coverage map to image. */
+ void saveToImage(Image& image);
+
+ /** Get the map's value for texture index c at position (x, y) */
+ uchar getValue(uint x, uint y, uint c) const;
+ /** Set the map's value for texture index c at position (x, y) */
+ void setValue(uint x, uint y, uint c, uchar val);
+
+ /** Copy the editing buffer into the texture's pixel buffer. */
+ void updateTexture();
+
+ /** Implemented from ManualResourceLoader to support reloading of the coverage map. */
+ void loadResource(Resource*);
+
+ /** Texture resource name for this coverage map. */
+ const String& getName() const;
+
+ private:
+ PixelFormat getFormat(int channels);
+ int getChannels(PixelFormat format);
+
+ uint mWidth, mHeight, mSize;
+ int mChannels;
+ uchar* mData;
+ TexturePtr mTexture;
+ };
+
+
+ CoverageMap::CoverageMap(const String& name, const String& group, uint width, uint height, int channels, bool black)
+ : mWidth(width), mHeight(height), mChannels(channels), mSize(width*height*channels)
+ {
+ mData = new uchar[mSize];
+ memset(mData, 0, mSize);
+ // the first channel of the first coverage map is set to full value so that
+ // terrain initially is rendered with the first splatting texture
+ if (!black)
+ for (uint i = 0; i < mSize; i += mChannels)
+ mData[i] = 255;
+ // create a manually managed texture resource
+ mTexture = TextureManager::getSingleton().createManual(name, group, TEX_TYPE_2D,
+ width, height, 1, 0, getFormat(mChannels), TU_DEFAULT, this);
+ }
+
+ CoverageMap::~CoverageMap()
+ {
+ delete[] mData;
+ TextureManager::getSingleton().remove(mTexture->getName());
+ }
+
+ void CoverageMap::loadResource(Resource*)
+ {
+ // the texture has requested to (re)load, we just copy our edit buffer
+ // into the texture
+ mTexture->createInternalResources();
+ updateTexture();
+ }
+
+ void CoverageMap::updateTexture()
+ {
+ // write the edit buffer into the texture's pixel buffer
+ HardwarePixelBufferSharedPtr buffer = mTexture->getBuffer();
+ PixelBox pixelBox (mWidth, mHeight, 1, getFormat(mChannels), mData);
+ Image::Box imageBox (0, 0, mWidth, mHeight);
+ buffer->blitFromMemory(pixelBox, imageBox);
+ }
+
+ const String& CoverageMap::getName() const
+ {
+ return mTexture->getName();
+ }
+
+ uchar CoverageMap::getValue(uint x, uint y, uint c) const
+ {
+ return mData[(y*mWidth + x)*mChannels + c];
+ }
+
+ void CoverageMap::setValue(uint x, uint y, uint c, uchar val)
+ {
+ mData[(y*mWidth + x)*mChannels + c] = val;
+ }
+
+
+ PixelFormat CoverageMap::getFormat(int channels)
+ {
+ switch (channels)
+ {
+ case 1: return PF_BYTE_A;
+ case 2: return PF_BYTE_LA;
+ case 3: return PF_BYTE_RGB;
+ case 4: return PF_BYTE_RGBA;
+ case -1: return PF_BYTE_A;
+ case -2: return PF_BYTE_LA;
+ case -3: return PF_BYTE_BGR;
+ case -4: return PF_BYTE_BGRA;
+ default: return PF_UNKNOWN;
+ }
+ }
+
+ int CoverageMap::getChannels(PixelFormat format)
+ {
+ switch (format)
+ {
+ case PF_BYTE_A: return 1;
+ case PF_BYTE_LA: return 2;
+ case PF_BYTE_RGB: return 3;
+ case PF_BYTE_BGR: return -3;
+ case PF_BYTE_RGBA: return 4;
+ case PF_BYTE_BGRA: return -4;
+ default: return 0;
+ }
+ }
+
+ void CoverageMap::loadFromImage(const Image& image)
+ {
+ if (image.getWidth() != mWidth || image.getHeight() != mHeight)
+ OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given image doesn't conform to the used width and height.", "CoverageMap::loadFromImage");
+ if (image.getFormat() != getFormat(mChannels) && image.getFormat() != getFormat(-mChannels))
+ OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given image is of invalid pixel format.", "CoverageMap::loadFromImage");
+
+ memcpy(mData, image.getData(), image.getSize());
+ if (getChannels(image.getFormat()) <= -3)
+ {
+ // need RGB(A), but given BGR(A) so invert
+ for (uint i = 0; i < mSize; i += mChannels)
+ swap(mData[i], mData[i+2]);
+ }
+
+ updateTexture();
+ }
+
+ void CoverageMap::saveToImage(Image& image)
+ {
+ image.loadDynamicImage(mData, mWidth, mHeight, 1, getFormat(mChannels));
+ }
+
+
+
+ struct SplattingImpl
+ {
+ String baseName;
+ String group;
+ uint width, height;
+ uint channels;
+ uint numTextures;
+ uint numMaps;
+
+ typedef vector<Impl::CoverageMap*> MapList;
+ MapList maps;
+
+ void paint(uint texture, uint x, uint y, float edit)
+ {
+ uint map = texture / channels;
+ uint channel = texture % channels;
+ int val = maps[map]->getValue(x, y, channel) + (int) (255.0 * edit);
+ if (val > 255)
+ val = 255;
+ if (val < 0)
+ val = 0;
+ maps[map]->setValue(x, y, channel, val);
+
+ balance(x, y, texture, val);
+ }
+
+ void balance(uint x, uint y, uint texture, int val)
+ {
+ // this method ensures that the values at (x, y) of all channels in all maps sum up to 255,
+ // otherwise the terrain will get over- or underlighted at that position
+ int sum = 0;
+ for (uint i = 0; i < numMaps; ++i)
+ {
+ for (uint j = 0; j < channels; ++j)
+ {
+ // skip the texture we painted with, otherwise we'd be
+ // undoing the change
+ if (i * channels + j == texture)
+ continue;
+ sum += maps[i]->getValue(x, y, j);
+ }
+ }
+
+ if (sum == 0)
+ {
+ // all other textures are 0, so set selected texture to full value
+ maps[texture/channels]->setValue(x, y, texture%channels, 255);
+ return;
+ }
+
+ // reduce/add all other channels as necessary
+ int diff = sum - (255 - val);
+ for (uint i = 0; i < numMaps; ++i)
+ {
+ for (uint j = 0; j < channels; ++j)
+ {
+ // skip the texture we painted with, otherwise we'd be
+ // undoing the change
+ if (i * channels + j == texture)
+ continue;
+ uchar v = maps[i]->getValue(x, y, j);
+ v -= (uchar) floor(0.5 + diff * (float(v) / sum));
+ maps[i]->setValue(x, y, j, v);
+ }
+ }
+ }
+
+ 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;
+ }
+}
Added: trunk/python-ogre/ThirdParty/et/ETSplattingManager.h
===================================================================
--- trunk/python-ogre/ThirdParty/et/ETSplattingManager.h (rev 0)
+++ trunk/python-ogre/ThirdParty/et/ETSplattingManager.h 2007-10-05 04:16:07 UTC (rev 408)
@@ -0,0 +1,133 @@
+#ifndef __ETSPLATTINGMANAGER_H__
+#define __ETSPLATTINGMANAGER_H__
+
+/*
+EDITABLE TERRAIN MANAGER for Ogre
+Copyright (C) 2007 Holger Frydrych <h.f...@gm...>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, you may use this file as part of a free software
+library without restriction. Specifically, if other files instantiate
+templates or use macros or inline functions from this file, or you compile
+this file and link it with other files to produce an executable, this
+file does not by itself cause the resulting executable to be covered by
+the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
+*/
+
+#include "ETPrerequisites.h"
+
+#include "OgreColourValue.h"
+#include "OgreImage.h...
[truncated message content] |