Witam,
mam dosyć ciekawy problem. Mianowicie chciałem wykorzystać AsyncTask do ładowania tekstur do własnego managera.
Klasa ładowania wygląda mniej więcej w ten sposób:
private class DoSomeWork extends AsyncTask<String, Void, String>
{
@Override
protected String doInBackground(String... params)
{
// Tutaj kod ładowania
textureManager.load(....);
// ...
textureManager.load(....);
return null;
}
@Override
protected void onPostExecute(String result)
{
// zamiana aktywnej sceny na inną, zwykle zmiana widoku "ładowanie, proszę czekać" na menu etc.
}
}
Niestety po wykonaniu takiej operacji wszystkie tekstury, które zostały wczytane w wątku są białe. Bez wątków wszystko jest ok.
Macie jakieś pomysły co może być nie tak?
W razie czego klasa do tekstur obecnie wygląda następująco:
public class TextureManager
{
private static volatile TextureManager mInstance;
private HashMap<String, Texture> mTextureHashMap;
private GL10 gl;
private AssetManager assetManager;
private TextureManager()
{
mTextureHashMap = new LinkedHashMap<String, Texture>();
}
public static TextureManager getInstance()
{
if (mInstance == null)
{
mInstance = new TextureManager();
}
return mInstance;
}
// Methods
public Texture loadTexture(String pathName)
{
String[] filePathArray = pathName.split("/");
String fileName = filePathArray[filePathArray.length - 1];
if (!mTextureHashMap.containsKey(fileName))
{
Bitmap loadedBitmap = getBitmapFromAsset(pathName);
if (loadedBitmap == null)
return null;
Texture internalTex = new Texture(gl, loadedBitmap);
mTextureHashMap.put(fileName, internalTex);
}
return getTexture(fileName);
}
public Texture getTexture(String fileName)
{
return mTextureHashMap.get(fileName);
}
private Bitmap getBitmapFromAsset(String pathName)
{
try
{
InputStream istr = assetManager.open(pathName);
Bitmap bitmap = BitmapFactory.decodeStream(istr);
return bitmap;
}
catch (IOException e)
{
Log.e("CatEngine: loadTexture", "No such file: " + pathName);
e.printStackTrace();
}
return null;
}
public void setGL(GL10 gl)
{
this.gl = gl;
}
public void setAssetManager(AssetManager assetManager)
{
this.assetManager = assetManager;
}
public void destroy()
{
mTextureHashMap.clear();
mInstance = null;
}
}
Bym zapomniał klasa Texture:
public class Texture
{
protected int[] mTexture = new int[1];
protected HashMap<String, TextureRegion> mTextureRegionHashMap;
protected Size imageSize;
protected Size textureSize;
public Texture(GL10 gl, Bitmap bitmap)
{
mTextureRegionHashMap = new HashMap<String, TextureRegion>();
float mRegionCoords[] = new float[] { // Mapping coordinates for the
// vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
// Getting parameters from bitmap
imageSize = new Size(bitmap.getWidth(), bitmap.getHeight());
int textureWidth = (int) imageSize.width;
int textureHeight = (int) imageSize.height;
// Checking if this is texture in meaning of openGL
if (isPowerOfTwo(textureWidth))
textureWidth = nextPowerOfTwo(textureWidth);
if (isPowerOfTwo(textureHeight))
textureHeight = nextPowerOfTwo(textureHeight);
// Resizing bitmap to fit power of two dimensions
if (textureWidth != bitmap.getWidth() || textureHeight != bitmap.getHeight())
{
Bitmap tmpBitmap = Bitmap.createBitmap(textureWidth, textureHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(tmpBitmap);
mRegionCoords[1] = (float) bitmap.getHeight() / (float) textureHeight;
mRegionCoords[5] = (float) bitmap.getHeight() / (float) textureHeight;
mRegionCoords[4] = (float) bitmap.getWidth() / (float) textureWidth;
mRegionCoords[6] = (float) bitmap.getWidth() / (float) textureWidth;
canvas.drawBitmap(bitmap, new Matrix(), null);
bitmap = tmpBitmap;
}
textureSize = new Size(textureWidth, textureHeight);
// Generate one texture pointer and bind it to our array
gl.glGenTextures(1, mTexture, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTexture[0]);
// Create nearest filtered texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Use Android GLUtils to specify a two-dimensional texture image from
// our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// Clean up
bitmap.recycle();
// Adding default regions to hash map
mTextureRegionHashMap.put("default", new TextureRegion(mRegionCoords));
}
public int getTexturePointer()
{
return mTexture[0];
}
public FloatBuffer getTextureBuffer()
{
return mTextureRegionHashMap.get("default").textureBuffer;
}
public FloatBuffer getTextureBuffer(String id)
{
return mTextureRegionHashMap.get(id).textureBuffer;
}
public Size getSize()
{
return imageSize;
}
public void addTextureRegion(String id, Point point, Size regionSize)
{
if (mTextureRegionHashMap.get(id) == null)
{
mTextureRegionHashMap.put(id, new TextureRegion(point, regionSize, textureSize));
}
}
public TextureRegion getTextureRegion(String textureRegionID)
{
return mTextureRegionHashMap.get(textureRegionID);
}
public TextureRegion[] getAnimationTextureRegions(String animationName, Size frameSize, int frames)
{
float width = frameSize.width;
TextureRegion regions[] = new TextureRegion[frames];
for (int i = 0; i < frames; i++)
{
regions[i] = new TextureRegion(new Point(i * width, 0), frameSize, textureSize);
}
return regions;
}
public int nextPowerOfTwo(int value)
{
if (value == 0)
return 1;
if ((value & value - 1) == 0)
return value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
}
public boolean isPowerOfTwo(int value)
{
return value != 0 && (value & value - 1) == 0;
}
}
I klasa region:
public class TextureRegion
{
Size regionSize;
float mRegionCoords[];
FloatBuffer textureBuffer;
ByteBuffer mByteBuffer;
Size size;
public TextureRegion(float[] regionCoords)
{
mRegionCoords = regionCoords;
mByteBuffer = ByteBuffer.allocateDirect(32);
mByteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = mByteBuffer.asFloatBuffer();
textureBuffer.put(mRegionCoords);
textureBuffer.position(0);
}
public TextureRegion(Point point, Size regionSize, Size textureSize)
{
this.regionSize = regionSize;
float x = point.x;
float y = point.y;
float width = regionSize.width;
float height = regionSize.height;
float texWidth = textureSize.width;
float texHeight = textureSize.height;
mRegionCoords = new float[]{ // Mapping coordinates for the vertices`
x / texWidth, (y + height) / texHeight, // top left (V2)
x / texWidth, y / texHeight, // bottom left (V1)
(x + width) / texWidth, (y + height) / texHeight, // top right (V4)
(x + width) / texWidth, y / texHeight // bottom right (V3)
};
mByteBuffer = ByteBuffer.allocateDirect(32);
mByteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = mByteBuffer.asFloatBuffer();
textureBuffer.put(mRegionCoords);
textureBuffer.position(0);
}
public void updateBuffer()
{
textureBuffer.clear();
textureBuffer = mByteBuffer.asFloatBuffer();
textureBuffer.put(mRegionCoords);
textureBuffer.position(0);
}
public Size getSize()
{
return regionSize;
}
public FloatBuffer getTextureBuffer()
{
return textureBuffer;
}
}