Mega Code Archive

 
Categories / Android / File
 

Fast Float Buffer

//package com.ryanm.droid.rugl.util; import java.lang.ref.SoftReference; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; /**  * Convenient work-around for poor {@link FloatBuffer#put(float[])} performance.  * This should become unnecessary in gingerbread, @see <a href  * ="http://code.google.com/p/android/issues/detail?id=11078">Issue 11078</a>  *   * @author ryanm  */ public class FastFloatBuffer {   /**    * Underlying data - give this to OpenGL    */   public ByteBuffer bytes;   private FloatBuffer floats;   private IntBuffer ints;   /**    * Use a {@link SoftReference} so that the array can be collected if    * necessary    */   private static SoftReference<int[]> intArray = new SoftReference<int[]>(       new int[0]);   /**    * Constructs a new direct native-ordered buffer    *     * @param capacity    *            the number of floats    */   public FastFloatBuffer(int capacity) {     bytes = ByteBuffer.allocateDirect((capacity * 4)).order(         ByteOrder.nativeOrder());     floats = bytes.asFloatBuffer();     ints = bytes.asIntBuffer();   }   /**    * See {@link FloatBuffer#flip()}    */   public void flip() {     bytes.flip();     floats.flip();     ints.flip();   }   /**    * See {@link FloatBuffer#put(float)}    *     * @param f    */   public void put(float f) {     bytes.position(bytes.position() + 4);     floats.put(f);     ints.position(ints.position() + 1);   }   /**    * It's like {@link FloatBuffer#put(float[])}, but about 10 times faster    *     * @param data    */   public void put(float[] data) {     int[] ia = intArray.get();     if (ia == null || ia.length < data.length) {       ia = new int[data.length];       intArray = new SoftReference<int[]>(ia);     }     for (int i = 0; i < data.length; i++) {       ia[i] = Float.floatToRawIntBits(data[i]);     }     bytes.position(bytes.position() + 4 * data.length);     floats.position(floats.position() + data.length);     ints.put(ia, 0, data.length);   }   /**    * For use with pre-converted data. This is 50x faster than    * {@link #put(float[])}, and 500x faster than    * {@link FloatBuffer#put(float[])}, so if you've got float[] data that    * won't change, {@link #convert(float...)} it to an int[] once and use this    * method to put it in the buffer    *     * @param data    *            floats that have been converted with    *            {@link Float#floatToIntBits(float)}    */   public void put(int[] data) {     bytes.position(bytes.position() + 4 * data.length);     floats.position(floats.position() + data.length);     ints.put(data, 0, data.length);   }   /**    * Converts float data to a format that can be quickly added to the buffer    * with {@link #put(int[])}    *     * @param data    * @return the int-formatted data    */   public static int[] convert(float... data) {     int[] id = new int[data.length];     for (int i = 0; i < data.length; i++) {       id[i] = Float.floatToRawIntBits(data[i]);     }     return id;   }   /**    * See {@link FloatBuffer#put(FloatBuffer)}    *     * @param b    */   public void put(FastFloatBuffer b) {     bytes.put(b.bytes);     floats.position(bytes.position() >> 2);     ints.position(bytes.position() >> 2);   }   /**    * @return See {@link FloatBuffer#capacity()}    */   public int capacity() {     return floats.capacity();   }   /**    * @return See {@link FloatBuffer#position()}    */   public int position() {     return floats.position();   }   /**    * See {@link FloatBuffer#position(int)}    *     * @param p    */   public void position(int p) {     bytes.position(4 * p);     floats.position(p);     ints.position(p);   }   /**    * @return See {@link FloatBuffer#slice()}    */   public FloatBuffer slice() {     return floats.slice();   }   /**    * @return See {@link FloatBuffer#remaining()}    */   public int remaining() {     return floats.remaining();   }   /**    * @return See {@link FloatBuffer#limit()}    */   public int limit() {     return floats.limit();   }   /**    * See {@link FloatBuffer#clear()}    */   public void clear() {     bytes.clear();     floats.clear();     ints.clear();   } }