org.jogamp.glg2d.VertexBuffer.java Source code

Java tutorial

Introduction

Here is the source code for org.jogamp.glg2d.VertexBuffer.java

Source

/*
 * Copyright 2013 Brandon Borkholder
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jogamp.glg2d;

import java.nio.FloatBuffer;

import org.lwjgl.opengl.GL11;
import org.lwjgl.BufferUtils;

/**
 * Wraps a simple {@code FloatBuffer} and makes it easier to push 2-D vertices
 * into the buffer and then draw them using any mode desired. The default
 * constructor uses a global buffer since drawing in OpenGL is not
 * multi-threaded.
 */
public class VertexBuffer {
    protected static VertexBuffer shared = new VertexBuffer(1024);

    protected FloatBuffer buffer;

    protected int deviceBufferId;

    /**
     * Creates a buffer that uses the shared global buffer. This is faster than
     * allocating multiple float buffers. Since OpenGL is single-threaded, we can
     * assume this won't be accessed outside the OpenGL thread and typically one
     * object is drawn completely before another one. If this is not true, one of
     * the objects being drawn simultaneously must use a private buffer. See
     * {@code #VertexBuffer(int)}.
     */
    public static VertexBuffer getSharedBuffer() {
        shared.clear();
        return shared;
    }

    protected VertexBuffer(FloatBuffer buffer) {
        this.buffer = buffer;
    }

    /**
     * Creates a private buffer. This can be used without fear of clobbering the
     * global buffer. This should only be used if you have a need to create two
     * parallel shapes at the same time.
     * 
     * @param capacity
     *          The size of the buffer in number of vertices
     */
    public VertexBuffer(int capacity) {
        this(BufferUtils.createFloatBuffer(capacity * 2));
    }

    /**
     * Adds multiple vertices to the buffer.
     * 
     * @param array
     *          The array containing vertices in the form (x,y),(x,y)
     * @param offset
     *          The starting index
     * @param numVertices
     *          The number of vertices, pairs of floats
     */
    public void addVertex(float[] array, int offset, int numVertices) {
        int numFloats = numVertices * 2;
        ensureCapacity(numFloats);
        buffer.put(array, offset, numFloats);
    }

    /**
     * Adds a vertex to the buffer.
     * 
     * @param x
     *          The x coordinate
     * @param y
     *          The y coordinate
     */
    public void addVertex(float x, float y) {
        ensureCapacity(2);
        buffer.put(x);
        buffer.put(y);
    }

    /**
     * Adds multiple vertices to the buffer.
     * 
     * @param vertices
     *          The buffer of new vertices to add.
     */
    public void addVertices(FloatBuffer vertices) {
        int size = vertices.limit() - vertices.position();
        ensureCapacity(size);

        buffer.put(vertices);
    }

    protected void ensureCapacity(int numNewFloats) {
        if (buffer.capacity() <= buffer.position() + numNewFloats) {
            FloatBuffer larger = BufferUtils.createFloatBuffer(buffer.position() * 2);
            deviceBufferId = -deviceBufferId;
            int position = buffer.position();
            buffer.rewind();
            larger.put(buffer);
            buffer = larger;
            buffer.position(position);
        }
    }

    /**
     * Discard all existing points. This method is not necessary unless the points
     * already added are not needed anymore and the buffer will be reused.
     */
    public void clear() {
        buffer.clear();
    }

    public FloatBuffer getBuffer() {
        return buffer;
    }

    /**
     * Draws the vertices and rewinds the buffer to be ready to draw next time.
     * 
     * @param gl
     *          The graphics context to use to draw
     * @param mode
     *          The mode, e.g. {@code GL#GL_LINE_STRIP}
     */
    public void drawBuffer(int mode) {
        if (buffer.position() == 0) {
            return;
        }

        int count = buffer.position();
        buffer.rewind();

        GL11.glVertexPointer(2, 0, buffer);

        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDrawArrays(mode, 0, count / 2);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);

        buffer.position(count);
    }
}