jPCT-AE - a 3d engine for Android > Support

Out of memory

(1/5) > >>

Kaiidyn:
I'm starting to get really frustrated with this error...


--- Code: --- Out of memory on a 3527724-byte allocation.
 FATAL EXCEPTION: GLThread 9
 java.lang.OutOfMemoryError
     at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:93)
     at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:218)
     at com.threed.jpct.ZipHelper.unzip(ZipHelper.java:30)
     at com.threed.jpct.GLRenderer.convertTexture(GLRenderer.java:766)
     at com.threed.jpct.GLRenderer.setTextures(GLRenderer.java:2151)
     at com.threed.jpct.GLRenderer.drawVertexArray(GLRenderer.java:2064)
     at com.threed.jpct.World.draw(World.java:1341)
     at com.threed.jpct.World.draw(World.java:1122)
     at gp.itsolutions.Render.onDrawFrame(Render.java:87)
     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1332)
     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)
--- End code ---

I am rewriting and cleaning the code for what I have now in my mmo game (in a separate project)
and get this error when (I think) loading the terrain from zip file (as ZipHelper is mentioned in the error)
But the fact is, I did not change anything compared to my old code, except for the fact that I created a separate class for loading and disposing the terrain...

Terrain class:

--- Code: ---public class Terrain {
private Object3D terrain = null;
private Texture terrainTexture = null;
private ZipInputStream zis = null;

public Terrain(World world){
try {

if(terrainTexture == null)
terrainTexture = new Texture(Gameplay.resources.openRawResource(R.raw.terraintexture));

if(!TextureManager.getInstance().containsTexture("terrainTexture"))
TextureManager.getInstance().addTexture("terrainTexture", terrainTexture);

if(zis == null){
zis = new ZipInputStream(Gameplay.resources.openRawResource(R.raw.terrain));
zis.getNextEntry();
}

if( (terrain == null) && (zis != null) ){

terrain = Loader.loadSerializedObject(zis);

terrain.setScale(20);
terrain.setTexture("terrainTexture");
//F.tileTexture(terrain, 25);
terrain.compile();
terrain.build();
world.addObject(terrain);

}

} catch (Exception e) {
e.printStackTrace();
}
}

public void dispose(){
if(terrainTexture != null){ terrainTexture = null; }
if(terrain != null){ terrain = null; }
if(zis != null){ try { zis.close(); } catch (IOException e) { } zis = null; }
}
}
--- End code ---

I have tried several attempts to try and fix it, but I can't get the right one..
Figured a second pair of eyes might help..

EgonOlsen:
It crashes while converting the texture (how large is it?) not while loading the zip. You can easily spot that in the stack trace.
I've a few hints, but i don't think that they'll cut it:


* Don't store the zis in the class but move it into the method instead. You don't need it after loading, it just eats some memory for no gain.
* Try to call strip() on the terrain to free some memory.
* Try to use 4bpp for the texture by calling enable4bpp(true);
* Try to compile the terrain using indexed geometry by calling forceGeometryIndices(true);

EgonOlsen:
And another one:


* Load the texture first, add it to the TextureManager, call preWarm() on the TextureManager and then load the model.

Kaiidyn:
The preWarm on the TextureManager fixed the first problem :)


--- Code: ---public class Terrain {
private Object3D terrain = null;
private Texture terrainTexture = null;

public Terrain(World world){


if(terrainTexture == null){
terrainTexture = new Texture(Gameplay.resources.openRawResource(R.raw.terraintexture));
terrainTexture.enable4bpp(true);
}
if(!TextureManager.getInstance().containsTexture("terrainTexture"))
TextureManager.getInstance().addTexture("terrainTexture", terrainTexture);

TextureManager.getInstance().preWarm(Gameplay.render.frameBuffer);

ZipInputStream zis = new ZipInputStream(Gameplay.resources.openRawResource(R.raw.terrain));
try {
zis.getNextEntry();
} catch (IOException e) {
throw new RuntimeException(e);
}

if( (this.terrain == null) ){

this.terrain = Loader.loadSerializedObject(zis);
this.terrain.strip();
this.terrain.setScale(20);
this.terrain.setTexture("terrainTexture");
//F.tileTexture(terrain, 25);
this.terrain.forceGeometryIndices(true);
this.terrain.compile();
this.terrain.build();
world.addObject(this.terrain);

}else{
Log.e("Terrain already loaded..");
}

try {
zis.close();
zis = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public void dispose(){
if(terrainTexture != null){ terrainTexture = null; }
if(terrain != null){ terrain = null; }
}
}
--- End code ---
Do I still need to call terrain.compile() after terrain.forceGeometryIndices(true) ? (or before?)
And is this the proper way to use enable4bpp, as I assume the texture is already being loaded when initializing the terrainTexture variable, the enable4bpp will need to convert it to 4bpp which in turn will consume more memory (or cpu)

When I call onStop and dispose everything (or nullify) and restart the game, it is giving another out of memory error

--- Code: --- ERROR/dalvikvm-heap(4283): 288000-byte external allocation too large for this process.
 FATAL EXCEPTION: GLThread 10
 java.lang.OutOfMemoryError
     at org.apache.harmony.luni.platform.OSMemory.malloc(Native Method)
     at org.apache.harmony.luni.platform.PlatformAddressFactory.alloc(PlatformAddressFactory.java:150)
     at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:66)
     at java.nio.ReadWriteDirectByteBuffer.<init>(ReadWriteDirectByteBuffer.java:51)
     at java.nio.BufferFactory.newDirectByteBuffer(BufferFactory.java:93)
     at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:68)
     at com.threed.jpct.CompiledInstance.fill(CompiledInstance.java:698)
     at com.threed.jpct.Object3DCompiler.compile(Object3DCompiler.java:136)
     at com.threed.jpct.World.compile(World.java:2037)
     at com.threed.jpct.World.renderScene(World.java:1087)
     at gp.itsolutions.Render.onDrawFrame(Render.java:86)
     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1332)
     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)
--- End code ---
Not sure what this means, or how to fix it.

Edit: It appears I start my game too fast after I shut it down, when I wait a couple of seconds it does work..  :D
edit2: It happens randomly now...  :-\

EgonOlsen:
Call forceGeometryIndices() before compile(). Your way to enable 4bpp is fine. The call itself doesn't consume one single byte of memory. The conversion happens during the upload process to the GPU. The texture data in memory is always 8bpp no matter which setting you use.

The second exception is an indication that you are not disposing and nullifying everything as needed. Keep in mind that for example

--- Code: ---a=new int[1000];
a=new int[1000];

--- End code ---

hasn't the same memory footprint as


--- Code: ---a=new int[1000];
a=null;
a=new int[1000];

--- End code ---

Apart from all that, you already seem to live on the edge of memory...you won't get very far with this as the game commences IMHO. What's the polygon count of the terrain, what's the size of the texture? Something seems to be too big here...


Navigation

[0] Message Index

[#] Next page

Go to full version