- preparing to rewrite the landscape gen phase

git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@116 ea6a568a-9f4f-0410-981a-c910a81bb256
actorid
nkorslund 16 years ago
parent 401bd35e02
commit c18a1ebd05

@ -19,7 +19,6 @@
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
module monster.util.freelist;
@ -183,16 +182,6 @@ struct Buffers
BufferList!(256) b256;
BufferList!(768) b768;
/*
static this()
{
writefln("64: ints=%s bytes=%s", b64.ints, b64.bytes);
writefln("128: ints=%s bytes=%s", b128.ints, b128.bytes);
writefln("256: ints=%s bytes=%s", b256.ints, b256.bytes);
writefln("768: ints=%s bytes=%s", b768.ints, b768.bytes);
}
*/
int[] getInt(uint size)
{
if(size <= b64.ints) return b64.getInt(size);

@ -14,18 +14,18 @@ public:
destroyMesh();
}
/**
* @brief repositions the mesh, and ensures that it is the right size
*/
// Repositions the mesh based on camera location
void update()
{
Ogre::Real vd = mCamera->getFarClipDistance();
if ( vd > mMeshDistance ) {
destroyMaterial();
destroyMesh();
createMaterial();
createMesh();
}
// Recreate the mesh if the view distance has increased
if ( vd > mMeshDistance )
{
destroyMaterial();
destroyMesh();
createMaterial();
createMesh();
}
Ogre::Vector3 p = mCamera->getDerivedPosition();
p.x -= ((int)p.x % 8192);
@ -49,7 +49,6 @@ private:
mMeshDistance = vd;
mObject->position(-vd,-2048, vd);
mObject->textureCoord(0, 1);
@ -66,7 +65,6 @@ private:
mObject->end();
mNode = mTerrainSceneNode->createChildSceneNode();
mNode->attachObject(mObject);
}
@ -78,6 +76,11 @@ private:
mNode->getParentSceneNode()->removeAndDestroyChild(mNode->getName());
}
// FIXME: We destroy and recreate the material (and mesh) when the
// view distance changes. If we make a built-in auto-adjusting FPS
// optimizer, this will happen quite a lot, so it's worth trying to
// optimize this. This might be moot however when we implement
// water, since BaseLand may not be needed anymore.
void createMaterial()
{
float vd = mCamera->getFarClipDistance();

@ -1,9 +1,6 @@
class TerrainFrameListener : public FrameListener
{
protected:
/**
* Updates the quad tree
*/
bool frameEnded(const FrameEvent& evt)
{
g_rootQuad->update(evt.timeSinceLastFrame);
@ -25,32 +22,11 @@ public:
g_heightMap = new HeightMap(node);
g_heightMap->load(TERRAIN_OUTPUT);
//fix settings
// Fix settings
g_heightMap->setMorphingEnabled(false);
g_heightMap->setTextureFadingEnabled(false);
//create the quad node
// Create the root quad
g_rootQuad = new Quad(Quad::QL_ROOT, 0);
}
/* KILLME
void drawLine(std::string name, Ogre::Vector3 start, Ogre::Vector3 end)
{
Ogre::ManualObject* mo = mSceneMgr->createManualObject( name);
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode( name+"node");
Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create( name+"Material","debugger");
mat->setReceiveShadows(false);
mat->getTechnique(0)->setLightingEnabled(true);
mat->getTechnique(0)->getPass(0)->setDiffuse(0,0,1,0);
mat->getTechnique(0)->getPass(0)->setAmbient(0,0,1);
mat->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,1);
mo->begin(name+"Material", Ogre::RenderOperation::OT_LINE_LIST);
mo->position(start);
mo->position(end);
mo->end();
node->attachObject(mo);
}
*/
};

@ -1,6 +1,6 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2009 Jacob Essex
Copyright (C) 2009 Jacob Essex, Nicolay Korslund
WWW: http://openmw.sourceforge.net/
This file (cpp_generator.cpp) is part of the OpenMW package.
@ -26,7 +26,9 @@ public:
Generator(const std::string& baseFileName) :
mBaseFileName(baseFileName)
{
#if GEN_LANDDATA
mDataO.open(std::string(baseFileName+".data").c_str(), std::ios::binary);
#endif
}
inline void addLandData(RecordPtr record, const std::string& source)
@ -37,7 +39,7 @@ public:
void beginGeneration()
{
//maxiumum distance form 0, 0 in any direction
// Find the maxiumum distance from (0,0) in any direction
int max = 0;
max = std::max<int>(mMWLand.getMaxX(), max);
max = std::max<int>(mMWLand.getMaxY(), max);
@ -61,13 +63,14 @@ public:
//Keep deviding the root side length by 2 (thereby simulating a
//split) until we reach the width of the base cell (or the
//smallest quad)
//smallest quad). TODO: We should make sure that the right number
//of levels are actually generated automatically, of course.
for (long i = mIndex.getRootSideLength(); i > 8192; i/=2 )
maxDepth++;
mIndex.setMaxDepth(maxDepth);
}
void generateLODLevel(int level, bool createTexture, int textureSize)
void generateLODLevel(int level, int textureSize)
{
std::cout << "Generating Level " << level << "\n";
@ -80,26 +83,33 @@ public:
// FIXME: Should probably use another name than 'level' here
level = pow((float)2, level); //gap between verts that we want
// Use this instead
assert(level == 1 << initialLevel);
const int halfLevel = level/2;
assert(halfLevel > 0 );
// FIXME. Just search for all pow() calls, really
// FIXME. Search for all pow() calls and fix them
int cellDist = pow((float)2, mIndex.getMaxDepth());
// Temporary storage
QuadData qd;
#if GEN_LANDDATA
qd.setVertexSeperation(128*halfLevel); //dist between two verts
std::vector<float>& gh = qd.getHeightsRef(); //ref to the data storage in the quad
std::vector<float>& gh = qd.getHeightsRef(); //ref to the data
//storage in the quad
std::vector<char>& gn = qd.getNormalsRef();
gh.resize(LAND_NUM_VERTS); //allocate memory for mesh functions
gn.resize(LAND_NUM_VERTS*3);
#endif
//the 16*16 array used for holding the LTEX records (what texure is splatted where)
//the 16*16 array used for holding the LTEX records (what texure
//is splatted where)
std::vector<int>& gl = qd.getTextureIndexRef();
gl.resize((LAND_LTEX_WIDTH+2)*(LAND_LTEX_WIDTH+2));
const std::string stringLevel(Ogre::StringConverter::toString(level)); //cache this
const std::string stringLevel(Ogre::StringConverter::toString(level));
const std::string defaultTexture(stringLevel + "_default.png");
bool hasUsedDefault = false;
@ -107,21 +117,22 @@ public:
for( int y = -(cellDist/2); y < (cellDist/2); y+=halfLevel )
for( int x = -(cellDist/2); x < (cellDist/2); x+=halfLevel )
{
qd.setParentTexture("");
bool usingDefaultTexture = false;
if ( initialLevel == 1 )
// For level one (up close), there's no need to generate
// any textures, as we can use the textures from the BSAs
// directly.
generateLTEXData(x, y, gl);
else if ( createTexture )
else
{
//this is the name of the file that OGRE will
//look for
std::string name = stringLevel + "_" +
// Texture file name
std::string name = stringLevel + "_" +
Ogre::StringConverter::toString(x) + "_" +
Ogre::StringConverter::toString(y) + ".png";
//where as the arg1 here is the file name to save it.
// Generate the texture
bool hasGen = generateTexture(std::string(TEXTURE_OUTPUT) + name, textureSize, x, y, halfLevel);
if ( hasGen ) qd.setTexture(name);
@ -133,10 +144,14 @@ public:
}
}
//calculate parent texture
// Calculate parent texture
if ( initialLevel != mIndex.getMaxDepth() )
{
// FIXME: This can definitely be improved, although it
// doesn't matter performance wise
//calcualte the level one higher
// FIXME: pow() again...
int higherLevel = pow((float)2, (initialLevel+1));
int highHalfLevel = higherLevel/2;
@ -144,7 +159,6 @@ public:
if ( (higherX-halfLevel) % highHalfLevel == 0 )
higherX -= halfLevel;
int higherY = y;
if ( (higherY-halfLevel) % highHalfLevel == 0 )
higherY -= halfLevel;
@ -153,7 +167,7 @@ public:
Ogre::StringConverter::toString(higherX) + "_" +
Ogre::StringConverter::toString(higherY) + ".png";
//check file exists without needing boost filesystenm libs
//check file exists without needing boost filesystem libs
FILE* fp = fopen((std::string(TEXTURE_OUTPUT) + higherName).c_str(), "r");
if ( fp )
{
@ -163,6 +177,8 @@ public:
else
qd.setParentTexture("");
}
#if GEN_LANDDATA
generateMesh(gh, gn, x, y, halfLevel );
bool isEmptyQuad = true;
@ -187,6 +203,8 @@ public:
mDataO.tellp());
boost::archive::binary_oarchive oa(mDataO); //using boost fs to write the quad
oa << qd;
#endif
}
//check if we have used a default texture
@ -201,20 +219,27 @@ public:
void endGeneration()
{
// FIXME: Just write one file?
#if GEN_LANDDATA
mDataO.close();
std::ofstream ofi(std::string(mBaseFileName + ".index").c_str(), std::ios::binary);
std::ofstream ofp(std::string(mBaseFileName + ".palette").c_str(), std::ios::binary);
boost::archive::binary_oarchive oai(ofi);
boost::archive::binary_oarchive oap(ofp);
oai << mIndex;
oap << mPalette;
#endif
mDataO.close();
std::ofstream ofp(std::string(mBaseFileName + ".palette").c_str(), std::ios::binary);
boost::archive::binary_oarchive oap(ofp);
oap << mPalette;
}
private:
// Generate texture data for level 1.
void generateLTEXData(int x, int y, std::vector<int>& index)
{
// All this does is to loop through all the 16x16 'land grid
// points' in the cell (plus the outer border of grid points from
// the surrounding cells) and store the texture names in the
// index.
for ( int texY = 0; texY < LAND_LTEX_WIDTH+2; texY++ )
for ( int texX = 0; texX < LAND_LTEX_WIDTH+2; texX++ )
{
@ -269,47 +294,58 @@ private:
}
}
// Create a cache texture.
bool generateTexture(const std::string& name, int size,
int blockX, int blockY, int halfLevel)
{
int width = size/(halfLevel*LAND_LTEX_WIDTH);
assert(width>=1);
std::vector<int> ltex; //prealloc, as we know exactly what size it needs to be
// Preallocate a buffer of texture indices
std::vector<int> ltex;
ltex.resize(halfLevel*LAND_LTEX_WIDTH*halfLevel*LAND_LTEX_WIDTH, 0);
//for each cell
// This loop collection is just to gather the texture indices for
// this quad. All texture paths are inserted into the
for ( int y = 0; y < halfLevel; y++ )
for ( int x = 0; x < halfLevel; x++ )
//for each texture in the cell
for ( int texY = 0; texY < LAND_LTEX_WIDTH; texY++ )
for ( int texX = 0; texX < LAND_LTEX_WIDTH; texX++ )
{
std::string source;
short texID = 0;
if ( mMWLand.hasData(x + blockX, y + blockY) )
{
source = mMWLand.getSource(x + blockX, y + blockY);
texID = mMWLand.getLTEXIndex(x + blockX, y + blockY, texX, texY);
}
std::string texturePath = "_land_default.dds";
if ( texID != 0 && mMWLand.hasLTEXRecord(source,--texID) )
texturePath = mMWLand.getLTEXRecord(source,texID);
//textures given as tga, when they are a dds. I hate that "feature"
//FIXME: ditto earlier comment
size_t d = texturePath.find_last_of(".") + 1;
texturePath = texturePath.substr(0, d) + "dds";
//FIXME: BTW, didn't we make the BSA reader case insensitive?
std::transform(texturePath.begin(), texturePath.end(), texturePath.begin(), tolower);
const int index = (y*LAND_LTEX_WIDTH+texY)*halfLevel*LAND_LTEX_WIDTH + x*LAND_LTEX_WIDTH+texX;
ltex[index] = mPalette.getOrAddIndex(texturePath);
}
{
// And loop over all 16x16 textures in each cell
for ( int texY = 0; texY < LAND_LTEX_WIDTH; texY++ )
for ( int texX = 0; texX < LAND_LTEX_WIDTH; texX++ )
{
std::string source;
short texID = 0;
// Get the data from the ESM
if ( mMWLand.hasData(x + blockX, y + blockY) )
{
source = mMWLand.getSource(x + blockX, y + blockY);
texID = mMWLand.getLTEXIndex(x + blockX, y + blockY, texX, texY);
}
std::string texturePath = "_land_default.dds";
if ( texID != 0 && mMWLand.hasLTEXRecord(source,--texID) )
texturePath = mMWLand.getLTEXRecord(source,texID);
// Convert .tga to .dds
// FIXME: ditto earlier comment.
size_t d = texturePath.find_last_of(".") + 1;
texturePath = texturePath.substr(0, d) + "dds";
//FIXME2: BTW, didn't we make the BSA reader case insensitive?
std::transform(texturePath.begin(), texturePath.end(), texturePath.begin(), tolower);
const int index = (y*LAND_LTEX_WIDTH+texY)*halfLevel*LAND_LTEX_WIDTH + x*LAND_LTEX_WIDTH+texX;
// FIXME: In any case, we should let mPalette do the
// name conversion. So if the texture is already
// inserted (which will almost always be the case) we
// can avoid costly string operations.
ltex[index] = mPalette.getOrAddIndex(texturePath);
}
}
//see if we have used anything at all
// FIXME: Now, I KNOW this isn't needed :)
// See if we have used anything at all. FIXME: This isn't needed
// as a separate loop
int sum = 0;
for ( std::vector<int>::iterator i = ltex.begin(); i != ltex.end(); ++i )
sum += *i;
@ -327,6 +363,9 @@ private:
// dependent, when it should be a simple computational exercise. But
// understand what it actually does, before you change anything.
// This function (and it's sub calls) is where most of the time is
// spent in the gen process, so this is also where we need to
// optimize.
void renderTexture(const std::string& outputName, std::vector<int>& ltex,
int texSize, int alphaSize)
{
@ -339,10 +378,12 @@ private:
MaterialGenerator mg;
mg.setTexturePaths(mPalette.getPalette());
// Aaand, this is just halfLevel again, which already is a very
// poor name for the number of cells along the side of the quad.
const int scaleDiv = alphaSize/LAND_LTEX_WIDTH;
//genetate material/aplahas
Ogre::MaterialPtr mp = mg.getAlphaMat(ltex, alphaSize, 0, scaleDiv,createdResources);
Ogre::MaterialPtr mp = mg.getAlphaMat(ltex, alphaSize, scaleDiv,createdResources);
Ogre::TexturePtr tex1 = getRenderedTexture(mp, "RTT_TEX_1",texSize, Ogre::PF_R8G8B8);
tex1->getBuffer()->getRenderTarget()->writeContentsToFile(outputName);
Ogre::MaterialManager::getSingleton().remove(mp->getHandle());
@ -359,6 +400,7 @@ private:
}
}
// Does everything in OGRE
Ogre::TexturePtr getRenderedTexture(Ogre::MaterialPtr mp, const std::string& name,
int texSize, Ogre::PixelFormat tt)
{
@ -393,8 +435,7 @@ private:
renderTexture->update();
//required for some reason?
//Not implementing resulted in a black tex using openGL, Linux, and a nvidia 6150 in 1.4.?
// Call the OGRE renderer.
Ogre::Root::getSingleton().renderOneFrame();
Ogre::CompositorManager::getSingleton().removeCompositor(vp, "Rtt_Comp");

@ -3,23 +3,18 @@ class TextureSplatter
public:
inline TextureSplatter(const std::vector<int>& ltex,
int texSize,
int ltexsize,
int border) :
mLTEX(ltex),
mTexSize(texSize), //the root of the size of the texture
mLTEXSize(ltexsize), //the root of the ltex array
mBorder(border) { //the size of the border of the ltex
mSizeDiff = texSize/(ltexsize-border*2);
}
int getAlphaAtPixel(int x, int y, int tid) {
//offset for border
x += (mBorder*mSizeDiff);
y += (mBorder*mSizeDiff);
int ltexsize)
: mLTEX(ltex),
mTexSize(texSize), //the root of the size of the texture
mLTEXSize(ltexsize) //the root of the ltex array
{ mSizeDiff = texSize/ltexsize; }
if ( getTextureAtPixel(x,y) == tid ) {
int getAlphaAtPixel(int x, int y, int tid)
{
if ( getTextureAtPixel(x,y) == tid )
return 255;
} else if ( mBorder > 0 )
/*
else if ( mBorder > 0 )
{
//hacky remove fix. perofrmance issues. skips if not ingame gen.
float amount = 0;
@ -39,6 +34,7 @@ public:
assert(amount>=0&&amount<=1);
return amount*255;
}
*/
return 0;
}
@ -54,7 +50,6 @@ private:
const std::vector<int>& mLTEX;
const int mTexSize;
const int mLTEXSize;
const int mBorder;
int mSizeDiff;
};
@ -71,8 +66,8 @@ public:
* texture. Only used at runtime, not while generating.
*/
Ogre::MaterialPtr generateSingleTexture
(const std::string& texName,
std::list<Ogre::ResourcePtr> createdResources)
(const std::string& texName,
std::list<Ogre::ResourcePtr> createdResources)
{
const std::string matname("MAT" + Ogre::StringConverter::toString(mCount++));
@ -93,7 +88,7 @@ public:
/**
* gets the material for the alpha textures
*/
Ogre::MaterialPtr getAlphaMat(std::vector<int>& ltex,
Ogre::MaterialPtr new_getAlphaMat(std::vector<int>& ltex,
int size,
int border,
float scaleDiv,
@ -101,22 +96,188 @@ public:
{
const std::string materialName("MAT" + Ogre::StringConverter::toString(mCount++));
// We REALLY need to clean these variables up
// Number of textures along one side
const int ltexWidth = Ogre::Math::Sqrt(ltex.size());
// Only true if border = 0, which I guess I've assumed below
assert(ltexWidth == size);
// Side for the quad only, not including the border. Used for the
// assert() below only.
const int rootSideLength = ltexWidth-(border*2);
// Multiply up the number of textures along a side to get the
// resolution of the alpha map. This gives 4*4=16 alpha pixels per
// texture square, or 4*16 = 64 alpha pixels across the entire
// quad.
const int sizeDiff = 4;
size *= sizeDiff;
const int rootSideLength = Ogre::Math::Sqrt(ltex.size())-(border*2); //used for looping
const int ltexWidth = Ogre::Math::Sqrt(ltex.size());
assert(size%rootSideLength==0);
Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().
create(materialName,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
createdResources.push_back(material);
// But the default texture in the bottom 'layer', so that we don't
// end up seeing through the landscape.
Ogre::Pass* np = material->getTechnique(0)->getPass(0);
np->setLightingEnabled(false);
// FIXME: Why 0.1f?
np->createTextureUnitState("_land_default.dds")->setTextureScale(0.1f/scaleDiv,0.1f/scaleDiv);
// Put all the texture indices in a set
typedef std::set<int> SI;
typedef SI::iterator SI_it;
SI textures;
for( int in = 0; in < ltex.size(); in++ )
textures.insert(ltex[in]);
// Allocate the buffers
typedef std::vector<uint8_t> AlphaBuf;
std::map<int,AlphaBuf> alphaMap;
const int bufSize = size*size;
//TextureSplatter ts(ltex, size, ltexWidth, border);
// Peform splatting. Loop over each texture square in this quad.
for(int ty=0; ty < size; ty += sizeDiff)
for(int tx=0; tx < size; tx += sizeDiff)
{
// Get the texture index for this square
const int thisInd = ltex[tx + ltexWidth*ty];
// Offset for this texture
const int offs = ty*size + tx;
AlphaBuf &abuf = alphaMap[thisInd];
abuf.resize(bufSize);
// Set alphas to full for this square
for(int y=0; y<sizeDiff; y++)
for(int x=0; x<sizeDiff; x++)
{
int toffs = offs + y*size + x;
if(toffs >= abuf.size())
std::cout << "tx=" << tx << " ty=" << ty
<< " x=" << x << " y=" << y
<< " offs=" << offs
<< " toffs=" << toffs
<< " abuf.size()=" << abuf.size()
<< "\n";
assert(toffs < abuf.size());
abuf[toffs] = 255;
}
// Get alpha influence from neighbouring cells.
// FIXME: Rewrite TextureSplatter
}
// Create passes for each alpha buffer
for ( SI_it itr = textures.begin(); itr != textures.end(); ++itr )
{
int tid = *itr;
const std::string tn(mTexturePaths[tid]);
if ( tn == "_land_default.dds" )
continue;
//std::cout << " Generating texture " << tn << "\n";
std::string alphaName(materialName + "_A_" + tn);
if ( Ogre::TextureManager::getSingleton().resourceExists(alphaName) )
OGRE_EXCEPT(0, "ALPHA Already Exists", "");
//create alpha map
Ogre::TexturePtr texPtr = Ogre::TextureManager::getSingleton().
createManual(
alphaName, // Name of texture
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, // Name of resource group in which the texture should be created
Ogre::TEX_TYPE_2D,
size,size, //size ofc
1,0, //depth, mipmaps
Ogre::PF_A8, //we only need one channel to hold the splatting texture
Ogre::TU_STATIC_WRITE_ONLY //best performace, we shopuldn't need the data again
);
createdResources.push_back(texPtr);
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texPtr->getBuffer();
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
AlphaBuf *abuf = &alphaMap[tid];
for(AlphaBuf::iterator it = abuf->begin(); it != abuf->end(); it++)
*(pDest++) = *it;
pixelBuffer->unlock();
np = material->getTechnique(0)->createPass();
np->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
np->setLightingEnabled(false);
np->setDepthFunction(Ogre::CMPF_EQUAL);
Ogre::TextureUnitState* tus = np->createTextureUnitState(alphaName);
tus->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
tus->setAlphaOperation( Ogre::LBX_BLEND_TEXTURE_ALPHA,
Ogre::LBS_TEXTURE,
Ogre::LBS_TEXTURE);
tus->setColourOperationEx( Ogre::LBX_BLEND_DIFFUSE_ALPHA,
Ogre::LBS_TEXTURE,
Ogre::LBS_TEXTURE);
tus->setIsAlpha(true);
tus = np->createTextureUnitState(tn);
tus->setColourOperationEx( Ogre::LBX_BLEND_DIFFUSE_ALPHA,
Ogre::LBS_TEXTURE,
Ogre::LBS_CURRENT);
tus->setTextureScale(0.1f/scaleDiv,0.1f/scaleDiv);
}
return material;
}
// The old variant
Ogre::MaterialPtr getAlphaMat(std::vector<int>& ltex,
int size,
float scaleDiv,
std::list<Ogre::ResourcePtr>& createdResources)
{
const std::string materialName("MAT" + Ogre::StringConverter::toString(mCount++));
// Multiply up the number of textures along a side to get the
// resolution of the alpha map. This gives 4*4=16 alpha pixels per
// texture square, or 4*16 = 64 alpha pixels across the entire
// quad.
const int sizeDiff = 4;
size *= sizeDiff;
// Number of textures along one side
const int ltexWidth = Ogre::Math::Sqrt(ltex.size());
assert(size%ltexWidth==0);
Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().
create(materialName,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
createdResources.push_back(material);
// But the default texture in the bottom 'layer', so that we don't
// end up seeing through the landscape.
Ogre::Pass* np = material->getTechnique(0)->getPass(0);
np->setLightingEnabled(false);
np->createTextureUnitState("_land_default.dds")->setTextureScale(0.1f/scaleDiv,0.1f/scaleDiv);
// Put all the texture indices in a set
std::set<int> textures;
for ( int y1 = 0; y1 < ltexWidth; y1++ ) {
for ( int x1 = 0; x1 < ltexWidth; x1++ ) {
@ -126,7 +287,6 @@ public:
for ( std::set<int>::iterator itr = textures.begin(); itr != textures.end(); ++itr )
{
int tid = *itr;
const std::string tn(mTexturePaths[tid]);
@ -146,7 +306,7 @@ public:
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, // Name of resource group in which the texture should be created
Ogre::TEX_TYPE_2D,
size,size, //size ofc
1, 0, //depth, mipmaps
1,0, //depth, mipmaps
Ogre::PF_A8, //we only need one channel to hold the splatting texture
Ogre::TU_STATIC_WRITE_ONLY //best performace, we shopuldn't need the data again
);
@ -161,7 +321,7 @@ public:
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
memset(pDest,0, sizeof(Ogre::uint8)*size*size);
TextureSplatter ts(ltex, size, ltexWidth, border);
TextureSplatter ts(ltex, size, ltexWidth);
for ( int ty = 0; ty < size; ty++ ) {
for ( int tx = 0; tx < size; tx++ ) {
pDest[ty*size+tx] = ts.getAlphaAtPixel(tx,ty, tid);

@ -43,6 +43,9 @@ const int LAND_NUM_VERTS = LAND_VERT_WIDTH*LAND_VERT_WIDTH;
const int LAND_LTEX_WIDTH = 16;
const int LAND_NUM_LTEX = LAND_LTEX_WIDTH*LAND_LTEX_WIDTH;
// Can be used to turn of landscape data generation
#define GEN_LANDDATA 1
// Multiplied with the size of the quad. If these are too close, a
// quad might end up splitting/unsplitting continuously, since the
// quad size changes when we split.
@ -147,12 +150,12 @@ extern "C" void terr_genData()
mhm.beginGeneration();
mhm.generateLODLevel(6, true, 1024);
mhm.generateLODLevel(5, true, 512);
mhm.generateLODLevel(4, true, 256);
mhm.generateLODLevel(3, true, 256);
mhm.generateLODLevel(2, true, 256);
mhm.generateLODLevel(1, false, 128);
mhm.generateLODLevel(6, 1024);
mhm.generateLODLevel(5, 512);
mhm.generateLODLevel(4, 256);
mhm.generateLODLevel(3, 256);
mhm.generateLODLevel(2, 256);
mhm.generateLODLevel(1, 128);
mhm.endGeneration();
}

@ -14,7 +14,6 @@ public:
Ogre::MovableObject(),
mWidth(width),
mUseSkirts(skirts),
mBuilt(false),
mDepth(depth),
mVertexes(0),
mIndices(0),
@ -74,14 +73,10 @@ public:
if ( g_heightMap->isMorphingEnabled() )
calculateDeltaValues();
mBuilt = true;
}
~TerrainMesh()
{
if ( !mBuilt ) return;
//deleting null values is fine iirc
delete mIndices;
@ -97,8 +92,6 @@ public:
}
# endif
mBuilt = false;
assert(node);
node->detachAllObjects();
@ -323,17 +316,24 @@ private:
std::vector<int> ti;
/*
ti.resize((size+2)*(size+2), -1);
for ( int y = 0; y < size+2; ++y ){
for ( int x = 0; x < size+2; ++x ){
ti[(y)*(size+2)+(x)] = tref.at((y+yoff)*(indexSize)+(x+xoff));
}
}
*/
ti.resize(size*size, -1);
for ( int y = 0; y < size; ++y ){
for ( int x = 0; x < size; ++x ){
ti[y*size+x] = tref.at((1+y+yoff)*(indexSize)+(1+x+xoff));
}
}
mMaterial = g_materialGen->getAlphaMat
(ti,size,
1, 1.0f/size,
1.0f/size,
mQuadData->getUsedResourcesRef());
}
@ -712,9 +712,6 @@ else pDeltas[( y)*vw+ x] = v;
const int mWidth;
const bool mUseSkirts;
///true if the land has been built
bool mBuilt;
int mDepth;
Ogre::MaterialPtr mMaterial;

Loading…
Cancel
Save