Package com.googlecode.gwtgl.example.client.examples.skybox

Source Code of com.googlecode.gwtgl.example.client.examples.skybox.SkyboxExample

/**  
* Copyright 2009-2010 Sönke Sothmann, Steffen Schäfer and others
*
* 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.googlecode.gwtgl.example.client.examples.skybox;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.typedarrays.client.Float32Array;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.googlecode.gwtgl.binding.WebGLBuffer;
import com.googlecode.gwtgl.binding.WebGLProgram;
import com.googlecode.gwtgl.binding.WebGLRenderingContext;
import com.googlecode.gwtgl.binding.WebGLShader;
import com.googlecode.gwtgl.binding.WebGLTexture;
import com.googlecode.gwtgl.binding.WebGLUniformLocation;
import com.googlecode.gwtgl.example.client.AbstractGwtGLExample;
import com.googlecode.gwtgl.example.client.util.MatrixWidget;
import com.googlecode.gwtgl.example.client.util.math.FloatMatrix;
import com.googlecode.gwtgl.example.client.util.math.MatrixUtil;
import com.googlecode.gwtgl.example.client.util.mesh.CubeFactory;
import com.googlecode.gwtgl.example.client.util.mesh.Mesh;

/**
* Example that shows a skybox. User can look around using the mouse.
*
* @author Steffen Schäfer
* @author Sönke Sothmann
*
*/
public class SkyboxExample extends AbstractGwtGLExample {

  private Mesh cube = CubeFactory.createNewInstance(1.0f);
  private MatrixWidget perspectiveMatrixWidget;
  private MatrixWidget translationMatrixWidget;
  private MatrixWidget rotationMatrixWidget;
  private MatrixWidget resultingMatrixWidget;

  private WebGLTexture textureTop;
  private WebGLTexture textureBottom;
  private WebGLTexture textureFront;
  private WebGLTexture textureBack;
  private WebGLTexture textureLeft;
  private WebGLTexture textureRight;
  private WebGLUniformLocation textureUniform;
  private WebGLProgram shaderProgram;
  private WebGLBuffer buffer;

  private float translateZ = 0;
  private FloatMatrix perspectiveMatrix;
  private FloatMatrix translationMatrix;
  private FloatMatrix rotationMatrix;
  private FloatMatrix resultingMatrix;
  private Camera camera = new Camera();
  private int texCoordsOffset;
  private int vertexPositionAttribute;
  private int textureCoordAttribute;

  /**
   * Constructs an instance of the SkyboxWrapperExample.
   */
  public SkyboxExample() {
    // create an panel to show the matrices
    HorizontalPanel matrixPanel = new HorizontalPanel();
    perspectiveMatrixWidget = new MatrixWidget(4, 4, "perspective matrix:");
    translationMatrixWidget = new MatrixWidget(4, 4, "translation matrix:");
    rotationMatrixWidget = new MatrixWidget(4, 4, "rotation matrix:");
    resultingMatrixWidget = new MatrixWidget(4, 4, "resulting matrix:");
    matrixPanel.add(perspectiveMatrixWidget);
    matrixPanel.add(translationMatrixWidget);
    matrixPanel.add(rotationMatrixWidget);
    matrixPanel.add(resultingMatrixWidget);

    setWidget(2, 0, matrixPanel);
    getFlexCellFormatter().setColSpan(2, 0, 2);

    // Show a description of the controls
    HTML exampleDescription = new HTML(
        "<h2>Skyox Wrapper Example</h2><h3>Controls</h3><p>Hold down left mouse button on the canvas and move the mouse to look around.</p>");
    VerticalPanel descriptionAndControls = new VerticalPanel();
    descriptionAndControls.add(exampleDescription);
    setWidget(1, 1, descriptionAndControls);
  }

  /*
   * (non-Javadoc)
   *
   * @see com.googlecode.gwtgl.example.client.AbstractGwtGLExample#init()
   */
  @Override
  protected void init() {
    initParams();
    initTexture();
    initShaders();
    initBuffers();
    initControls();

    showMatrices();
  }

  /**
   * Updates the Matrix widgets every 500ms
   */
  private void showMatrices() {
    Timer timer = new Timer() {
      @Override
      public void run() {
        perspectiveMatrixWidget.setData(perspectiveMatrix);
        translationMatrixWidget.setData(translationMatrix);
        rotationMatrixWidget.setData(rotationMatrix);
        resultingMatrixWidget.setData(resultingMatrix);
      }
    };
    timer.scheduleRepeating(500);
  }

  /**
   * Initializes the controls of the example.
   */
  private void initControls() {
    webGLCanvas.addMouseMoveHandler(camera);
   
    webGLCanvas.addMouseDownHandler(camera);
   
    webGLCanvas.addMouseUpHandler(camera);
  }

  /**
   * Initialized the params of WebGL.
   */
  private void initParams() {
    // Set the background color
    glContext.clearColor(0.2f, 0.2f, 0.2f, 1.0f);
    // Set the clear depth (everything is cleared)
    glContext.clearDepth(1.0f);

    // Activate depth test and set the depth function
    glContext.enable(WebGLRenderingContext.DEPTH_TEST);
    glContext.depthFunc(WebGLRenderingContext.LEQUAL);
  }

  /**
   * Checks the WebGL Errors and throws an exception if there is an error.
   */
  private void checkErrors() {
    int error = glContext.getError();
    if (error != WebGLRenderingContext.NO_ERROR) {
      String errorDesc = "UNKNOWN";
      if (error == WebGLRenderingContext.INVALID_ENUM) {
        errorDesc="INVALID_ENUM";
      } else if (error == WebGLRenderingContext.INVALID_OPERATION) {
        errorDesc="INVALID_OPERATION";
      } else if (error == WebGLRenderingContext.INVALID_FRAMEBUFFER_OPERATION) {
        errorDesc="INVALID_FRAMEBUFFER_OPERATION";
      } else if (error == WebGLRenderingContext.OUT_OF_MEMORY) {
        errorDesc="OUT_OF_MEMORY";
      }
     
      String message = "WebGL Error: " + error+", "+errorDesc;
      GWT.log(message, null);
      throw new RuntimeException(message);
    }
  }

  /**
   * Creates the ShaderProgram used by the example to render.
   */
  private void initShaders() {
    WebGLShader vertexShader = getShader(WebGLRenderingContext.VERTEX_SHADER,
        Resources.INSTANCE.vertexShader().getText());
    WebGLShader fragmentShader = getShader(WebGLRenderingContext.FRAGMENT_SHADER,
        Resources.INSTANCE.fragmentShader().getText());
    // Create the program object
    shaderProgram = glContext.createProgram();
    glContext.attachShader(shaderProgram, vertexShader);
    glContext.attachShader(shaderProgram, fragmentShader);
   
    glContext.linkProgram(shaderProgram);
   
    vertexPositionAttribute = glContext.getAttribLocation(shaderProgram, "vertexPosition");
    glContext.enableVertexAttribArray(vertexPositionAttribute);
   
    textureCoordAttribute = glContext.getAttribLocation(shaderProgram, "texPosition");
      glContext.enableVertexAttribArray(textureCoordAttribute);
    // Check the link status
    boolean linked = glContext.getProgramParameterb(shaderProgram, WebGLRenderingContext.LINK_STATUS);
    if (!linked) {
      String infoLog = glContext.getProgramInfoLog(shaderProgram);
      GWT.log("Error linking program:\n" + infoLog, null);
      glContext.deleteProgram(shaderProgram);
      return;
    }

    textureUniform = glContext.getUniformLocation(shaderProgram, "tex");

    checkErrors();
  }

  /**
   * Initializes the buffers for vertex coordinates, normals and texture
   * coordinates.
   */
  private void initBuffers() {
    buffer = glContext.createBuffer();
    glContext.bindBuffer(WebGLRenderingContext.ARRAY_BUFFER, buffer);
   
    Float32Array vertices = Float32Array.create(cube.getVertices());
    texCoordsOffset = vertices.getByteLength();
    Float32Array texCoords = Float32Array.create(cube.getTexCoords());
   
    glContext.bufferData(WebGLRenderingContext.ARRAY_BUFFER,
        vertices.getByteLength() + texCoords.getByteLength(),
        WebGLRenderingContext.STATIC_DRAW);
   
    glContext
        .bufferSubData(WebGLRenderingContext.ARRAY_BUFFER, 0, vertices);
    glContext.bufferSubData(WebGLRenderingContext.ARRAY_BUFFER,
        texCoordsOffset, texCoords);
   
    checkErrors();
  }

  /*
   * (non-Javadoc)
   *
   * @see com.googlecode.gwtgl.example.client.AbstractGwtGLExample#draw()
   */
  @Override
  protected void draw() {
    glContext.clear(WebGLRenderingContext.COLOR_BUFFER_BIT | WebGLRenderingContext.DEPTH_BUFFER_BIT);
    // Use the program object
    glContext.useProgram(shaderProgram);

    // Load the vertex data
    glContext.bindBuffer(WebGLRenderingContext.ARRAY_BUFFER, buffer);
    glContext.vertexAttribPointer(vertexPositionAttribute, 3, WebGLRenderingContext.FLOAT, false, 0, 0);

    glContext.vertexAttribPointer(textureCoordAttribute, 2, WebGLRenderingContext.FLOAT, false, 0, texCoordsOffset);
    WebGLUniformLocation mvUniform = glContext.getUniformLocation(shaderProgram, "projectionMatrix");

    perspectiveMatrix = MatrixUtil.createPerspectiveMatrix(45, 1.0f, 0.1f, 100);
    translationMatrix = MatrixUtil.createTranslationMatrix(0, 0, translateZ);
    rotationMatrix = MatrixUtil.createRotationMatrix(camera.getRotationXAxis(), camera.getRotationYAxis(), 0);
    resultingMatrix = perspectiveMatrix.multiply(translationMatrix).multiply(rotationMatrix);

    glContext.uniformMatrix4fv(mvUniform, false, resultingMatrix.getColumnWiseFlatData());
    glContext.uniform1i(textureUniform, 0);
   
    glContext.activeTexture(WebGLRenderingContext.TEXTURE0);
   
    glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, textureBack);
    glContext.drawArrays(WebGLRenderingContext.TRIANGLES, 0, 6);
   
    glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, textureFront);
    glContext.drawArrays(WebGLRenderingContext.TRIANGLES, 6, 6);
   
    glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, textureLeft);
    glContext.drawArrays(WebGLRenderingContext.TRIANGLES, 12, 6);
   
    glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, textureRight);
    glContext.drawArrays(WebGLRenderingContext.TRIANGLES, 18, 6);
   
    glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, textureTop);
    glContext.drawArrays(WebGLRenderingContext.TRIANGLES, 24, 6);
   
    glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, textureBottom);
    glContext.drawArrays(WebGLRenderingContext.TRIANGLES, 30, 6);
   
    checkErrors();
    glContext.flush();
    checkErrors();
  }

  /**
   * Initializes the textures of this example.
   */
  private void initTexture() {
    // Create and initialize the WebGLTexture objects.
    textureFront = createTexture(Resources.INSTANCE.textureSkyboxFt());
    textureBack = createTexture(Resources.INSTANCE.textureSkyboxBk());
    textureTop = createTexture(Resources.INSTANCE.textureSkyboxUp());
    textureBottom = createTexture(Resources.INSTANCE.textureSkyboxDn());
    textureLeft = createTexture(Resources.INSTANCE.textureSkyboxLf());
    textureRight = createTexture(Resources.INSTANCE.textureSkyboxRt());
    checkErrors();
  }

  private WebGLTexture createTexture(ImageResource imageResource) {
    final WebGLTexture texture = glContext.createTexture();
   
    final Image img = new Image();
    img.addLoadHandler(new LoadHandler() {
      @Override
      public void onLoad(LoadEvent event) {
        RootPanel.get().remove(img);
       
        glContext.activeTexture(WebGLRenderingContext.TEXTURE0);
        glContext.bindTexture(WebGLRenderingContext.TEXTURE_2D, texture);
       
        glContext.texParameteri(WebGLRenderingContext.TEXTURE_2D, WebGLRenderingContext.TEXTURE_MIN_FILTER, WebGLRenderingContext.NEAREST);
        glContext.texParameteri(WebGLRenderingContext.TEXTURE_2D, WebGLRenderingContext.TEXTURE_MAG_FILTER, WebGLRenderingContext.NEAREST);
        glContext.texParameteri(WebGLRenderingContext.TEXTURE_2D, WebGLRenderingContext.TEXTURE_WRAP_S, WebGLRenderingContext.CLAMP_TO_EDGE);
        glContext.texParameteri(WebGLRenderingContext.TEXTURE_2D, WebGLRenderingContext.TEXTURE_WRAP_T, WebGLRenderingContext.CLAMP_TO_EDGE);
       
        glContext.texImage2D(WebGLRenderingContext.TEXTURE_2D, 0, WebGLRenderingContext.RGBA,WebGLRenderingContext.RGBA, WebGLRenderingContext.UNSIGNED_BYTE, img.getElement());
        checkErrors();
      }
    });
    img.setVisible(false);
    RootPanel.get().add(img);
    // image.setResource(imageResource);
    // TODO doesn't work with more than one image bundled to one
    // ImageBundle if the browser doesn't support data:... urls
    // So it's no problem at the moment because Chrome and FF support it
    img.setUrl(imageResource.getURL());
    return texture;
  }

  /**
   * Creates an Shader instance defined by the ShaderType and the source.
   *
   * @param shaderType
   *            the type of the shader to create
   * @param source
   *            the source of the shader
   * @return the created Shader instance.
   */
  WebGLShader getShader(int shaderType, String source) {
    WebGLShader shader = glContext.createShader(shaderType);
    glContext.shaderSource(shader, source);
    glContext.compileShader(shader);

    // check if the Shader is successfully compiled
    if (!glContext.getShaderParameterb(shader, WebGLRenderingContext.COMPILE_STATUS)) {
      throw new RuntimeException(glContext.getShaderInfoLog(shader));
    }

    return shader;

  }

}
TOP

Related Classes of com.googlecode.gwtgl.example.client.examples.skybox.SkyboxExample

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.