Package com.googlecode.gwtgl.wrapper

Source Code of com.googlecode.gwtgl.wrapper.Buffer$BufferFragment

/*
* 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.wrapper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.googlecode.gwtgl.binding.WebGLBuffer;
import com.googlecode.gwtgl.binding.WebGLRenderingContext;
import com.googlecode.gwtgl.wrapper.enums.BufferTarget;
import com.googlecode.gwtgl.wrapper.enums.BufferUsage;
import com.googlecode.gwtgl.wrapper.enums.DataType;

/**
* Wrapper class for the {@link WebGLBuffer} with automatic management of
* multiple arrays in one buffer.
*
* @author Steffen Schäfer
*
*/
/**
* @author Sönke Sothmann
* @author Steffen Schäfer
*
*/
public class Buffer {
 
  /**
   * A BufferFragment represents one set of datas inside a buffer object.
   */
  @SuppressWarnings("unused")
  private class BufferFragment {
    private Array<?, ?> dataToSet;
    private int offset;
    private int byteLength;
    private int maxLength;
    private int numElements;
    private DataType dataType;
   
    /**
     * @return the offset
     */
    public int getOffset() {
      return offset;
    }
   
    /**
     * @return the byteLength
     */
    public int getByteLength() {
      return byteLength;
    }
   
    /**
     * @return the maxLength
     */
    public int getMaxLength() {
      return maxLength;
    }
   
    /**
     * @return the numElements
     */
    public int getNumElements() {
      return numElements;
    }

    /**
     * @return the dataType
     */
    public DataType getDataType() {
      return dataType;
    }

    private void setData(Array<?, ?> dataToSet) {
      setData(dataToSet, false);
    }
   
    private void setData(Array<?, ?> dataToSet, boolean initial) {
      if (fixed && maxLength < dataToSet.getByteLength()) {
        throw new IllegalStateException(
            "The fragement's size is too small for the data to set!");
      }
      unsetData = true;

      this.dataToSet = dataToSet;
      if(initial) {
        maxLength = byteLength;
        if (fragments.isEmpty()) {
          offset = 0;
        } else {
          // get the last fragment to calculate the offset of the new one
          BufferFragment lastFragment = fragments.get(fragments.size() - 1);
          offset = lastFragment.offset + lastFragment.byteLength;
        }
      }
      byteLength = dataToSet.getByteLength();
      dataType=dataToSet.getDataType();
      numElements=dataToSet.getLength();
      if(maxLength < dataToSet.getByteLength()) {
        maxLength=dataToSet.getByteLength();
        recalcOffsets();
      }
    }
  }

  private List<BufferFragment> fragments = new ArrayList<BufferFragment>();
  private Map<String, BufferFragment> namedFragments = new HashMap<String, BufferFragment>();

  private boolean fixed = false;
  private boolean unsetData = false;

  private final WebGLBuffer nativeBufferObject;
  private final WebGLRenderingContext glContext;
  private final WebGLWrapper webGLWrapper;
  private final BufferTarget target;
  private final BufferUsage usage;

  /**
   * Creates a Buffer associated to the given webGLWrapper. The Buffer has a
   * BufferTarget and BufferUsage which is used to set the data.
   *
   * @param webGLWrapper
   * @param target
   * @param usage
   */
  public Buffer(WebGLWrapper webGLWrapper, BufferTarget target, BufferUsage usage) {
    this.webGLWrapper = webGLWrapper;
    this.glContext = webGLWrapper.glContext;
    this.nativeBufferObject = glContext.createBuffer();
    this.target = target;
    this.usage = usage;
  }

  /**
   * Adds a new managed array to the Buffer.
   *
   * @param name
   * @param dataToSet
   */
  public void addData(String name, Array<?, ?> dataToSet) {
    if (fixed) {
      throw new IllegalStateException(
          "The buffer is already fixed and no new data can be added.");
    }
    unsetData = true;
   
    BufferFragment fragment1 = new BufferFragment();
   
    fragment1.setData(dataToSet, true);
    BufferFragment fragment = fragment1;
    fragments.add(fragment);
    namedFragments.put(name, fragment);
  }

  /**
   * Sets new values for the named data array.
   *
   * @param name
   * @param dataToSet
   */
  public void setData(String name,Array<?, ?> dataToSet) {
    BufferFragment fragment = namedFragments.get(name);
    if (fragment == null) {
      throw new IllegalStateException("Fragment with name " + name
          + " not found!");
    }
    fragment.setData(dataToSet);
  }

  private void recalcOffsets() {
    int offset = 0;
    for (BufferFragment fragment : fragments) {
      fragment.offset = offset;
      offset += fragment.maxLength;
    }
  }

  /**
   * Is buffer bound?
   * @return true if buffer is bound, false otherwise
   */
  // TODO check if this works and make the method public
  private boolean isBound() {
    WebGLBuffer buffer = glContext.getParameter(target.getBinding());
    if (buffer == nativeBufferObject || nativeBufferObject.equals(buffer)) {
      return true;
    }
    return false;
  }

  /**
   * Binds the Buffer to the associated BufferTarget.
   */
  public void bind() {
    glContext.bindBuffer(target.getIntValue(), nativeBufferObject);
    // initialize the buffer and set the data if necessary
    setData();
  }

  private void setData() {
    if (!fixed) {
      // buffer is not initialized
      // claculate the needed size for all fragments to set and initialize
      // the buffer
      glContext.bufferData(target.getIntValue(), getLenght(), usage
          .getIntValue());
      fixed = true;
    }
    if (unsetData) {
      // some data is not set yet
      for (BufferFragment fragment : fragments) {
        if(fragment.dataToSet != null) {
          glContext.bufferSubData(target.getIntValue(), fragment.offset,
              fragment.dataToSet.getNativeArray());
          fragment.dataToSet = null;
        }
      }
      unsetData = false;
    }
  }

  private int getLenght() {
    int length = 0;
    for (BufferFragment fragment : fragments) {
      length += fragment.byteLength;
    }
    return length;
  }
 
  /**
   * Returns the byte offset of the given array.
   *
   * @param name
   * @return the byte offset of the given array
   */
  public int getOffset(String name) {
    BufferFragment fragment = namedFragments.get(name);
    if (fragment == null) {
      throw new IllegalStateException("Fragment with name " + name
          + " not found!");
    }
    return fragment.offset;
  }
 
  /**
   * Returns the byte length of the given array.
   *
   * @param name
   * @return the byte length of the given array
   */
  public int getByteLength(String name) {
    BufferFragment fragment = namedFragments.get(name);
    if (fragment == null) {
      throw new IllegalStateException("Fragment with name " + name
          + " not found!");
    }
    return fragment.byteLength;
  }

  /**
   * Delete the underlying Buffer object.
   */
  public void delete() {
    glContext.deleteBuffer(nativeBufferObject);
  }

  /**
   * Returns the {@link WebGLWrapper} the Buffer is associated to.
   *
   * @return the {@link WebGLWrapper} the Buffer is associated to
   */
  public WebGLWrapper getWebGLWrapper() {
    return webGLWrapper;
  }

}
TOP

Related Classes of com.googlecode.gwtgl.wrapper.Buffer$BufferFragment

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.