Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.openglperf.cts;
     18 
     19 import java.lang.Math;
     20 import java.nio.ByteBuffer;
     21 import java.nio.ByteOrder;
     22 import java.nio.FloatBuffer;
     23 import java.nio.ShortBuffer;
     24 
     25 /*
     26  * Class for generating a sphere model for given input params
     27  * The generated class will have vertices and indices
     28  * Vertices data is composed of vertex coordinates in x, y, z followed by
     29  *  texture coordinates s, t for each vertex
     30  * Indices store vertex indices for the whole sphere.
     31  * Formula for generating sphere is originally coming from source code of
     32  * OpenGL ES2.0 Programming guide
     33  * which is available from http://code.google.com/p/opengles-book-samples/,
     34  * but some changes were made to make texture look right.
     35  */
     36 public class Sphere {
     37     public static final int FLOAT_SIZE = 4;
     38     public static final int SHORT_SIZE = 2;
     39 
     40     private FloatBuffer mVertices;
     41     private ShortBuffer[] mIndices;
     42     private int[] mNumIndices;
     43     private int mTotalIndices;
     44 
     45     /*
     46      * @param nSlices how many slice in horizontal direction.
     47      *                The same slice for vertical direction is applied.
     48      *                nSlices should be > 1 and should be <= 180
     49      * @param x,y,z the origin of the sphere
     50      * @param r the radius of the sphere
     51      */
     52     public Sphere(int nSlices, float x, float y, float z, float r, int numIndexBuffers) {
     53 
     54         int iMax = nSlices + 1;
     55         int nVertices = iMax * iMax;
     56         if (nVertices > Short.MAX_VALUE) {
     57             // this cannot be handled in one vertices / indices pair
     58             throw new RuntimeException("nSlices " + nSlices + " too big for vertex");
     59         }
     60         mTotalIndices = nSlices * nSlices * 6;
     61         float angleStepI = ((float) Math.PI / nSlices);
     62         float angleStepJ = ((2.0f * (float) Math.PI) / nSlices);
     63 
     64         // 3 vertex coords + 2 texture coords
     65         mVertices = ByteBuffer.allocateDirect(nVertices * 5 * FLOAT_SIZE)
     66                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
     67         mIndices = new ShortBuffer[numIndexBuffers];
     68         mNumIndices = new int[numIndexBuffers];
     69         // first evenly distribute to n-1 buffers, then put remaining ones to the last one.
     70         int noIndicesPerBuffer = (mTotalIndices / numIndexBuffers / 6) * 6;
     71         for (int i = 0; i < numIndexBuffers - 1; i++) {
     72             mNumIndices[i] = noIndicesPerBuffer;
     73         }
     74         mNumIndices[numIndexBuffers - 1] = mTotalIndices - noIndicesPerBuffer *
     75                 (numIndexBuffers - 1);
     76 
     77         for (int i = 0; i < numIndexBuffers; i++) {
     78             mIndices[i] = ByteBuffer.allocateDirect(mNumIndices[i] * SHORT_SIZE)
     79                     .order(ByteOrder.nativeOrder()).asShortBuffer();
     80         }
     81         // calling put for each float took too much CPU time, so put by line instead
     82         float[] vLineBuffer = new float[iMax * 5];
     83         for (int i = 0; i < iMax; i++) {
     84             for (int j = 0; j < iMax; j++) {
     85                 int vertexBase = j * 5;
     86                 float sini = (float) Math.sin(angleStepI * i);
     87                 float sinj = (float) Math.sin(angleStepJ * j);
     88                 float cosi = (float) Math.cos(angleStepI * i);
     89                 float cosj = (float) Math.cos(angleStepJ * j);
     90                 // vertex x,y,z
     91                 vLineBuffer[vertexBase + 0] = x + r * sini * sinj;
     92                 vLineBuffer[vertexBase + 1] = y + r * sini * cosj;
     93                 vLineBuffer[vertexBase + 2] = z + r * cosi;
     94                 // texture s,t
     95                 vLineBuffer[vertexBase + 3] = (float) j / (float) nSlices;
     96                 vLineBuffer[vertexBase + 4] = (1.0f - i) / (float)nSlices;
     97             }
     98             mVertices.put(vLineBuffer, 0, vLineBuffer.length);
     99         }
    100 
    101         short[] indexBuffer = new short[max(mNumIndices)];
    102         int index = 0;
    103         int bufferNum = 0;
    104         for (int i = 0; i < nSlices; i++) {
    105             for (int j = 0; j < nSlices; j++) {
    106                 int i1 = i + 1;
    107                 int j1 = j + 1;
    108                 if (index >= mNumIndices[bufferNum]) {
    109                     // buffer ready for moving to target
    110                     mIndices[bufferNum].put(indexBuffer, 0, mNumIndices[bufferNum]);
    111                     // move to the next one
    112                     index = 0;
    113                     bufferNum++;
    114                 }
    115                 indexBuffer[index++] = (short) (i * iMax + j);
    116                 indexBuffer[index++] = (short) (i1 * iMax + j);
    117                 indexBuffer[index++] = (short) (i1 * iMax + j1);
    118                 indexBuffer[index++] = (short) (i * iMax + j);
    119                 indexBuffer[index++] = (short) (i1 * iMax + j1);
    120                 indexBuffer[index++] = (short) (i * iMax + j1);
    121             }
    122         }
    123         mIndices[bufferNum].put(indexBuffer, 0, mNumIndices[bufferNum]);
    124 
    125         mVertices.position(0);
    126         for (int i = 0; i < numIndexBuffers; i++) {
    127             mIndices[i].position(0);
    128         }
    129     }
    130 
    131     public FloatBuffer getVertices() {
    132         return mVertices;
    133     }
    134 
    135     public int getVeticesStride() {
    136         return 5*FLOAT_SIZE;
    137     }
    138 
    139     public ShortBuffer[] getIndices() {
    140         return mIndices;
    141     }
    142 
    143     public int[] getNumIndices() {
    144         return mNumIndices;
    145     }
    146 
    147     public int getTotalIndices() {
    148         return mTotalIndices;
    149     }
    150 
    151 
    152     private int max(int[] array) {
    153         int max = array[0];
    154         for (int i = 1; i < array.length; i++) {
    155             if (array[i] > max) max = array[i];
    156         }
    157         return max;
    158     }
    159 }
    160