TextureLoader2 mipmap bug!

Hi!

Test case: create any texture of size (128x16) and try to load it with TextureLoader2 while specifying mipmap = true.
It will result in Exception:

java.lang.IndexOutOfBoundsException
at java.nio.Buffer.checkBounds(Unknown Source)
at java.nio.DirectByteBuffer.put(Unknown Source)
at com.xith3d.scenegraph.ImageComponent2D.setImage(ImageComponent2D.java:181)
at com.xith3d.scenegraph.ImageComponent2D.(ImageComponent2D.java:72)
at com.xith3d.loaders.texture.TextureLoader2.createTexture(TextureLoader2.java:571)
at com.xith3d.loaders.texture.TextureLoader2.createTexture(TextureLoader2.java:509)
at com.xith3d.loaders.texture.TextureLoader2.getTexture(TextureLoader2.java:408)
at com.xith3d.loaders.texture.TextureLoader2.getTexture(TextureLoader2.java:244)

I believe there are little “slip of pen” mistakes at the following lines (TextureLoader2):

in createTexture(BufferedImage img, int format, boolean mipmap, int width, int height):
581 int nextWidth = Math.max(1, width >> 1);
582 int nextHeight = Math.max(1, width >> 1); // should be height!!!

in createMipMaps(Texture2D tex, ImageComponent2D ic, boolean mipmap):
622 int nextWidth = Math.max(1, width >> 1);
623 int nextHeight = Math.max(1, width >> 1); // should be height!!!

I’m not sure really :), but at least no crash anymore :slight_smile:

Bohdan.

You got me :slight_smile: This was a easter egg for the careful reader.

No - of course not - it was what I call copy & pest…

Hi!

Just in case… want to point that this is not corrected yet on CVS… :slight_smile:
Anybody, or you Matthias (I just not sure if you have developer access…) can you please commit the change… Otherwise it going to be forgotten with the time…

Committed by anybody.

;D Thanks!

Hi!

It seems there is another bug in NEW TextureLoader (TextureLoader2) regarding mipmaps.

Here is test case of textured quad with “mipmap = true” and Minification filter (!!!) set to “MULTI_LEVEL_LINEAR”.




import java.io.File;

import javax.swing.JFrame;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import org.xith3d.test.util.TestUtils;

import com.xith3d.loaders.texture.TextureLoader;
import com.xith3d.loaders.texture.TextureStreamLocatorFile;
import com.xith3d.render.CanvasPeer;
import com.xith3d.render.RenderPeer;
import com.xith3d.render.jsr231.RenderPeerImpl;
import com.xith3d.scenegraph.Appearance;
import com.xith3d.scenegraph.BranchGroup;
import com.xith3d.scenegraph.Canvas3D;
import com.xith3d.scenegraph.Geometry;
import com.xith3d.scenegraph.Locale;
import com.xith3d.scenegraph.Shape3D;
import com.xith3d.scenegraph.Texture;
import com.xith3d.scenegraph.View;
import com.xith3d.scenegraph.VirtualUniverse;

public class TextureLoaderMipMap_and_MinFilter {

    public TextureLoaderMipMap_and_MinFilter() {
        JFrame frame = new JFrame("MipMap & MULTI_LEVEL_LINEAR MinFilter");
        frame.setSize(400, 400);
        //======= setting up Universe ==========================================
        VirtualUniverse My_Universe = new VirtualUniverse();
        Locale locale = new Locale();
        My_Universe.addLocale(locale);
        BranchGroup scRootBG  = new BranchGroup();
        locale.addBranchGraph(scRootBG);
        RenderPeer renderPeer = new RenderPeerImpl();
        CanvasPeer canvasPeer = renderPeer.
                       makeCanvas(frame.getContentPane(), 0, 0, 32, false);
        Canvas3D scrCanvas = new Canvas3D();
        scrCanvas.set3DPeer(canvasPeer);
        View scView = new View();
        scView.addCanvas3D(scrCanvas);
        My_Universe.addView(scView);
        //======================================================================
        Geometry quad = TestUtils.createQuad(
                new Point3f(-1f, -1f, 0), 
                new Point3f(-1f,  1f, 0), 
                new Point3f( 1f,  1f, 0), 
                new Point3f( 1f, -1f, 0), 
                1,1);
        Appearance app = new Appearance();
        scRootBG.addChild(new Shape3D(quad, app));
        //-----------------------------------------------
        TextureLoader tx_loader = TextureLoader.getInstance();
        tx_loader.addTextureStreamLocator(new TextureStreamLocatorFile(new File(".")));
        Texture tex = tx_loader.getTexture(
                "test.png",                
                TextureLoader.RGB,         
                true,                      // MipMap
                Texture.MULTI_LEVEL_LINEAR,// Min-Filter
                Texture.BASE_LEVEL,        // Mag-Filter
                Texture.WRAP               
        );
        //-----------------------------------------------
        app.setTexture(tex);
        //======= running ===============================
        frame.setVisible(true);
        float aMax = 20f;
        float aMin = 2.0f;
        float a = aMin;
        float da = 0.1f;
        while (frame.isVisible()) {
            a += da;
            if (a > aMax || a < aMin) da = -da;
            scView.getTransform().lookAt(
                    new Point3f (0, 0, a),
                    new Point3f (0, 0, 0),  
                    new Vector3f(0, 1, 0)
            );
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {}
            //------------------
            scView.renderOnce();
        }
        System.exit(0);
    }
    
    public static void main(String args[]) {
        new TextureLoaderMipMap_and_MinFilter();
    }
    
}

Texture used is attached as well as brief screenshots what is actually happening.

I have tested this with old TextureLoader and there is no such a problem.

Bohdan.

I noticed that bug, too but had no chance to resolve it.

It appeared to be actually not in the TextureLoader itself, but in “com.xith3d.image.PixelProcessorByteComponents”;

To fix, change in PixelProcessorByteComponents.calcMipMap(…), Line 48:


-  srcOff += srcLineSize;
+  srcOff += 2*srcLineSize;

Bohdan.

P.S. Amos (I’m afraid to add “anybody”…;D), would you please verify and commit?

comitted.

Thanks Qudus! :slight_smile:

EDIT:
Sorry, Qudus… if you could do little correction: “srcLineSize << 1” would be better than “2*srcLineSize”
It is not critical there anyhow… but “technically” better :slight_smile:

No problem. And done (blindly).

sh*t, too late. you beat me on this one, qud :wink: :wink:

Hi!

It appeared there is one more thing to fix regarding mipmaps this time apply to RGBA and LUMINANCE textures only.
Having that done everything is finaly working fine for me, so I think it should be done with TextureLoader now :).

So, “com.xith3d.image.PixelProcessorByteComponents.calcMipMap(…)”, Line 38:


- for(int x=0 ; x<srcWidth ; x+=2,srcOffX+=3) {
+ for(int x=0 ; x<srcWidth ; x+=2,srcOffX+=numComponents) {

Hardcoded “3” there would process with mipmaps like it is always RGB texture, which is wrong, should be “numComponents”.
Bug would show itself for RGBA and LUMINANCE textures, and results in funny artefacts (see attachment).

Bohdan.

Done.

(@Qudus : had this one, finally ^^)

Thanks Amos! :slight_smile: