I have a Control which creates a ByteBuffer, from that an Image and from there a Texture2D. In the setSpatial method, I add a MatParamOverride to the spatial to use this texture, and now I have a Control which can dynamicly update the Texture by writing to the ByteBuffer. This works like a charm.
But here comes the trouble: I want to save and load these spatials, together with the Control and the generated texture. Since I need access to the ByteBuffer again after loading, I thought to save the ByteBuffer in the write method. Then in the read method, just read the buffer and recreate the Image, Texture and MatParamOverride accordingly. This seems to work, until I write anything to the ByteBuffer, it now seems to have changed format from ARGB to RGBA or something…
I created a minimal demonstration here: GitHub - smeaggie/ImageTest
In this test case, on first run it will create a savegame with a generated brownish texture. Pressing “T” will call update() on the control, which will put the same brown color on the ByteBuffer, so the cube should NOT change color. Now quit, comment out the first part (lines 37-47) and uncomment the LoadGame calls (lines 49-50). Now the cube has the correct color to begin with, but pressing “T” will change the color. It gets a lot of blue, which hints to me the A and B channels are swapped at least?
A quick solution seems to be to read the ByteBuffer into a temporary buffer and recreate the ByteBuffer using ByteBuffer.allocateDirect() like this:
@Override()
public void read(JmeImporter im) throws IOException {
super.read(im);
ByteBuffer temp = im.getCapsule(this).readByteBuffer("buffer", null);
buffer = ByteBuffer.allocateDirect(128 * 128 * 4);
buffer.position(0);
temp.position(0);
buffer.put(temp);
...etc...
So what happens here? Am I abusing the save/load system? The Image/Texture system? Is there a problem with saving/loading ByteBuffers? I’m happy with the workaround but I can’t seem to figure out what went wrong and I really just like to know if this is some error on my part…
For completeness, this is my system info from the SDK:
Product Version: jMonkeyEngine SDK v3.5.2-stable
Java: 11.0.17; OpenJDK 64-Bit Server VM 11.0.17+8
Runtime: OpenJDK Runtime Environment 11.0.17+8
System: Linux version 5.15.0-67-generic running on amd64; UTF-8; en_US (jmonkeyplatform)
[EDIT]:
this might be interesting, found the BufferUtils.createByteBuffer() so I updated the ScreenControl to create the initial Buffer like this:
buffer = BufferUtils.createByteBuffer(128 * 128 * 4);
and now the cube is blueish from the start and never actually brown. Could the answer lay in the difference in endianness? ByteBuffer.allocateDirect() gives BIG_ENDIAN, the BufferUtils.createByteBuffer() creates a LITTLE_ENDIAN buffer. Changing endianness seems a good way to swap color channels somewhere…