Android Open Source - droidengine2d Rectangle Batch Renderer






From Project

Back to project page droidengine2d.

License

The source code is released under:

Apache License

If you think the Android project droidengine2d listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*   Copyright 2013-2014 Miguel Vicente Linares
 */* ww  w. j av a 2  s . c om*/
 *  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 com.miviclin.droidengine2d.graphics.mesh;

import static com.miviclin.droidengine2d.util.PrimitiveTypeSize.SIZE_OF_FLOAT;
import static com.miviclin.droidengine2d.util.PrimitiveTypeSize.SIZE_OF_SHORT;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import android.opengl.GLES20;
import android.os.Build;

import com.miviclin.droidengine2d.BuildConfig;
import com.miviclin.droidengine2d.graphics.GLDebugger;
import com.miviclin.droidengine2d.graphics.cameras.Camera;
import com.miviclin.droidengine2d.graphics.material.BlendingOptions;
import com.miviclin.droidengine2d.graphics.material.Material;
import com.miviclin.droidengine2d.graphics.shader.ShaderProgram;
import com.miviclin.droidengine2d.util.math.Vector2;

/**
 * Base class for all batch renderers that render rectangles.<br>
 * Allows rendering a batch of rectangles, each rectangle having its own translation, rotation and scale, in one draw
 * call.
 * 
 * @author Miguel Vicente Linares
 * 
 * @param <M> Material
 */
public abstract class RectangleBatchRenderer<M extends Material> extends GraphicsBatchRenderer<M> {

  private int verticesDataStride;

  private ShortBuffer indexBuffer;
  private FloatBuffer vertexBuffer;
  private FloatBuffer mvpIndexBuffer;

  private RectangleBatchGeometry geometry;

  /**
   * Creates a new RectangleBatchRenderer.
   * 
   * @param verticesDataStride Data stride of the vertices.
   * @param batchCapacity Maximum size of this GraphicsBatch.
   */
  public RectangleBatchRenderer(int verticesDataStride, int batchCapacity) {
    super(batchCapacity);
    this.verticesDataStride = verticesDataStride;
    this.geometry = new RectangleBatchGeometry(32, false, true);
  }

  @Override
  protected void beginDraw() {
    ShaderProgram shaderProgram = getShaderProgram();
    if (!shaderProgram.isLinked()) {
      shaderProgram.compileAndLink();
    }
    shaderProgram.use();
  }

  @Override
  protected void endDraw() {
    if (getBatchSize() > 0) {
      drawBatch();
    }
  }

  /**
   * Initializes this batch renderer.
   */
  public void initialize() {
    setupIndices();
    setupVerticesData();

    indexBuffer = ByteBuffer.allocateDirect(getBatchCapacity() * 6 * SIZE_OF_SHORT)
        .order(ByteOrder.nativeOrder())
        .asShortBuffer();
    copyIndicesToIndexBuffer();

    vertexBuffer = ByteBuffer.allocateDirect(getBatchCapacity() * 4 * verticesDataStride * SIZE_OF_FLOAT)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();
    copyGeometryToVertexBuffer(getBatchCapacity());
    setVertexBufferLimit(getBatchCapacity());

    mvpIndexBuffer = ByteBuffer.allocateDirect(geometry.getMvpIndices().length * SIZE_OF_FLOAT)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();
    mvpIndexBuffer.put(geometry.getMvpIndices()).flip();
  }

  /**
   * Removes all elements of the vertex buffer and then copies the current geometry to the vertex buffer.<br>
   * After this method is called, {@link #setVertexBufferLimit()} must be called.
   * 
   * @param batchSize Number of elements of the current batch to be copied to the vertex buffer.
   */
  protected abstract void copyGeometryToVertexBuffer(int batchSize);

  /**
   * Sets the limit of the vertex buffer.<br>
   * This method must be called after {@link #copyGeometryToVertexBuffer()} is called.
   * 
   * @param batchSize Number of elements of the current batch copied to the vertex buffer.
   */
  protected void setVertexBufferLimit(int batchSize) {
    vertexBuffer.position(batchSize * verticesDataStride * 4).flip();
  }

  /**
   * Copies the indices of the geometry to the index buffer.
   */
  protected void copyIndicesToIndexBuffer() {
    int numIndices = getBatchCapacity() * 6;
    for (int i = 0; i < numIndices; i++) {
      indexBuffer.put(geometry.getIndex(i));
    }
    indexBuffer.flip();
  }

  /**
   * Sets up the array of indices of the geometry of the mesh used to render this batch.
   */
  protected void setupIndices() {
    int numIndices = getBatchCapacity() * 6;
    for (int i = 0, j = 0; i < numIndices; i += 6, j += 4) {
      geometry.addIndex((short) (j + 0));
      geometry.addIndex((short) (j + 1));
      geometry.addIndex((short) (j + 2));
      geometry.addIndex((short) (j + 2));
      geometry.addIndex((short) (j + 3));
      geometry.addIndex((short) (j + 0));
    }
  }

  /**
   * Sets up the vertices of the geometry of the mesh used to render this batch.<br>
   * The vertices of each rectangle must be defined in the following order:<br>
   * 1. Bottom-left.<br>
   * 2. Bottom-right.<br>
   * 3. Top-right.<br>
   * 4. Top-left.
   */
  protected abstract void setupVerticesData();

  /**
   * Transforms the rectangle located at the specified index of the batch.
   * 
   * @param index Index where the rectangle whose transform we want to update is located.
   * @param position Position.
   * @param scale Scale.
   * @param origin Origin of the rectangle (value between 0.0f and 1.0f).
   * @param rotation Rotation angle around the origin.
   * @param camera Camera.
   * 
   * @see RectangleBatchRenderer#setupVerticesData()
   */
  protected void updateTransform(int index, Vector2 position, Vector2 scale, Vector2 origin, float rotation,
      Camera camera) {

    if (origin.getX() < 0 || origin.getX() > 1 || origin.getY() < 0 || origin.getY() > 1) {
      throw new IllegalArgumentException("The origin coordinates must be in the [0..1] interval.");
    }

    int i = index * 4;
    float modelOriginX = 0.0f - (origin.getX() - 0.5f);
    float modelOriginY = 0.0f - (origin.getY() - 0.5f);
    // Bottom-Left
    geometry.getVertex(i + 0).set(modelOriginX - 0.5f, modelOriginY - 0.5f, 0.0f);
    // Bottom-Right
    geometry.getVertex(i + 1).set(modelOriginX + 0.5f, modelOriginY - 0.5f, 0.0f);
    // Top-Right
    geometry.getVertex(i + 2).set(modelOriginX + 0.5f, modelOriginY + 0.5f, 0.0f);
    // Top-Left
    geometry.getVertex(i + 3).set(modelOriginX - 0.5f, modelOriginY + 0.5f, 0.0f);
    // Update MVP matrix
    geometry.updateMVPMatrix(index, position, scale, rotation, camera);
  }

  /**
   * Prepares the geometry to be sent to the shader program.
   * 
   * @param batchSize Number of elements in the batch.
   */
  protected abstract void setupVertexShaderVariables(int batchSize);

  /**
   * Prepares the batch to be rendered.
   */
  protected void prepareDrawBatch() {
    int batchSize = getBatchSize();
    copyGeometryToVertexBuffer(batchSize);
    setVertexBufferLimit(batchSize);
    mvpIndexBuffer.limit(batchSize * 4).position(0);
    indexBuffer.limit(batchSize * 6).position(0);
    setupVertexShaderVariables(batchSize);
  }

  /**
   * Renders all the elements that are currently in this batch in one draw call.
   */
  protected void drawBatch() {
    prepareDrawBatch();

    BlendingOptions blendingOptions = getCurrentBatchBlendingOptions();
    GLES20.glBlendFunc(blendingOptions.getSourceFactor(), blendingOptions.getDestinationFactor());

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
      GLES20.glBlendEquation(blendingOptions.getBlendEquationMode());
    }

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexBuffer.limit(), GLES20.GL_UNSIGNED_SHORT, indexBuffer);

    if (BuildConfig.DEBUG) {
      GLDebugger.getInstance().incrementNumDrawCallsInCurrentFrame();
    }

    getCurrentBatchBlendingOptions().copy(getNextBatchBlendingOptions());
    setForceDraw(false);
    resetBatchSize();

    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Adds a rectangle to this batch.<br>
   * If the batch was full, it will be rendered in one draw call and it will be left empty. Then, the specified
   * rectangle will be added to this batch.
   * 
   * @param position Position.
   * @param scale Scale.
   * @param origin Origin of the rectangle (value between 0.0f and 1.0f).
   * @param rotation Rotation angle around the origin.
   * @param camera Camera.
   */
  public abstract void draw(Vector2 position, Vector2 scale, Vector2 origin, float rotation, Camera camera);

  /**
   * Returns the stride of the data of the vertices of this batch.
   * 
   * @return stride
   */
  protected int getVerticesDataStride() {
    return verticesDataStride;
  }

  /**
   * Returns the stride of the data of the vertices of this batch in bytes.
   * 
   * @return Stride
   */
  public int getVerticesDataStrideBytes() {
    return verticesDataStride * SIZE_OF_FLOAT;
  }

  /**
   * Sets the stride of the data of the vertices of this batch.
   * 
   * @param verticesDataStride stride
   */
  protected void setVerticesDataStride(int verticesDataStride) {
    this.verticesDataStride = verticesDataStride;
  }

  /**
   * Returns the index buffer of this batch.
   * 
   * @return index buffer
   */
  public ShortBuffer getIndexBuffer() {
    return indexBuffer;
  }

  /**
   * Returns the vertex buffer of this batch.
   * 
   * @return vertex buffer
   */
  public FloatBuffer getVertexBuffer() {
    return vertexBuffer;
  }

  /**
   * Returns the MVP index buffer of this batch.
   * 
   * @return MVP index buffer
   */
  public FloatBuffer getMvpIndexBuffer() {
    return mvpIndexBuffer;
  }

  /**
   * Returns the Geometry of this batch of this batch.
   * 
   * @return Geometry
   */
  public RectangleBatchGeometry getGeometry() {
    return geometry;
  }

  /**
   * Sets the Geometry of this batch of this batch.
   * 
   * @param geometry RectangleBatchGeometry.
   */
  public void setGeometry(RectangleBatchGeometry geometry) {
    this.geometry = geometry;
  }
}




Java Source Code List

com.miviclin.droidengine2d.AbstractGame.java
com.miviclin.droidengine2d.EngineActivity.java
com.miviclin.droidengine2d.EngineLock.java
com.miviclin.droidengine2d.Engine.java
com.miviclin.droidengine2d.GameThread.java
com.miviclin.droidengine2d.Game.java
com.miviclin.droidengine2d.audio.MusicPlayer.java
com.miviclin.droidengine2d.audio.SoundManager.java
com.miviclin.droidengine2d.gamestate.GameStateAdapter.java
com.miviclin.droidengine2d.gamestate.GameStateManager.java
com.miviclin.droidengine2d.gamestate.GameStateNotRegisteredException.java
com.miviclin.droidengine2d.gamestate.GameState.java
com.miviclin.droidengine2d.gamestate.OnGameStateChangeListener.java
com.miviclin.droidengine2d.graphics.Color.java
com.miviclin.droidengine2d.graphics.DefaultRenderer.java
com.miviclin.droidengine2d.graphics.EngineRenderer.java
com.miviclin.droidengine2d.graphics.GLDebugger.java
com.miviclin.droidengine2d.graphics.GLRenderer.java
com.miviclin.droidengine2d.graphics.GLView.java
com.miviclin.droidengine2d.graphics.Graphics.java
com.miviclin.droidengine2d.graphics.animation.AnimationFrame.java
com.miviclin.droidengine2d.graphics.animation.AnimationStateAdapter.java
com.miviclin.droidengine2d.graphics.animation.AnimationStateListener.java
com.miviclin.droidengine2d.graphics.animation.Animation.java
com.miviclin.droidengine2d.graphics.cameras.Camera.java
com.miviclin.droidengine2d.graphics.cameras.OrthographicCamera.java
com.miviclin.droidengine2d.graphics.material.BlendingOptions.java
com.miviclin.droidengine2d.graphics.material.ColorMaterial.java
com.miviclin.droidengine2d.graphics.material.Material.java
com.miviclin.droidengine2d.graphics.material.TextureColorMaterial.java
com.miviclin.droidengine2d.graphics.material.TextureHsvMaterial.java
com.miviclin.droidengine2d.graphics.material.TextureMaterial.java
com.miviclin.droidengine2d.graphics.material.TransparentTextureMaterial.java
com.miviclin.droidengine2d.graphics.material.UnsupportedMaterialException.java
com.miviclin.droidengine2d.graphics.mesh.ColorMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.Geometry.java
com.miviclin.droidengine2d.graphics.mesh.GraphicsBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.RectangleBatchGeometry.java
com.miviclin.droidengine2d.graphics.mesh.RectangleBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TextureColorMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TextureHsvMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TextureMaterialBatchRendererBase.java
com.miviclin.droidengine2d.graphics.mesh.TextureMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TransparentTextureMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.shader.ShaderProgramException.java
com.miviclin.droidengine2d.graphics.shader.ShaderProgram.java
com.miviclin.droidengine2d.graphics.shader.ShaderVars.java
com.miviclin.droidengine2d.graphics.text.BitmapFont.java
com.miviclin.droidengine2d.graphics.text.FontChar.java
com.miviclin.droidengine2d.graphics.text.Font.java
com.miviclin.droidengine2d.graphics.text.UndefinedCharacterException.java
com.miviclin.droidengine2d.graphics.texture.TextureAtlas.java
com.miviclin.droidengine2d.graphics.texture.TextureManager.java
com.miviclin.droidengine2d.graphics.texture.TexturePackerAtlas.java
com.miviclin.droidengine2d.graphics.texture.TextureRegion.java
com.miviclin.droidengine2d.graphics.texture.Texture.java
com.miviclin.droidengine2d.input.DefaultKeyEventProcessor.java
com.miviclin.droidengine2d.input.GameInputManager.java
com.miviclin.droidengine2d.input.GameStateInputManager.java
com.miviclin.droidengine2d.input.KeyEventInfo.java
com.miviclin.droidengine2d.input.KeyEventProcessor.java
com.miviclin.droidengine2d.input.KeyProcessor.java
com.miviclin.droidengine2d.input.MotionEventProcessor.java
com.miviclin.droidengine2d.input.TouchProcessor.java
com.miviclin.droidengine2d.input.sensor.AccelerometerValuesListener.java
com.miviclin.droidengine2d.input.sensor.Accelerometer.java
com.miviclin.droidengine2d.input.sensor.SensorUtilities.java
com.miviclin.droidengine2d.resources.AssetsLoader.java
com.miviclin.droidengine2d.util.ActivityUtilities.java
com.miviclin.droidengine2d.util.MutexLock.java
com.miviclin.droidengine2d.util.PrimitiveTypeSize.java
com.miviclin.droidengine2d.util.TransformUtilities.java
com.miviclin.droidengine2d.util.Transform.java
com.miviclin.droidengine2d.util.math.Matrix4.java
com.miviclin.droidengine2d.util.math.MatrixFix.java
com.miviclin.droidengine2d.util.math.Vector2.java
com.miviclin.droidengine2d.util.math.Vector3.java
com.miviclin.droidengine2d.util.time.TimeConstants.java
com.miviclin.droidengine2d.util.time.TimeCounter.java