0

Hi, sorry a bout this question but I have no Idea how I would texture something drawn by using glDrawElements? From what I gather you need to use glTexCoordPointer? but I'm still really confused.

public class DrawWater {

    public Expr2 func;  // The function that is being drawn.
    private String functionInput;
    private boolean version_1_5;  // Check is OpenGL 1.5 is available; set in init().
    public boolean dataIsValid;  // Set to true whenever data needs to be recomputed.
    public double xMax = 5;
    public double yMax = 5;
    private int[] textures = new int[3];            // Storage For 3 Textures
    // This is checked in the display() method before drawing.
    /* Buffers to hold the points and normals for the surface. */
    private FloatBuffer vBuf = BufferUtil.newFloatBuffer(201 * 201 * 3);
    private FloatBuffer nBuf = BufferUtil.newFloatBuffer(201 * 201 * 3);

    /* Buffers to hold the indices for drawing the surface and lines with glDrawElements*/
    private IntBuffer surfaceIndexBuffer = BufferUtil.newIntBuffer(200 * 201 * 2);
    private IntBuffer xLineIndexBuffer = BufferUtil.newIntBuffer(21 * 201);
    private IntBuffer yLineIndexBuffer = BufferUtil.newIntBuffer(21 * 201);

    /* VBO ID numbers for holding the data when OpenGL version is 1.5 or higher */
    private int vertexVBO, normalVBO;            // VBO IDs for surface data.
    private int xLineVBO, yLineVBO, surfaceVBO;  // VBO IDs for index data.

    public DrawWater() {
    }

    public void setup(GL gl, String equ) {

        this.functionInput = equ;
        this.func = new Expr2(equ);
    }

    public void draw(GL gl) {

        version_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5");

        if (gl.isExtensionAvailable("GL_VERSION_1_3")) {
            gl.glEnable(GL.GL_MULTISAMPLE);
        }

        makeElementBuffers();  // Generate lists of indices for glDrawElements.  This data never changes.

        if (version_1_5) {
            // Generate VBOs for the data, and fill the ones that are for index data with
            // data from Java nio buffers.  The VBOs for index data won't change again and
            // so use GL.GL_STATIC_DRAW.
            int[] ids = new int[5];
            gl.glGenBuffers(5, ids, 0);

            this.vertexVBO = ids[0];
            this.normalVBO = ids[1];
            this.xLineVBO = ids[2];
            this.yLineVBO = ids[3];
            this.surfaceVBO = ids[4];

            gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
            gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
            gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO);
            gl.glNormalPointer(GL.GL_FLOAT, 0, 0);
            gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
            gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO);
            gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 2 * 200 * 201, surfaceIndexBuffer, GL.GL_STATIC_DRAW);
            gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, xLineVBO);
            gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, xLineIndexBuffer, GL.GL_STATIC_DRAW);
            gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, yLineVBO);
            gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, yLineIndexBuffer, GL.GL_STATIC_DRAW);
            gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);

        } else {

            gl.glVertexPointer(3, GL.GL_FLOAT, 0, vBuf);
            gl.glNormalPointer(GL.GL_FLOAT, 0, nBuf);

        }



        this.dataIsValid = false;  // Force recomputation of data with new graph definition.

        if (func != null) {

            gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, new float[]{0.7f, 0.7f, 1}, 0);
            gl.glMaterialfv(GL.GL_BACK, GL.GL_AMBIENT_AND_DIFFUSE, new float[]{0.8f, 0.8f, 0.5f}, 0);

            if (!dataIsValid) {
                this.computeSurfaceData();
                if (version_1_5) {
                    // Set up VBOs for surface points and normals. Since these change
                    // pretty regularly, use GL.GL_DYNAMIC_DRAW.
                    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
                    gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 3 * 201 * 201, vBuf, GL.GL_DYNAMIC_DRAW);
                    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO);
                    gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 3 * 201 * 201, nBuf, GL.GL_DYNAMIC_DRAW);
                    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
                }
            }
            gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL.GL_NORMAL_ARRAY);

            this.drawSurface(gl);  // Just draw the surface.

            gl.glPolygonOffset(1, 1);
            gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);

            this.drawSurface(gl);

            gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
            gl.glDisable(GL.GL_LIGHTING);
            gl.glColor3f(0, 0, 0);
            gl.glDisableClientState(GL.GL_NORMAL_ARRAY);

            gl.glEnable(GL.GL_LIGHTING);
        }
        gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL.GL_NORMAL_ARRAY);


    }



    private void makeElementBuffers() {
        for (int i = 0; i < 201; i += 10) {  // indices for drawing lines in x-direction
            for (int j = 0; j < 201; j++) {
                this.xLineIndexBuffer.put(201 * i + j);
            }
        }
        for (int i = 0; i < 201; i += 10) {  // indices for drawing lines in y-direction
            for (int j = 0; j < 201; j++) {
                this.yLineIndexBuffer.put(201 * j + i);
            }
        }
        for (int i = 0; i < 200; i++) {   // indices for drawing surface with GL_TRIANGLE_STRIPs
            for (int j = 0; j < 201; j++) {
                this.surfaceIndexBuffer.put(201 * (i + 1) + j);
                this.surfaceIndexBuffer.put(201 * i + j);
            }
        }
        this.xLineIndexBuffer.rewind();
        this.yLineIndexBuffer.rewind();
        this.surfaceIndexBuffer.rewind();
    }

    private void computeSurfaceData() {
        double xmin = -xMax;
        double xmax = xMax;
        double ymin = -yMax;
        double ymax = yMax;
        double xRes = 200;
        double yRes = 200;
        float[] surfaceData = new float[301 * 3];
        float[] normalData = new float[301 * 3];
        double dx = (xmax - xmin) / xRes;
        double dy = (ymax - ymin) / yRes;

        for (int i = 0; i <= xRes; i++) {
            int v = 0;
            int n = 0;
            double y1 = ymin + dy * i;

            for (int j = 0; j <= yRes; j++) {
                double x = xmin + dx * j;
                func.setVariable('x', x);
                func.setVariable('y', y1);
                double z1 = func.value();
                float[] normal1 = computeUnitNormal(x, y1);
                surfaceData[v++] = (float) x;
                surfaceData[v++] = (float) y1;
                surfaceData[v++] = (float) z1;
                normalData[n++] = normal1[0];
                normalData[n++] = normal1[1];
                normalData[n++] = normal1[2];
            }
            vBuf.put(surfaceData, 0, 201 * 3);
            nBuf.put(normalData, 0, 201 * 3);
        }
        vBuf.rewind();
        nBuf.rewind();
        dataIsValid = true;
    }

    /**
     * Draw the surface as a series of triangle strips.
     */
    private void drawSurface(GL gl) {


        if (version_1_5) {
            gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO);
            for (int i = 0; i < 200; i++) {
                gl.glTexCoordPointer(3, GL.GL_TRIANGLE_STRIP, 402, nBuf);
                gl.glDrawElements(GL.GL_TRIANGLE_STRIP, 402, GL.GL_UNSIGNED_INT, 402 * i * 4);
            }
            gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
        } else {
            for (int i = 0; i < 200; i++) {
                surfaceIndexBuffer.position(402 * i);
                gl.glDrawElements(GL.GL_TRIANGLE_STRIP, 402, GL.GL_UNSIGNED_INT, surfaceIndexBuffer);
            }
        }
    }

    /**
     * Compute a unit normal to the graph of z = func(x,y).
     * This is only an approximation, using nearby points instead
     * of exact derivatives.
     */
    private float[] computeUnitNormal(double x, double y) {
        double epsilon = 0.00001;
        func.setVariable('x', x);
        func.setVariable('y', y);
        double z = this.func.value();
        func.setVariable('x', x + epsilon);
        double z1 = func.value();
        func.setVariable('x', x);
        func.setVariable('y', y + epsilon);
        double z2 = this.func.value();
        // normal is (epsilon,0,z1-z) X (0,epsilon,z2-z)
        double a = -epsilon * (z1 - z);
        double b = -epsilon * (z2 - z);
        double c = epsilon * epsilon;
        double length = Math.sqrt(a * a + b * b + c * c);

        if (Double.isNaN(length) || Double.isInfinite(length)) {
            return new float[]{0, 0, 1};
        } else {
            return new float[]{(float) (a / length), (float) (b / length), (float) (c / length)};
        }

    }

    private void loadGLTextures(GLAutoDrawable gldrawable) throws IOException {
        TextureReader.Texture texture = null;
        texture = TextureReader.readTexture("data/images/04.bmp");

        GL gl = gldrawable.getGL();

        //Create Nearest Filtered Texture
        gl.glGenTextures(1, textures, 0);
        gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);

        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);

        gl.glTexImage2D(GL.GL_TEXTURE_2D,
                0,
                3,
                texture.getWidth(),
                texture.getHeight(),
                0,
                GL.GL_RGB,
                GL.GL_UNSIGNED_BYTE,
                texture.getPixels());
    }
}

Any help or advise would help I'm just confused ?

2
Contributors
1
Reply
2
Views
6 Years
Discussion Span
Last Post by emilo35
0

Hi there. I'm sorry to say that I'm not going to set up the jogl environment for the sole purpose of debugging/finding a solution for you here. However, looking through the code (not analyzing your algorithms too closely) I thought I still might be able to push you in the right direction. First, I wonder, is this something taken from a tutorial, and that actually should work, or is it something you wrote?

To me it looks like the texture coordinates are calculated to your quads when drawing them. This will only happen if gl.isExtensionAvailable("GL_VERSION_1_5") returns true. If you get this far, you must make sure that you call loadGLTextures(GLAutoDrawable gldrawable) upon init, and that you have an image named "data/images/04.bmp" that also should have a dimension that is a power of two.

If your texture(s) loads fine, then you could try enabling 2D texures with gl.glEnable(GL.GL_TEXTURE_2D); and also binding the particular texture you're interested in with gl.glBindTexture(GL.GL_TEXTURE_2D, textures[/* Texture ID here */]); before drawing.

I hope any of this helps, and make sure to let me know how everything turns out for you!

Regards,
Emil Olofsson

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.