Nehe Lesson 27 shadows

Started by bobjob, August 26, 2007, 23:15:51

Previous topic - Next topic

bobjob

Does anyone know what i have done wrong, i cant seem to port the lesson over to lwjgl.
http://rafb.net/p/TsCcES15.html
Iv included the whole program. If someone wanted to try it here is a link for the object that it loads
http://rafb.net/p/8usltF25.html

It runs fine, except there is no shadow.

bobjob

Iv also tried making the pixel format (0, 16, 1) yet it still wont do anything could it be my video card?

Fool Running

I was gonna try it out, but the links are dead :-\
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

bobjob

oops sorry, didnt realize how short lasting that code paste site is.

here is a link that should last

http://users.on.net/~bobjob/nehe/Lesson27.java code
http://users.on.net/~bobjob/nehe/Object2.txt object

thanx in advance, this is realllly drivn me nuts cant understand why it wont work.


Fool Running

I'll assume you aren't Mark Bernard and didn't write the code and won't mind me bashing it.... It was HORRIBLE code :-\
Well, horrible code aside, I did get it to render correctly. The code, as written in the LWJGL port of the NeHe tutorial, didn't come close to working (the author probably never actually tried it ::)).
I'll try paste the methods I changed:
    private void initGL() {                                         // All Setup For OpenGL Goes Here
        initGLObjects();
        int width = 640;
        int height = 480;
        GL11.glShadeModel(GL11.GL_SMOOTH);                            // Enable Smooth Shading
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
        GL11.glClearDepth(1.0f);                                 // Depth Buffer Setup
        GL11.glClearStencil(0);                                  // Stencil Buffer Setup
        GL11.glEnable(GL11.GL_DEPTH_TEST);                            // Enables Depth Testing
        GL11.glDepthFunc(GL11.GL_LEQUAL);                             // The Type Of Depth Testing To Do
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);  // Really Nice Perspective Calculations

        floatBuffer = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asFloatBuffer();
        byteBuffer = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder());
        GL11.glLight(GL11.GL_LIGHT1, GL11.GL_POSITION, (FloatBuffer)floatBuffer.put(lightPos).flip());        // Set Light1 Position
        GL11.glLight(GL11.GL_LIGHT1, GL11.GL_AMBIENT, (FloatBuffer)floatBuffer.put(lightAmb).flip());         // Set Light1 Ambience
        GL11.glLight(GL11.GL_LIGHT1, GL11.GL_DIFFUSE, (FloatBuffer)floatBuffer.put(lightDif).flip());         // Set Light1 Diffuse
        GL11.glLight(GL11.GL_LIGHT1, GL11.GL_SPECULAR, (FloatBuffer)floatBuffer.put(lightSpc).flip());        // Set Light1 Specular
        GL11.glEnable(GL11.GL_LIGHT1);                                // Enable Light1
        GL11.glEnable(GL11.GL_LIGHTING);                              // Enable Lighting

        GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, (FloatBuffer)floatBuffer.put(matAmb).flip());         // Set Material Ambience
        GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE, (FloatBuffer)floatBuffer.put(matDif).flip());         // Set Material Diffuse
        GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, (FloatBuffer)floatBuffer.put(matSpc).flip());        // Set Material Specular
        GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SHININESS, (FloatBuffer)floatBuffer.put(matShn).flip());       // Set Material Shininess

        GL11.glCullFace(GL11.GL_BACK);                                // Set Culling Face To Back Face
        GL11.glEnable(GL11.GL_CULL_FACE);                             // Enable Culling
        GL11.glClearColor(0.1f, 1.0f, 0.5f, 1.0f);               // Set Clear Color (Greenish Color)

        q = new Sphere();                               // Initialize Quadratic
        q.setNormals(GL11.GL_SMOOTH);                   // Enable Smooth Normal Generation
        q.setTextureFlag(false);                        // Disable Auto Texture Coords

        GL11.glViewport(0,0,width,height);                           // Reset The Current Viewport

        GL11.glMatrixMode(GL11.GL_PROJECTION);                            // Select The Projection Matrix
        GL11.glLoadIdentity();                                       // Reset The Projection Matrix

        // Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(45.0f,
                (float) displayMode.getWidth() / (float) displayMode.getHeight(),
                0.05f,100.0f);

        GL11.glMatrixMode(GL11.GL_MODELVIEW);                             // Select The Modelview Matrix
        GL11.glLoadIdentity();                                       // Reset The Modelview Matrix
    }
    private void render() {
        float Minv[] = new float[16];
        float wlp[] = new float[4];
        float lp[] = new float[4];

        // Clear Color Buffer, Depth Buffer, Stencil Buffer
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);

        GL11.glLoadIdentity();                                   // Reset Modelview Matrix
        GL11.glTranslatef(0.0f, 0.0f, -20.0f);                   // Zoom Into Screen 20 Units
        GL11.glLight(GL11.GL_LIGHT1, GL11.GL_POSITION, (FloatBuffer)byteBuffer.asFloatBuffer().put(lightPos).flip());        // Position Light1
        GL11.glTranslatef(spherePos[0], spherePos[1], spherePos[2]); // Position The Sphere
        q.draw(1.5f, 32, 16);                         // Draw A Sphere

        // calculate light's position relative to local coordinate system
        // dunno if this is the best way to do it, but it actually works
        // if u find another aproach, let me know ;)

        // we build the inversed matrix by doing all the actions in reverse order
        // and with reverse parameters (notice -xrot, -yrot, -ObjPos[], etc.)
        GL11.glLoadIdentity();                                   // Reset Matrix
        GL11.glRotatef(-yrot, 0.0f, 1.0f, 0.0f);                 // Rotate By -yrot On Y Axis
        GL11.glRotatef(-xrot, 1.0f, 0.0f, 0.0f);                 // Rotate By -xrot On X Axis
        
        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, (FloatBuffer)floatBuffer.clear());              // Retrieve ModelView Matrix (Stores In Minv)
        floatBuffer.get(Minv, 0, 16);
        lp[0] = lightPos[0];                                // Store Light Position X In lp[0]
        lp[1] = lightPos[1];                                // Store Light Position Y In lp[1]
        lp[2] = lightPos[2];                                // Store Light Position Z In lp[2]
        lp[3] = lightPos[3];                                // Store Light Direction In lp[3]
        vMatMult(Minv, lp);                                 // We Store Rotated Light Vector In 'lp' Array
        GL11.glTranslatef(-objPos[0], -objPos[1], -objPos[2]);   // Move Negative On All Axis Based On ObjPos[] Values (X, Y, Z)
        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX,(FloatBuffer)floatBuffer.clear());              // Retrieve ModelView Matrix From Minv
        floatBuffer.get(Minv, 0, 16);
        wlp[0] = 0.0f;                                      // World Local Coord X To 0
        wlp[1] = 0.0f;                                      // World Local Coord Y To 0
        wlp[2] = 0.0f;                                      // World Local Coord Z To 0
        wlp[3] = 1.0f;
        vMatMult(Minv, wlp);                                // We Store The Position Of The World Origin Relative To The
                                                            // Local Coord. System In 'wlp' Array
        lp[0] += wlp[0];                                    // Adding These Two Gives Us The
        lp[1] += wlp[1];                                    // Position Of The Light Relative To
        lp[2] += wlp[2];                                    // The Local Coordinate System

        GL11.glColor4f(0.7f, 0.4f, 0.0f, 1.0f);                  // Set Color To An Orange
        GL11.glLoadIdentity();                                   // Reset Modelview Matrix
        GL11.glTranslatef(0.0f, 0.0f, -20.0f);                   // Zoom Into The Screen 20 Units
        drawGLRoom();                                       // Draw The Room
        GL11.glTranslatef(objPos[0], objPos[1], objPos[2]);      // Position The Object
        GL11.glRotatef(xrot, 1.0f, 0.0f, 0.0f);                  // Spin It On The X Axis By xrot
        GL11.glRotatef(yrot, 0.0f, 1.0f, 0.0f);                  // Spin It On The Y Axis By yrot
        drawGLObject(obj);                                  // Procedure For Drawing The Loaded Object
        castShadow(obj, lp);                               // Procedure For Casting The Shadow Based On The Silhouette

        GL11.glColor4f(0.7f, 0.4f, 0.0f, 1.0f);                  // Set Color To Purplish Blue
        GL11.glDisable(GL11.GL_LIGHTING);                             // Disable Lighting
        GL11.glDepthMask(false);                              // Disable Depth Mask
        GL11.glTranslatef(lp[0], lp[1], lp[2]);                  // Translate To Light's Position
                                                            // Notice We're Still In Local Coordinate System
        q.draw(0.2f, 16, 8);                          // Draw A Little Yellow Sphere (Represents Light)
        GL11.glEnable(GL11.GL_LIGHTING);                              // Enable Lighting
        GL11.glDepthMask(true);                               // Enable Depth Mask

        xrot += xspeed;                                     // Increase xrot By xspeed
        yrot += yspeed;                                     // Increase yrot By yspeed

        GL11.glFlush();                                          // Flush The OpenGL Pipeline
    }

//     connectivity procedure - based on Gamasutra's article
//     hard to explain here
    private void setConnectivity(GlObject o) {
        int p1i, p2i, p1j, p2j;
        int P1i, P2i, P1j, P2j;
        int i,j,ki,kj;

        for(i=0;i<o.nPlanes-1;i++) {
            for(j=i+1;j<o.nPlanes;j++) {
                for(ki=0;ki<3;ki++) {
                    if(o.planes[i].neigh[ki] == 0){
                        for(kj=0;kj<3;kj++){
                            p1i=ki;
                            p1j=kj;
                            p2i=(ki+1)%3;
                            p2j=(kj+1)%3;

                            p1i=o.planes[i].p[p1i];
                            p2i=o.planes[i].p[p2i];
                            p1j=o.planes[j].p[p1j];
                            p2j=o.planes[j].p[p2j];

                            P1i=((p1i+p2i)-Math.abs(p1i-p2i))/2;
                            P2i=((p1i+p2i)+Math.abs(p1i-p2i))/2;
                            P1j=((p1j+p2j)-Math.abs(p1j-p2j))/2;
                            P2j=((p1j+p2j)+Math.abs(p1j-p2j))/2;

                            if((P1i==P1j) && (P2i==P2j)){  //they are neighbours
                                o.planes[i].neigh[ki] = j+1;
                                o.planes[j].neigh[kj] = i+1;
                            }
                        }
                    }
                }
            }
        }
    }

    private void castShadow(GlObject o, float lp[]){
        int i;
        float side;

        //set visual parameter
        for (i=0;i<o.nPlanes;i++){
            // chech to see if light is in front or behind the plane (face plane)
            side =  o.planes[i].planeEq.a*lp[0]+
                    o.planes[i].planeEq.b*lp[1]+
                    o.planes[i].planeEq.c*lp[2]+
                    o.planes[i].planeEq.d;
            if (side >0) o.planes[i].visible = true;
                    else o.planes[i].visible = false;
        }

        GL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT 
                | GL11.GL_ENABLE_BIT | GL11.GL_POLYGON_BIT | GL11.GL_STENCIL_BUFFER_BIT);
        GL11.glDisable(GL11.GL_LIGHTING);
        GL11.glDepthMask(false);
        GL11.glDepthFunc(GL11.GL_LEQUAL);
        GL11.glEnable(GL11.GL_STENCIL_TEST);
        GL11.glColorMask(false, false, false, false);
        GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xffffffff);

        // first pass, stencil operation increases stencil value
        GL11.glFrontFace(GL11.GL_CCW);
        GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_INCR);
        doShadowPass(o, lp);

        // second pass, stencil operation decreases stencil value
        GL11.glFrontFace(GL11.GL_CW);
        GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_DECR);
        doShadowPass(o, lp);

        GL11.glFrontFace(GL11.GL_CCW);
        GL11.glColorMask(true, true, true, true);

        //draw a shadowing rectangle covering the entire screen
        GL11.glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GL11.glStencilFunc(GL11.GL_NOTEQUAL, 0, 0xffffffff);
        GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
        GL11.glPushMatrix();
        GL11.glLoadIdentity();
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        GL11.glVertex3f(-0.1f, 0.1f,-0.10f);
        GL11.glVertex3f(-0.1f,-0.1f,-0.10f);
        GL11.glVertex3f( 0.1f, 0.1f,-0.10f);
        GL11.glVertex3f( 0.1f,-0.1f,-0.10f);
        GL11.glEnd();
        GL11.glPopMatrix();
        GL11.glPopAttrib();
    }

    private void doShadowPass(GlObject o, float[] lp){
        int i, j, k, jj;
        int p1, p2;
        Point v3 = new Point();
        Point v4 = new Point();
        for (i=0; i<o.nPlanes;i++){
            if (o.planes[i].visible)
                for (j=0;j<3;j++){
                    k = o.planes[i].neigh[j];
                    if ((k != 0) || (!o.planes[k-1].visible)){
                        // here we have an edge, we must draw a polygon
                        p1 = o.planes[i].p[j];
                        jj = (j+1)%3;
                        p2 = o.planes[i].p[jj];
    
                        //calculate the length of the vector
                        v3.x = (o.points[p1].x - lp[0])*100;
                        v3.y = (o.points[p1].y - lp[1])*100;
                        v3.z = (o.points[p1].z - lp[2])*100;
    
                        v4.x = (o.points[p2].x - lp[0])*100;
                        v4.y = (o.points[p2].y - lp[1])*100;
                        v4.z = (o.points[p2].z - lp[2])*100;
    
                        //draw the polygon
                        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
                            GL11.glVertex3f(o.points[p1].x,
                                        o.points[p1].y,
                                        o.points[p1].z);
                            GL11.glVertex3f(o.points[p1].x + v3.x,
                                        o.points[p1].y + v3.y,
                                        o.points[p1].z + v3.z);
    
                            GL11.glVertex3f(o.points[p2].x,
                                        o.points[p2].y,
                                        o.points[p2].z);
                            GL11.glVertex3f(o.points[p2].x + v4.x,
                                        o.points[p2].y + v4.y,
                                        o.points[p2].z + v4.z);
                        GL11.glEnd();
                    }
                }
        }
    }
}

Basically I changed the use of java.nio buffers to be used correctly and an 'if' that was wrong. Maybe some other tidbits around...

Hope that helps ;D
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

bobjob

hmmm, dang im not sure which version i pasted, there is the lwjgl source from the nehe site, which doesnt even load models properly, I could only go as far as to fix that. there is also the version that i just coppied off the visual c++ version to java best i could.

thanx for trying. I give up! im going to leave shadows till last.

bobjob

ohhhhh you worked out how to actually fix it (didnt relise), i added the changes you put in, thanx man, your a gun!