How to add colors or normals to custom object?

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

How to add colors or normals to custom object?

Chaz
Yo. I have next task: load heightmap and visualize it like a 3D object. Actually I already did it using simple GL_ARRAY_BUFFER and DrawArrays.
But my image totally has not any normals, or seems that all normals are the same. (Lighting is enabled).
I tried example where was used glVertexAttribPointer, but i got fatal error when try assign color's data.
Here is my 3 main functions.

 public void CreateBuffer(GL2 gl) // creating buffers with vertex and color data
    {
        this.gl=gl;
        targetsBuffer = Buffers.newDirectIntBuffer(2);
        gl.glGenBuffers(2, targetsBuffer);

        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, targetsBuffer.get(0));
        gl.glBufferData(GL.GL_ARRAY_BUFFER, fBuff.capacity() * Buffers.SIZEOF_FLOAT, fBuff, GL.GL_STATIC_DRAW);

        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, targetsBuffer.get(1));
        gl.glBufferData(GL.GL_ARRAY_BUFFER, cBuff.capacity() * Buffers.SIZEOF_FLOAT, cBuff, GL.GL_STATIC_DRAW); // here I got exception (fatal error)

        CreateVAO();
    }

    public void CreateVAO() // creating something that should help me to colorize my object
    {
        IntBuffer id = Buffers.newDirectIntBuffer(1);
        gl.glGenVertexArrays(1,id);

        gl.glBindVertexArray(id.get(0));
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, targetsBuffer.get(0));
        gl.glVertexAttribPointer(0, 3, GL2.GL_FLOAT,false,0,0);

        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,targetsBuffer.get(1));
        gl.glVertexAttribPointer(1, 3, GL2.GL_FLOAT,false,0,0);

    }

    @Override
    public void Draw(){
        gl.glEnableVertexAttribArray(0);
        gl.glEnableVertexAttribArray(1);

        gl.glBindVertexArray(0);

        gl.glDrawArrays(GL2.GL_QUADS, 0, fBuff.capacity() / 3);

        gl.glDisableVertexAttribArray(0);
        gl.glDisableVertexAttribArray(1);
    }

So what I do wrong?

UPD: Actually I understood where is was 1 of my faults - i have to call rewind() for cBuff. And I had change Draw function to this
 public void Draw(){
        gl.glBindVertexArray(1);

        gl.glEnableVertexAttribArray(0);
        gl.glEnableVertexAttribArray(1);

        gl.glDrawArrays(GL2.GL_QUADS, 0, fBuff.capacity() / 3);

        gl.glDisableVertexAttribArray(0);
        gl.glDisableVertexAttribArray(1);
    }

Now I don't got exceptions, but I still don't see colors on my object. Here is function in which I initialize and filling the buffers.

 private void Import(String path) throws Exception
    {
        byte[] bytes = Files.readAllBytes(Paths.get(path));
        int resolution = (int)Math.sqrt(bytes.length/4);
        float[] floats=new float[resolution*resolution];
        ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer().get(floats);

        this.heightStickLength=this.widthStickLength=resolution;
        this.heightScale=1;

        minHeight=Float.MAX_VALUE;
        maxHeight = Float.MIN_VALUE;

        for(int i = 0; i<floats.length; i++)
        {
            floats[i]=floats[i]*600f;
        }

        for(float f : floats)
        {
            if(f>maxHeight) maxHeight=f;
            if(f<minHeight) minHeight=f;
        }

        CreateColliderShape(floats);

        System.out.println("Max height: "+maxHeight+" Min height: "+minHeight);

        float step = 2000/513f;
        float optiStep=1;

        fBuff = Buffers.newDirectFloatBuffer(resolution*resolution*3*4/(int)optiStep);
        cBuff = Buffers.newDirectFloatBuffer(resolution*resolution*3*4/(int)optiStep);

        for(int i =0; i<resolution-1; i+=optiStep)
        {
            for(int j =0; j<resolution-1; j+=optiStep)
            {
                float x1=i*step,y1=floats[(j)*resolution+(resolution-1-i)],z1=j*step;

                float x2=i*step+step,y2=floats[(j)*resolution+(resolution-2-i)],z2=j*step;

                float x3=i*step+step,y3=floats[(j+1)*resolution+(resolution-2-i)],z3=j*step+step;

                float x4=i*step,y4=floats[(j+1)*resolution+(resolution-1-i)],z4=j*step+step;

                    fBuff.put(x1); cBuff.put(1);
                    fBuff.put(y1); cBuff.put(0);
                    fBuff.put(z1); cBuff.put(0);

                    fBuff.put(x2); cBuff.put(1);
                    fBuff.put(y2); cBuff.put(0);
                    fBuff.put(z2); cBuff.put(0);

                    fBuff.put(x3); cBuff.put(1);
                    fBuff.put(y3); cBuff.put(0);
                    fBuff.put(z3); cBuff.put(0);

                    fBuff.put(x4); cBuff.put(1);
                    fBuff.put(y4); cBuff.put(0);
                    fBuff.put(z4); cBuff.put(0);
            }
        }

        fBuff.rewind();
        cBuff.rewind();
    }
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

gouessej
Administrator
Hi

Why not looking at this example?
http://jogamp.org/git/?p=jogl-demos.git;a=blob;f=src/demos/es2/RawGL2ES2demo.java;hb=HEAD

Your source code is incomplete, maybe your object is simply not in the view frustum.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
Now all right. Problem was in light position. It was (x,y,z,0), instead of (x,y,z,1) xD
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
In reply to this post by gouessej
No no no! I was wrong. I saw shape of the terrain just because my light was in point mode with light fading. And different parts of shape has different colours. But my normals still does not works.
In your example I see shaders and do not see any VBO and DrawArray call so I guess it useful for me.
Now I changed my code to this.

 private void Import(String path) throws Exception
    {
        byte[] bytes = Files.readAllBytes(Paths.get(path));
        int resolution = (int)Math.sqrt(bytes.length/4);
        float[] floats=new float[resolution*resolution];
        ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer().get(floats);

        this.heightStickLength=this.widthStickLength=resolution;
        this.heightScale=1;

        minHeight=Float.MAX_VALUE;
        maxHeight = Float.MIN_VALUE;

        for(int i = 0; i<floats.length; i++)
        {
            floats[i]=floats[i]*600f;
        }

        for(float f : floats)
        {
            if(f>maxHeight) maxHeight=f;
            if(f<minHeight) minHeight=f;
        }

        CreateColliderShape(floats);

        System.out.println("Max height: "+maxHeight+" Min height: "+minHeight);

        float step = 2000/513f;
        float optiStep=1;

        fBuff = Buffers.newDirectFloatBuffer(resolution*resolution*3*4/(int)optiStep);
        nBuff = Buffers.newDirectFloatBuffer(fBuff.capacity()/3);

        for(int i =0; i<resolution-1; i+=optiStep)
        {
            for(int j =0; j<resolution-1; j+=optiStep)
            {
                float x1=i*step,y1=floats[(j)*resolution+(resolution-1-i)],z1=j*step;

                float x2=i*step+step,y2=floats[(j)*resolution+(resolution-2-i)],z2=j*step;

                float x3=i*step+step,y3=floats[(j+1)*resolution+(resolution-2-i)],z3=j*step+step;

                float x4=i*step,y4=floats[(j+1)*resolution+(resolution-1-i)],z4=j*step+step;

                    fBuff.put(x1);
                    fBuff.put(y1);
                    fBuff.put(z1);

                    fBuff.put(x2);
                    fBuff.put(y2);
                    fBuff.put(z2);

                    fBuff.put(x3);
                    fBuff.put(y3);
                    fBuff.put(z3);

                    fBuff.put(x4);
                    fBuff.put(y4);
                    fBuff.put(z4);

                float n = 0.5f;
                    nBuff.put(n);
                    nBuff.put(n);
                    nBuff.put(n);
                    nBuff.put(n);
            }
        }

        fBuff.rewind();
        nBuff.rewind();
    }

    public void CreateBuffer(GL2 gl)
    {
        this.gl=gl;
        targetsBuffer = Buffers.newDirectIntBuffer(2);
        gl.glGenBuffers(2, targetsBuffer);

        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, targetsBuffer.get(0));
        gl.glBufferData(GL.GL_ARRAY_BUFFER, fBuff.capacity() * Buffers.SIZEOF_FLOAT, fBuff, GL.GL_STATIC_DRAW);

        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, targetsBuffer.get(1));
        gl.glBufferData(GL.GL_ARRAY_BUFFER, nBuff.capacity() * Buffers.SIZEOF_FLOAT, nBuff, GL.GL_STATIC_DRAW);

        CreateVAO();
    }

    public void CreateVAO()
    {
        IntBuffer id = Buffers.newDirectIntBuffer(1);
        gl.glGenVertexArrays(1,id);

        gl.glBindVertexArray(id.get(0));
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, targetsBuffer.get(0));
        gl.glVertexAttribPointer(0, 3, GL2.GL_FLOAT,false,0,0);

        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,targetsBuffer.get(1));
        gl.glVertexAttribPointer(1, 3, GL2.GL_FLOAT,false,0,0);
    }

    @Override
    public void Draw(){
        gl.glEnable(GL2.GL_NORMALIZE);

        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, targetsBuffer.get(0));
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0);

        gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,targetsBuffer.get(1));
        gl.glNormalPointer(GL2.GL_FLOAT, 0, 0);

        gl.glDrawArrays(GL2.GL_QUADS, 0, fBuff.capacity()/3);
    }

As you can see, I don't calculate any normals, just assign the same normal for each vertex. But it looks strange. Because normals did not assigned for some part of terrain.
Watch screenshot please.
http://puu.sh/g9eFY/54d10e7f98.png
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
In reply to this post by Chaz
Man, i'm sorry for spending your time. My problem was in don't understanding some words in documentation, so after using some logic I realized, that something wrong in  
gl.glNormalPointer(GL2.GL_FLOAT, 0, 0);
so now I understand what is means - stride. Ahahah!!!
With  gl.glNormalPointer(GL2.GL_FLOAT, 4, 0); all looks nice! Going to calculate normals!
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
i meant gl.glNormalPointer(GL2.GL_FLOAT, 3, 0); , not 4. xD
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

gouessej
Administrator
The example calls glDrawArrays. I thought that you wanted to use VAO and now you call glNormalPointer :s
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
I just wanted to apply normals xD
One more question.
I guess that normal - it is float number in range from 0 to 1, right?
So how to calculate that float number? Because in google I see examples, where normal has Vector3 type.
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

gouessej
Administrator
You don't really understand what you do, you mix some methods of the fixed pipeline with some methods of the programmable pipeline. Using VAOs with glNormalPointer is nonsensical.

A normal should be normalized, i.e its norm should be equal to one. "google" doesn't have the answers to all questions. "For a convex polygon (such as a triangle), a surface normal can be calculated as the vector cross product of two (non-parallel) edges of the polygon" (see Wikipedia: https://en.wikipedia.org/wiki/Normal_%28geometry%29).
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
Actually now I don't use VAO. Forget to delete that method.
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

Chaz
After thousand years...
                Vector3f dest1=new Vector3f();
                VectorUtil.sub(dest1,new Vector3f(x4,y4,z4),new Vector3f(x1,y1,z1));
                Vector3f dest2=new Vector3f();
                VectorUtil.sub(dest2,new Vector3f(x2,y2,z2),new Vector3f(x1,y1,z1));
                float xn = (dest1.y*dest2.z)-(dest1.z*dest2.y);
                float yn = (dest1.z*dest2.x)-(dest1.x*dest2.z);
                float zn = (dest1.x*dest2.y)-(dest1.y*dest2.x);
                float n1 = (float)Math.sqrt(xn*xn+yn*yn+zn*zn);
                nBuff.put(xn/n1+yn/n1+zn/n1);

                VectorUtil.sub(dest1,new Vector3f(x1,y1,z1),new Vector3f(x2,y2,z2));
                VectorUtil.sub(dest2,new Vector3f(x3,y3,z3),new Vector3f(x2,y2,z2));
                xn = (dest1.y*dest2.z)-(dest1.z*dest2.y);
                yn = (dest1.z*dest2.x)-(dest1.x*dest2.z);
                zn = (dest1.x*dest2.y)-(dest1.y*dest2.x);
                n1 = (float)Math.sqrt(xn*xn+yn*yn+zn*zn);
                nBuff.put(xn/n1+yn/n1+zn/n1);

                VectorUtil.sub(dest1,new Vector3f(x2,y2,z2),new Vector3f(x3,y3,z3));
                VectorUtil.sub(dest2,new Vector3f(x4,y4,z4),new Vector3f(x3,y3,z3));
                xn = (dest1.y*dest2.z)-(dest1.z*dest2.y);
                yn = (dest1.z*dest2.x)-(dest1.x*dest2.z);
                zn = (dest1.x*dest2.y)-(dest1.y*dest2.x);
                n1 = (float)Math.sqrt(xn*xn+yn*yn+zn*zn);
                nBuff.put(xn/n1+yn/n1+zn/n1);

                VectorUtil.sub(dest1,new Vector3f(x3,y3,z3),new Vector3f(x4,y4,z4));
                VectorUtil.sub(dest2,new Vector3f(x1,y1,z1),new Vector3f(x4,y4,z4));
                xn = (dest1.y*dest2.z)-(dest1.z*dest2.y);
                yn = (dest1.z*dest2.x)-(dest1.x*dest2.z);
                zn = (dest1.x*dest2.y)-(dest1.y*dest2.x);
                n1 = (float)Math.sqrt(xn*xn+yn*yn+zn*zn);
                nBuff.put(xn/n1+yn/n1+zn/n1);
Reply | Threaded
Open this post in threaded view
|

Re: How to add colors or normals to custom object?

gouessej
Administrator
You could have called getNormalVec3 instead of reinventing the wheel.
Julien Gouesse | Personal blog | Website