glMultMatrix

Started by Emperor, October 03, 2003, 15:50:41

Previous topic - Next topic

Emperor

Hi, I'm writing a simple game engine and wanted objects to return their transform matrix to be flexible in method how to generate it, for example to have setposition and setangle for sprites, and more complex for 3d object.

I wanted to use glMultMatrix to apply the matrix to the object,

but it doesn't work.

The following code:


      Vector3f position=object.getPosition();

      FloatBuffer buf = FloatBuffer.allocate(16);
      Matrix4f matrix = new Matrix4f();
      matrix.setZero();
      matrix.m00=1;
      matrix.m11=1;
      matrix.m22=1;
      matrix.m30=position.x;
      matrix.m31=position.y;
      matrix.m32=position.z;
      
      matrix.store(buf);
      buf.rewind();
      
      GL.glMultMatrixf(buf);

should do the same as       
      GL.glTranslatef(position.x, position.y, position.z);

shouldn't it?

but instead no transformations are done...

Any ideas? is it a math thing or gl or floatbuffer related issue?


Is it a good idea to generate the transform matrixes instead of calling GL functions? The main advantage I see is that it can be much more flexible.

Thx for the help!

Matzon


Emperor

Ok, so now I use

      Vector3f position=object.getPosition();

      FloatBuffer buf = ByteBuffer.allocateDirect(16*4).asFloatBuffer();

               
      Matrix4f matrix = new Matrix4f();

      matrix.translate(new Vector3f().set(position.x, position.y, position.z));
      matrix.store(buf);
      buf.rewind();
      
      GL.glMultMatrixf(buf);

      
//      GL.glTranslatef(position.x, position.y, position.z);



but when I use MultMatrix, I see nothing, whereas glTranslate does...

my matrix math is very bad... what am I doing wrong?

princec

Generally speaking it's best to let GL handle the transformations instead of making your own matrices up.

If you're interested in checking the difference between how GL computes the matrices and your code, try using glGetFloatv() to get the current matrix after a transform and printing it out.

Cas :)

andrewc

I'm not sure what is wrong, but the approach should work. I had a go at using matrices for storing transforms, but it was a while ago so I can't remember too much about it. Perhaps it will help. It's an edited version 0.6 example:

/* 
 * Copyright (c) 2002 Light Weight Java Game Library Project
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are 
 * met:
 * 
 * * Redistributions of source code must retain the above copyright 
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'Light Weight Java Game Library' nor the names of 
 *   its contributors may be used to endorse or promote products derived 
 *   from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.nio.*;
import java.io.*;
import java.awt.image.BufferedImage;
import javax.imageio.*;

import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.input.*;
import org.lwjgl.vector.*;

/**
 * $Id: BaseWindow.java,v 1.10 2003/03/28 23:57:45 matzon Exp $
 *
 * Setting Up An OpenGL Window
 *
 * Credit goes to Jeff Molofee (NeHe) whos tutorial this is based on
 *
 * @author Luke Holden
 * @version $Revision: 1.10 $
 */
public class Cubes {
    protected GL gl;
    protected GLU glu;
    
    protected boolean fullscreen = true;
    protected boolean finished = false;
    protected long timerRes;
    
    private IntBuffer textureBuf = createIntBuffer(1);

    private float distance;
    private Cube[] cube;

    /** Creates a new instance of Lesson */
    public Cubes() {
    }
    

    protected void createGLWindow(int width, int height, int bits, boolean fullscreenflag) throws Exception {
        fullscreen = fullscreenflag;
        try {
          int mode = -1;
          DisplayMode[] modes = Display.getAvailableDisplayModes();
          for (int i = 0; i < modes.length; i ++) {
            if( modes[i].width == width && 
                modes[i].height == height && 
                modes[i].bpp >= bits) {
                  mode = i;
                  break;
            }       
          }          
          
            gl = new GL("LWJGL Window", 0, 0, width, height, bits, 0, 0, 0);
            gl.create();
            glu = new GLU(gl);
            Keyboard.create();
            Keyboard.enableBuffer();
            Mouse.create();
            //Mouse.enableBuffer();
            
            resizeGLScene(width, height);
            
            initGLSettings();
        }
        catch (Exception e) {
            throw new Exception("Problem initialising Lesson", e);
        }  
    }
    
    protected void resizeGLScene(int width, int height) {
        gl.viewport(0, 0, width, height);

        gl.matrixMode(GL.PROJECTION);
        gl.loadIdentity();
        
        glu.perspective(45.0f, ((float) width) / ((float) height), 0.1f, 100.0f);
        
        gl.matrixMode(GL.MODELVIEW);
        gl.loadIdentity();
    }
    
    protected void initGLSettings() throws Exception {
        try {
            loadGLTextures();
            gl.enable(GL.TEXTURE_2D);
        }
        catch (Exception e) {
            throw new Exception("Problem initialising GL", e);
        }

        gl.shadeModel(GL.SMOOTH);
       
        gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);

        gl.clearDepth(1.0f);
        gl.enable(GL.DEPTH_TEST);
        gl.depthFunc(GL.LEQUAL);

        gl.cullFace(GL.BACK);
        gl.enable(GL.CULL_FACE);
        
        gl.hint(GL.PERSPECTIVE_CORRECTION_HINT, GL.NICEST);
    }
    
    protected void killGLWindow() {
        Mouse.destroy();
        Keyboard.destroy();
        gl.destroy();
    }


    public IntBuffer createIntBuffer(int size) {
        ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
        temp.order(ByteOrder.nativeOrder());
        
        return temp.asIntBuffer();
    }


    /* A javafied version of AUX_RGBImageRec *LoadBMP(char*); */
    public Texture loadTexture(String filename) throws Exception {
        Texture texture = null;
        BufferedImage tmpImg = null;
        
        /* normally I would use StringUtils.isValid(String) from the 
           jakarta commons lib, but thats beyond the scope of this lesson */
        if ((filename != null) && (!"".equals(filename.trim()))) {
            try {
                InputStream is = getClass().getResourceAsStream(filename);
                tmpImg = (BufferedImage) ImageIO.read(is);
                if (tmpImg == null) {
                    throw new Exception("Error: Got null from ImageIO.read()");
                }
                texture = new Texture(tmpImg);
            }
            catch ( Exception e ) {
                throw new Exception("Problem loading bitmap", e);
            }
        } else {
            throw new Exception("Error: file name is not valid!");
        }
        return texture;
    }


    /* Load Bitmaps And Convert To Textures */
    protected void loadGLTextures() throws Exception {
        /* Create Storage Space For The Texture */
        Texture[] textureImage = new Texture[1];
        
        /* Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit */
        try {
            textureImage[0] = loadTexture("data/crate.png");
            if (textureImage[0] == null) {
                throw new Exception("Error: got null from loadImage()!");
            }
            
            /* Create The Texture */
            gl.genTextures(1, Sys.getDirectBufferAddress(textureBuf));
            
            /* Typical Texture Generation Using Data From The Bitmap */
            gl.bindTexture(GL.TEXTURE_2D, textureBuf.get(0));
            
            
            /* Linear Filtering */
            gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR);
            gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR);

            /* Generate The Texture */
            gl.texImage2D(GL.TEXTURE_2D, 
                          0, 
                          3, 
                          textureImage[0].getWidth(), 
                          textureImage[0].getHeight(), 
                          0, 
                          GL.RGB, 
                          GL.UNSIGNED_BYTE, 
                          textureImage[0].getPtr());

        }
        catch (Exception e) {
            throw new Exception("Problem loading textures", e);
        }
    }
    


    protected void run(int width, int height, int bpp, boolean fullscreen) throws Exception {
        timerRes = Sys.getTimerResolution();
        if (timerRes == 0) {
            throw new Exception("There are no timers available!");
        }
        
        try {           
            createGLWindow(width, height, bpp, fullscreen);
            createScene();

            finished = false;
            while (!finished) {
                gl.tick();

                float frameTime = (float)Sys.getTime() / (float)timerRes;
                Sys.setTime(0);

                handleInput(frameTime);
                updateScene(frameTime);
                renderScene();

                gl.paint();
            } 
            
            killGLWindow();
        }
        catch (Exception e) {
            throw new Exception("Problem in main loop", e);
        }
    }

    protected void createScene() {
        cube = new Cube[2];
        cube[0] = new CubeX(-0.8, -0.5, -5.0,  1.0, textureBuf.get(0));
        cube[1] = new CubeY( 1.1,  0.3, -8.0, -1.3, textureBuf.get(0));
    }

    protected void updateScene(float frameTime) {
        for (int i = 0; i < cube.length; i++) 
          cube[i].update(frameTime);
    }

    protected void renderScene() {   
        gl.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
      	gl.loadIdentity();
        gl.translatef(0, 0, distance);

        for (int i = 0; i < cube.length; i++)
          cube[i].render(gl);
    }
       
    protected void handleInput(float frameTime) {
        Keyboard.poll();
        if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
            finished = true;
        } 
        if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            distance += frameTime * 3;
        } 
        if (Keyboard.isKeyDown(Keyboard.KEY_Z)) {
            distance -= frameTime * 3;
        } 
    }
    
    public static void main(String[] arguments) {
        int err = 0;
        Cubes lesson = new Cubes();
        try {
            lesson.run(640, 480, 16, false);            
        }
        catch (Exception e) {
            err = 1;
            e.printStackTrace();
        }
        System.exit(err);
    }
}

class Cube {
    float[][] v = {{-1,-1, 1},{ 1,-1, 1},{ 1,-1,-1},{-1,-1,-1},{-1, 1, 1},{ 1, 1, 1},{ 1, 1,-1},{-1, 1,-1}};
    int[][] f = {{0,1,5,4},{1,2,6,5},{2,3,7,6},{3,0,4,7},{4,5,6,7},{3,2,1,0}};

    Matrix4f matrix;
    Vector3f vector;
    FloatBuffer buffer;

    float x, y, z, speed;
    int texturePtr;

    Cube(double x, double y, double z, double speed, int ptr) {
        this.speed = (float)speed;
        texturePtr = ptr;
        matrix = new Matrix4f();
        vector = new Vector3f();
        matrix.m30 = (float)x;
        matrix.m31 = (float)y;
        matrix.m32 = (float)z;
        buffer = createFloatBuffer(16);
    }

    public void update(float frameTime) {
    }

    public void render(GL gl) {
      gl.pushMatrix();

        buffer.clear();
        matrix.store(buffer);
        gl.multMatrixf(Sys.getDirectBufferAddress(buffer));

        gl.bindTexture(GL.TEXTURE_2D, texturePtr);
      	gl.begin(GL.QUADS);
          int vertex;
          for (int i = 0; i < f.length; i++) {

            vertex = f[i][0];
            gl.texCoord2f(0.0f, 0.0f); gl.vertex3f(v[vertex][0], v[vertex][1], v[vertex][2]);

            vertex = f[i][1];
            gl.texCoord2f(1.0f, 0.0f); gl.vertex3f(v[vertex][0], v[vertex][1], v[vertex][2]);

            vertex = f[i][2];
            gl.texCoord2f(1.0f, 1.0f); gl.vertex3f(v[vertex][0], v[vertex][1], v[vertex][2]);

            vertex = f[i][3];
            gl.texCoord2f(0.0f, 1.0f); gl.vertex3f(v[vertex][0], v[vertex][1], v[vertex][2]);
          }
        gl.end();
      gl.popMatrix();
    }

    protected void pitch(float angle)
    {
        vector.set(1.0f, 0.0f, 0.0f);
        matrix.rotate(angle, vector);
    }

    protected void roll(float angle)
    {
        vector.set(0.0f, 0.0f, 1.0f);
        matrix.rotate(angle, vector);
    }

    protected void yaw(float angle)
    {
        vector.set(0.0f, 1.0f, 0.0f);
        matrix.rotate(angle, vector);
    }

    public FloatBuffer createFloatBuffer(int size) {
        ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
        temp.order(ByteOrder.nativeOrder());
        
        return temp.asFloatBuffer();
    }

}

class CubeX extends Cube
{
    public CubeX(double x, double y, double z, double speed, int ptr) {
        super(x, y, z, speed, ptr);
    }

    public void update(float frameTime)
    {
        pitch(45.0f * frameTime);
        roll(7.0f * frameTime);
    }
}

class CubeY extends Cube
{
    public CubeY(double x, double y, double z, double speed, int ptr) {
        super(x, y, z, speed, ptr);
    }

    public void update(float frameTime)
    {
        yaw(45.0f * frameTime);
    }
}

andrewc

Quote from: "Emperor"matrix.setZero();
      matrix.m00=1;
      matrix.m11=1;
      matrix.m22=1;

I think you probably need another line here
matrix.m33 = 1;
This sets the overall scale or something.

Or you could try replacing it all with matrix.setIdentity();

Emperor

Got it!

I had to call buf.flip... had a look at a previous post here.

Now it works.

A simple intro to the use of nio Buffers with lwjgl would be great for new users!

I also tried the glGetFloat, but it also returns only zero values... think it's a buffer issue again, here is my code:

   FloatBuffer buf = ByteBuffer.allocateDirect(16*4).order(ByteOrder.nativeOrder()).asFloatBuffer();

      GL.glGetFloat(GL.GL_MODELVIEW,buf);
      
      for (int i = 0; i < 4; i++)
      {
         System.out.println(buf.get() +" "+buf.get() +" "+buf.get()  + " " +buf.get() );
      }

thank you!