[SOLVED] Crash when painting terrain
PatrickB3
13-09-2006 00:51:02
When you using brushes like the 10x10 circular PLSM2 crashes in function:
void PagingLandScapeTexture::upload(const Image::Box& textureRect)
It crashes at:
const PixelBox srcBox = mImages.getPixelBox().getSubVolume(textureRect);
It says:
Details:
-----------------------------------
Error #: 4
Function: PixelBox::getSubVolume
Description: Bounds out of range.
File: ..\src\OgrePixelFormat.cpp
Line: 544
OvermindDL1
13-09-2006 05:44:20
As told on other threads, the latest PLSM2 does not work with GOOF, only a couple modifications are needed as I recall, look through the recent posts to find it.
PatrickB3
13-09-2006 09:20:16
This isn't with GOOF and I already included the changes to PLSM2 in my app. Those changes only affect queries not painting.
tuan kuranes
13-09-2006 13:46:13
Cannot reproduce the crash.
here's my brush loading code for reference.
unsigned int Bsize = 16;
mSceneMgr->setOption ( "BrushArrayWidth", &Bsize);
mSceneMgr->setOption ( "BrushArrayHeight", &Bsize);
Image data;
data.load("16x16CircularBrush.jpg","PLSM2");
uchar *uData = data.getData ();
const Real scaler = 1.0 / 255;
for (size_t i = 0; i < 256; i ++)
mBrushHeights[i] = uData[i] * scaler;
mSceneMgr->setOption ( "BrushArray", &mBrushHeights);
Falagard
13-09-2006 14:00:27
Could have something to do with Ogre switching over to a different image loading API, if you're using GOOF's brush code as a reference it might not work anymore, so double check against tuan's code.
PatrickB3
14-09-2006 08:39:54
Haven't upgraded Ogre or anything. Tried Tuan's code but the same thing happens. BTW deforming seems to work so it couldn't be the brushes. I add a try catch block to that code. It logs as follows:
catch(...) {
Ogre::String t;
t = "Exception in Terrain Painting.\n TR - Left:" + Ogre::StringConverter::toString( textureRect.left );
t += "\n TR - Right:" + Ogre::StringConverter::toString( textureRect.right );
t += "\n TR - Top:" + Ogre::StringConverter::toString( textureRect.top );
t += "\n TR - Bottom:" + Ogre::StringConverter::toString( textureRect.bottom );
t += "\n IR - Left:" + Ogre::StringConverter::toString( mImages[i].getPixelBox().left );
t += "\n IR - Right:" + Ogre::StringConverter::toString( mImages[i].getPixelBox().right );
t += "\n IR - Top:" + Ogre::StringConverter::toString( mImages[i].getPixelBox().top );
t += "\n IR - Bottom:" + Ogre::StringConverter::toString( mImages[i].getPixelBox().bottom );
LogManager::getSingleton().logMessage( t );
That added to the log:
-----------------------------------
Details:
-----------------------------------
Error #: 4
Function: PixelBox::getSubVolume
Description: Bounds out of range.
File: ..\src\OgrePixelFormat.cpp
Line: 544
Stack unwinding: <<beginning of stack>>
16:07:06: Exception in Terrain Painting.
TR - Left:364
TR - Right:374
TR - Top:213
TR - Bottom:223
IR - Left:0
IR - Right:0
IR - Top:0
IR - Bottom:0
As you can see the texture rect seems like good values for the paint operation but the image has no size. However the terrain is textured fine so the image must exist. The really weird thing is every so often ( but rarely ) it works but only until I exit the game.
tuan kuranes
14-09-2006 09:22:33
What texture mode or custom material do you use ?
PatrickB3
14-09-2006 19:05:05
I'm using the PLSplattingShaderLit.
My .cfg is:
GroupName=PLSM2
LandScapeFileName=NewWorld2
FileSystem=LandScapeFileName
LandScapeExtension=RAW
Width=16
Height=16
RawWidth=513
RawHeight=513
Data2DFormat=HeightFieldRaw
#ScaleX=22500
#ScaleY=7500
#ScaleZ=22500
#ScaleX=45000
#ScaleY=15000
#ScaleZ=45000
ScaleX=11250
ScaleY=5500
ScaleZ=11250
NumTextureFormatSupported=1
TextureFormatSupported0=PLSplattingShaderLit
TextureFormat=PLSplattingShaderLit
NumMatHeightSplat=4
MaterialHeight1=15
MaterialHeight2=50
MaterialHeight3=80
SplatFilename0=brownsand1.jpg
SplatFilename1=atgrass.jpg
SplatFilename2=rocks.jpg
SplatFilename3=grounddirt.jpg
VisibleRenderables=80
MaxRenderLevel=100
NumRenderablesLoading=100
MaxAdjacentPages=1
MaxPreloadedPages=2
MaxNumRenderables=1024
IncrementRenderables=256
MaxNumTiles=4096
IncrementTiles=256
VertexCompression=yes
VertexProgramMorph=no
#ZHorizon=yes
#HeightMapBlurFactor=0.5f
#Deformable=no
Deformable=yes
VertexLit=yes
VertexColors=no
VertexNormals=yes
HorizonVisibilityComputing=yes
#MaterialDistanceLod=1000
#CameraThreshold=5
MaxPixelError=10
TextureModifiable=yes
#TextureModifiable=no
LODMorphStart=0.002
#DistanceLOD=100
ChangeFactor=100
#PageSize=513
TileSize=33
Also, not sure if this helps any but, the try catch block prevents the crash. If I set the texture as changed in the catch block the game then crashes on exit when it tries to save the modified file.
The sometimes working part BTW is not within the same run. It either works until I exit or doesn't work from the second I start the app.
It feels a lot like memory is getting overriden somewhere but I can't find anywhere that it is.
PatrickB3
14-09-2006 21:56:27
The problem turned out to be setting material scheme. Apparently the time I do it isn't good. Didn't really expect it as the terrain material doesn't use a scheme but apparently setting the material scheme resets something in Ogre to a different value from when PLSM2 loads the materials. I'm guessing it is mipmaps but I'll have to investigate further to see what and how to prevent it from bothering PLSM2.
PatrickB3
14-09-2006 22:10:06
Definately related to Mipmaps. However I have no idea on how to set the scheme without bothering PLSM2. Do I need to have it reload the terrain after setting it?
tuan kuranes
15-09-2006 08:26:13
I hope not.
Can you give me the exact way you use scheme so that I can reproduce that and see what I can do about that ?
PatrickB3
15-09-2006 18:11:39
I use two schemes in the materials , scheme HighDetail and scheme LowDetail. Thoiugh I didn't use a scheme at all for the terrain material.
In CreateScene I was setting mViewport->setMaterialScheme( "LowDetail" );
If I do that painting doesn't doesn't work. It seems to be related to the fact that PLSM2 reads the LOD level for the current scheme and seems to do it before create scene is called.
For now I just commented out the line. I have been thinking maybe I need to set a fake map in cfg and load the real one after all scheme is set. I checked the code for setMaterialScheme and it doesn't seem to be doing anything special but if I don't set the scheme after is fine in PLSM2.
PatrickB3
15-09-2006 18:54:02
Thinking about further I don't think loading the map at different times would do anything as PLSM2 loads the terrain images as it needs them anyways.
This code looks guilty in PagingLandScapeTexture::loadTexturesToModify():
const unsigned short numLodLevels =
mMaterial->getNumLodLevels(MaterialManager::getSingleton()._getActiveSchemeIndex());
As it is the only place PLSM2 uses code to access Schemes. When not using a scheme numLodLevels is 2, but when I set the scheme then it is 0 which now makes perfect sense to why painting crashes as it never loaded the modifiable textures.
Changing it to:
unsigned short numLodLevels =
mMaterial->getNumLodLevels(MaterialManager::getSingleton()._getActiveSchemeIndex());
if ( numLodLevels == 0 )
numLodLevels = mMaterial->getNumLodLevels( 0 );
makes the problem go away though I'm not certain it is the best way to do it.
tuan kuranes
18-09-2006 13:10:25
I don't understand clearly the fix...
For my understanding of schemes, I should rather store "loaded scheme", compare it to current scheme before any modification/operation on it, and if it doesn't exists load that scheme, and store previous ones into a "std::map"
PatrickB3
20-09-2006 19:52:31
I believe the problem is how Ogre works not really a PLSM2 thing. Ogre stores an index to the current scheme. When you get information from Ogre for that scheme ( such as mMaterial->getNumLodLevels(MaterialManager::getSingleton()._getActiveSchemeIndex()); ) it only returns valid information IF the material actually has that scheme defined.
My fix fixes the problem for me but I'm like 99.99999% sure that you can't use that as a general fix. It works for me because I know for a fact that a) I'm using schemes and b) my terrain material is not. c) Number of LOD levels will NEVER be 0. I know in my game that if numLODLevels is 0 then it failed to get the count from the active scheme.
I could not find a function in Ogre that would return an index for the actual scheme being used by the material. The active scheme index is the one the app requested whether or not the material has a scheme defined for it Ogre seems to not care.
One would have thought that if the material didn't have the active scheme then Ogre would return the number of LOD levels the material is using but it is just a simple look up. There is no error checking.
For example in my game I have:
No Scheme = 0 LOD levels = 2
HighDetail = 1 LODLevels = 0 since Terrain doesn't have it defined in material
LowDetail = 2 LOD Levels = 0 since Terrain doesn't have it defined in material
So if I set scheme to LowDetail getNumberLODLevels looks up in the table for scheme index 2 and returns 0 LOD Levels.
It seems if no schemes are defined in the material then scheme 0 is always used but I can't really tell if this is always true under all circumstances.
tuan kuranes
21-09-2006 15:28:17
From plsm2 perspective, I still have to patch it to support multiples schemes at once.
Now that won't solve your problem, unless, you replace terrain material schemes with yours, which is what you more or less supposed to do if you use schemes.
PatrickB3
22-09-2006 20:26:21
Yeah I was thinking I'm going to have to add the schemes to all materials. I was really hoping that I would only have to use them on things that actually need them but Ogre doesn't seem to play nice with materials that don't use schemes if some are using schemes. Makes material generation a much larger pain than it should be but now I'm suspicous that if PLSM couldn't handle it well maybe something else may not be able to either.
If all materials have the schemes than PLSM2 doesn't need any fixing because it works fine if every material has schemes. On the other hand I don't really see any reason for PLSM2 to support schemes on the terain as it has its own way to change the material used anyways which is more powerful than a scheme.
I think I'm gonna post the issue in the Ogre forums and see what they say as honestly schemes really suck and aren't implemented all that well. I really think they need a material definition that tells Ogre to use it for all schemes.
PatrickB3
22-09-2006 22:18:51
OK, Sinbad says it's a bug and he will fix in Dagon.
Ok, Material::getNumLodLevels should fall back on the first scheme in the same way Material::getBestTechnique does if the scheme isn't present, for consistency. We never used this method (relying only on getBestTechnique) which is why it's been missed. Will be fixed in Dagon.
You only need to make multiple techniques in a material if you want to customise it for a scheme. If you don't want to define multiple schemes fora material, don't - the default technique, or the first supported one if the default scheme doesn't exist, will be used instead.
So there isn't anything to fix in PLSM2.
tuan kuranes
23-09-2006 13:24:04
thanks for the report and clarification.