fr.ign.cogit.geoxygene.appli.gl.GLTextComplex.java Source code

Java tutorial

Introduction

Here is the source code for fr.ign.cogit.geoxygene.appli.gl.GLTextComplex.java

Source

/*******************************************************************************
 * This file is part of the GeOxygene project source files.
 * 
 * GeOxygene aims at providing an open framework which implements OGC/ISO
 * specifications for the development and deployment of geographic (GIS)
 * applications. It is a open source contribution of the COGIT laboratory at the
 * Institut Gographique National (the French National Mapping Agency).
 * 
 * See: http://oxygene-project.sourceforge.net
 * 
 * Copyright (C) 2005 Institut Gographique National
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library (see file LICENSE if present); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA
 *******************************************************************************/
package fr.ign.cogit.geoxygene.appli.gl;

import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
import static org.lwjgl.opengl.GL15.glBindBuffer;
import static org.lwjgl.opengl.GL15.glBufferData;
import static org.lwjgl.opengl.GL15.glGenBuffers;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL30.glBindVertexArray;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import org.apache.log4j.Logger;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;

import fr.ign.cogit.geoxygene.api.feature.IFeature;
import fr.ign.cogit.geoxygene.appli.GeoxygeneConstants;
import fr.ign.cogit.geoxygene.appli.render.texture.ExpressiveRendering;
import fr.ign.cogit.geoxygene.util.gl.AbstractGLComplex;
import fr.ign.cogit.geoxygene.util.gl.GLComplex;
import fr.ign.cogit.geoxygene.util.gl.GLInput;
import fr.ign.cogit.geoxygene.util.gl.GLMesh;
import fr.ign.cogit.geoxygene.util.gl.GLRenderingCapability;
import fr.ign.cogit.geoxygene.util.gl.GLSimpleVertex;
import fr.ign.cogit.geoxygene.util.gl.GLTools;
import fr.ign.cogit.geoxygene.util.gl.GLTexture;

/**
 * GL Primitive is a representation of a 2D Object with 2D coordinates, Texture
 * coordinates and Color components. It is composed of primitives types which are
 * themselves composed of index lists so it can mix different type of
 * primitives, but the insertion order is not kept
 * 
 * @author JeT
 * 
 */
public class GLTextComplex extends AbstractGLComplex<GLSimpleVertex> implements GLComplex {

    private static final Logger logger = Logger.getLogger(GLTextComplex.class.getName()); // logger

    private FloatBuffer verticesBuffer = null; // Vertex buffer (VBO array)
                                               // constructed from vertices
    private IntBuffer indicesBuffer = null; // Index Buffer (VBO indices)
                                            // constructed from flattened
                                            // indicesPerType
    private GLTexture texture = null;

    private int vaoId = -1; // VAO index
    private int vboVerticesId = -1; // VBO Vertices index
    private int vboIndicesId = -1; // VBO Indices index
    private double overallOpacity = 1.;
    private GLSimpleRenderingCapability[] renderingCapabilities = null;
    private ExpressiveRendering expressiveRendering = null;
    private IFeature feature = null;
    int stride = -1;

    public enum GLSimpleRenderingCapability implements GLRenderingCapability {
        POSITION, COLOR, TEXTURE,
    }

    /**
     * Default constructor
     */
    public GLTextComplex(String id, double minX, double minY, IFeature f) {
        super(id, minX, minY);
        this.addInput(GLSimpleVertex.VertexPositionVarName, GLSimpleVertex.vertexPostionLocation, GL11.GL_FLOAT, 3,
                false);
        this.addInput(GLSimpleVertex.VertexUVVarName, GLSimpleVertex.vertexUVLocation, GL11.GL_FLOAT, 2, false);
        this.addInput(GLSimpleVertex.VertexColorVarName, GLSimpleVertex.vertexColorLocation, GL11.GL_FLOAT, 4,
                false);
        this.feature = f;
    }

    /**
     * @return the opacity for that entire complex
     */
    @Override
    public double getOverallOpacity() {
        return this.overallOpacity;
    }

    /**
     * @param expressiveRendering
     *            the expressiveRendering to set
     */
    public void setExpressiveRendering(ExpressiveRendering expressiveRendering) {
        this.expressiveRendering = expressiveRendering;
    }

    /**
     * @return the expressiveRendering
     */
    public ExpressiveRendering getExpressiveRendering() {
        return this.expressiveRendering;
    }

    /**
     * Overall opacity is used to set the opacity of the FBO in which this
     * object has been drawn without an transparency. Set the vertices opacity
     * to 1
     */
    public void setOverallOpacity(double overallOpacity) {
        this.overallOpacity = overallOpacity;
    }

    /**
     * @return the renderingCapability
     */
    @Override
    public GLSimpleRenderingCapability[] getRenderingCapabilities() {
        if (this.renderingCapabilities == null) {
            if (this.getTexture() != null) {
                this.renderingCapabilities = new GLSimpleRenderingCapability[] { GLSimpleRenderingCapability.COLOR,
                        GLSimpleRenderingCapability.TEXTURE };
            } else {
                this.renderingCapabilities = new GLSimpleRenderingCapability[] {
                        GLSimpleRenderingCapability.COLOR };
            }
        }
        return this.renderingCapabilities;
    }

    /**
     * @return the texture
     */
    public GLTexture getTexture() {
        return this.texture;
    }

    /**
     * @param texture
     *            the texture to set
     */
    public void setTexture(GLTexture texture) {
        this.texture = texture;
        this.renderingCapabilities = null;

    }

    /**
     * Set the color of all vertices contained in this complex
     * 
     * @param color
     *            color to be set to all vertices
     */
    public void setColor(final java.awt.Color color) {
        for (GLSimpleVertex vertex : this.getVertices()) {
            vertex.setRGBA(color);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.ign.cogit.geoxygene.util.gl.GLComplex#invalidateBuffers()
     */
    @Override
    public void invalidateBuffers() {
        if (this.vboIndicesId >= 0) {
            GL15.glDeleteBuffers(this.vboIndicesId);
            this.indicesBuffer = null;
            this.vboIndicesId = -1;
        }
        if (this.vboVerticesId >= 0) {
            GL15.glDeleteBuffers(this.vboVerticesId);
            this.verticesBuffer = null;
            this.vboVerticesId = -1;
        }
        if (this.vaoId >= 0) {
            GL30.glDeleteVertexArrays(this.vaoId);
            this.vaoId = -1;
        }
    }

    /**
     * @return the feature
     */
    public IFeature getFeature() {
        return this.feature;
    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.ign.cogit.geoxygene.util.gl.GLComplex#getFlippedVerticesBuffer()
     */
    @Override
    public FloatBuffer getFlippedVerticesBuffer() {
        if (this.verticesBuffer == null) {
            this.verticesBuffer = BufferUtils
                    .createFloatBuffer(this.getVertices().size() * this.getStride() / (Float.SIZE / 8));
            // BufferUtils.createByteBuffer(this.vertices.size() *
            // GLSimpleVertex.VERTEX_BYTESIZE).asFloatBuffer();
            for (GLSimpleVertex vertex : this.getVertices()) {
                // Add position, color and texture floats to the buffer
                // System.err.println("add XYZ to vertex buffer: " +
                // Arrays.toString(vertex.getXYZ()));
                // System.err.println("add UV to vertex buffer: " +
                // Arrays.toString(vertex.getUV()));
                // System.err.println("add RGBA to vertex buffer: " +
                // Arrays.toString(vertex.getRGBA()));
                this.verticesBuffer
                        .put(new float[] { (vertex.getXYZ()[0]), (vertex.getXYZ()[1]), vertex.getXYZ()[2] });
                this.verticesBuffer.put(vertex.getUV());
                this.verticesBuffer.put(vertex.getRGBA());

            }
            this.verticesBuffer.flip();
            // System.err.println("create a new vertex buffer = ");
            // GLTools.displayBuffer(this.verticesBuffer);

        }
        this.verticesBuffer.rewind();
        return this.verticesBuffer;
    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.ign.cogit.geoxygene.util.gl.GLComplex#getFlippedIndicesBuffer()
     */
    @Override
    public IntBuffer getFlippedIndicesBuffer() {
        if (this.indicesBuffer == null) {
            this.generateIndicesBuffers();
        }
        this.indicesBuffer.rewind();
        return this.indicesBuffer;
    }

    /**
     * Compute the acceleration structure for all the contained meshes
     * 
     * @param glComplex
     * @return
     */
    private void generateIndicesBuffers() {
        // count the total number of vertices
        int nbIndices = 0;
        for (GLMesh mesh : this.getMeshes()) {
            nbIndices += mesh.getIndices().size();
        }
        // fill the indices buffer (VBO indices)
        // and generate a range of indices in the indices buffer
        this.indicesBuffer = BufferUtils.createIntBuffer(nbIndices);
        int currentStartIndex = 0;
        for (GLMesh mesh : this.getMeshes()) {
            for (int nIndex = 0; nIndex < mesh.getIndices().size(); nIndex++) {
                this.indicesBuffer.put(mesh.getIndices().get(nIndex).intValue());
            }
            mesh.setFirstIndex(currentStartIndex);
            currentStartIndex = currentStartIndex + mesh.getIndices().size();
            mesh.setLastIndex(currentStartIndex - 1);
        }
        this.indicesBuffer.flip();
    }

    /**
     * Bind Buffers with gl Context
     */
    private void generateVao() {
        // Create a new Vertex Array Object in memory and select it (bind)
        this.vaoId = GL30.glGenVertexArrays();
        if (this.vaoId <= 0) {
            logger.error("VAO ID is invalid " + this.vaoId);
        }
        glBindVertexArray(this.vaoId);

        // create the Vertex VBO
        this.vboVerticesId = glGenBuffers();
        if (this.vboVerticesId <= 0) {
            logger.error("VBO(Vertices) ID is invalid " + this.vboVerticesId);
        }
        glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vboVerticesId);

        int byteShift = 0;
        for (GLInput input : this.getInputs()) {
            GL20.glVertexAttribPointer(input.getLocation(), input.getComponentCount(), input.getGlType(),
                    input.isNormalized(), this.getStride(), byteShift);
            // System.err.println("loc = " + input.getLocation() + " "
            // + input.getComponentCount() + " " + input.getGlType()
            // + " stride = " + this.getStride() + " shift = " + byteShift
            // + " name = " + input.getName() + " "
            // + this.getClass().getSimpleName());
            byteShift += input.getComponentCount() * GLTools.sizeInBytes(input.getGlType());
            glEnableVertexAttribArray(input.getLocation());

        }
        // System.err.println("previous");
        // for (int nAttrib = 0; nAttrib < GLSimpleVertex.ATTRIBUTES_COUNT;
        // nAttrib++)
        // {
        // GL20.glVertexAttribPointer(GLSimpleVertex.ATTRIBUTES_ID[nAttrib],
        // GLSimpleVertex.ATTRIBUTES_COMPONENT_NUMBER[nAttrib],
        // GLSimpleVertex.ATTRIBUTES_TYPE[nAttrib],
        // false, GLSimpleVertex.VERTEX_BYTESIZE,
        // GLSimpleVertex.ATTRIBUTES_BYTEOFFSET[nAttrib]);
        // System.err.println("loc = " + GLSimpleVertex.ATTRIBUTES_ID[nAttrib] +
        // " " +
        // GLSimpleVertex.ATTRIBUTES_COMPONENT_NUMBER[nAttrib] + " "
        // + GLSimpleVertex.ATTRIBUTES_TYPE[nAttrib] + " stride = " +
        // GLSimpleVertex.VERTEX_BYTESIZE + " shift = " +
        // GLSimpleVertex.ATTRIBUTES_BYTEOFFSET[nAttrib]);
        // glEnableVertexAttribArray(GLSimpleVertex.ATTRIBUTES_ID[nAttrib]);
        //
        // }

        glBufferData(GL_ARRAY_BUFFER, this.getFlippedVerticesBuffer(), GL_STATIC_DRAW);

        // displayBuffer(this.getFlippedVerticesBuffer());

        // glBindBuffer(GL_ARRAY_BUFFER, 0);

        // create the index VBO
        this.vboIndicesId = glGenBuffers();
        if (this.vboIndicesId <= 0) {
            logger.error("VBO(Indices) ID is invalid " + this.vboIndicesId);
        }

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this.vboIndicesId);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, this.getFlippedIndicesBuffer(), GL_STATIC_DRAW);

        // displayBuffer(this.getFlippedIndicesBuffer());

        glBindVertexArray(0);

    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.ign.cogit.geoxygene.util.gl.GLComplex#getVaoId()
     */
    @Override
    public int getVaoId() {
        if (this.vaoId <= 0) {
            this.generateVao();
        }
        return this.vaoId;
    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.ign.cogit.geoxygene.util.gl.GLComplex#getVboVerticesId()
     */
    @Override
    public int getVboVerticesId() {
        if (this.vboVerticesId <= 0) {
            this.generateVao();
        }
        return this.vboVerticesId;
    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.ign.cogit.geoxygene.util.gl.GLComplex#getVboIndicesId()
     */
    @Override
    public int getVboIndicesId() {
        if (this.vboIndicesId <= 0) {
            this.generateVao();
        }
        return this.vboIndicesId;
    }

    // /**
    // * Add all meshes from a gl complex
    // *
    // * @param subComplex
    // */
    // @Override
    // public void addGLComplex(GLComplex subComplex) {
    //
    // if (subComplex instanceof GLSimpleComplex) {
    // GLSimpleComplex subComplex = (GLSimpleComplex) subComplex;
    //
    // }
    // // map between old indices and new ones
    // HashMap<Integer, Integer> indicesLUT = new HashMap<Integer, Integer>();
    //
    // if (subComplex == null) {
    // return;
    // }
    // if (subComplex.mayOverlap()) {
    // this.setMayOverlap(true);
    // }
    // // add all vertices
    // int vertexOldIndex = 0;
    // for (GLSimpleVertex vertex : subComplex.getVertices()) {
    // int vertexNewIndex = this.addVertex(vertex);
    // indicesLUT.put(vertexOldIndex, vertexNewIndex);
    // vertexOldIndex++;
    // }
    // // add a copy of all meshes (map indices with computed LUT)
    // for (GLMesh oldMesh : subComplex.getMeshes()) {
    // GLMesh newMesh = this.addGLMesh(oldMesh.getGlType());
    // for (int oldIndex : oldMesh.getIndices()) {
    // newMesh.addIndex(indicesLUT.get(oldIndex));
    // }
    // }
    // this.invalidateBuffers();
    // }

}