Hello,
I have been digging around a little for the memory issues I have concerning texture uploading since I do use pretty huge textures.
It seems that jPCT-AE requires twice the size of a texture (in peak memory usage) in JVM RAM: the original pixeldata of the texture + the buffer used for uploading.
But I believe that on modern day devices you can actually use tricks to consume near nothing in the JVM RAM when loading such huge textures.
I believe jPCT-AE doesn't support these features out of the box because it's been directly ported from the PC version and to provide backwards compatibility with the very old devices.
Here's the class I use to upload textures now (feel free to use it or make your own modifications to it):
package com.aeroshark333.artofearthify.utils;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import com.threed.jpct.RGBColor;
import com.threed.jpct.Texture;
// Created by Abiram/AeroShark333
public class CustomTexture extends Texture {
final Bitmap bmp;
public CustomTexture(Bitmap image) {
super(2, 2, RGBColor.BLACK);
this.bmp = image;
}
public int loadTexture(final boolean forceNearest, final boolean keepInMemory){
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
if (!forceNearest) {
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
}else {
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
}
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
if (!keepInMemory) {
bmp.recycle();
}
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
this.setExternalId(textureHandle[0],GLES20.GL_TEXTURE_2D);
return textureHandle[0];
}
}
One could use the CustomTexture constructor from any Thread but the CustomTexture#loadTexture(boolean,boolean) method needs to be called from the GLThread.
This implementation is kinda very simple and it doesn't cover all of jPCT-AE's texture features (and it probably isn't really (easily) possible to have texture manipulation/effects like jPCT-AE supports them out of the box). However, the uploading process seems much faster using this method too. Also, this could potentially solve memory issues if you have them.
Now, I did say you could use near nothing in JVM RAM, so what about the Bitmap that is passed to this CustomTexture?
Well, as since Android 8.0, you can load Bitmap's immediately into the hardware-level (probably GPU..?), meaning that the Bitmap is not stored in the JVM RAM.
That is if you use Bitmap.Config.HARDWARE when you decode your image file (from resources, online of file):
https://developer.android.com/reference/android/graphics/Bitmap.Config#HARDWARE.
Unfortunately, jPCT-AE does not seem to support Bitmap's that have been created using this Config, because of the immutability and inaccessibility of the Bitmap pixels.
However, but the CustomTexture class would work with Bitmap's that are using this Config.
I hope this could be useful for someone someday.
Feel free to give your thoughts and ideas
Cheers,
Abiram