• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package android.gameperformance;
17 
18 import java.nio.ByteBuffer;
19 import java.nio.ByteOrder;
20 
21 /**
22  * Helper class that generates patch to render. Patch is a regular polygon with the center in 0.
23  * Regular polygon fits in circle with requested radius.
24  */
25 public class RenderPatch {
26     public static final int FLOAT_SIZE = 4;
27     public static final int SHORT_SIZE = 2;
28     public static final int VERTEX_COORD_COUNT = 3;
29     public static final int VERTEX_STRIDE = VERTEX_COORD_COUNT * FLOAT_SIZE;
30     public static final int TEXTURE_COORD_COUNT = 2;
31     public static final int TEXTURE_STRIDE = TEXTURE_COORD_COUNT * FLOAT_SIZE;
32 
33     // Tessellation is done using points on circle.
34     public static final int TESSELLATION_BASE = 0;
35     // Tesselation is done using extra point in 0.
36     public static final int TESSELLATION_TO_CENTER = 1;
37 
38     // Radius of circle that fits polygon.
39     private final float mDimension;
40 
41     private final ByteBuffer mVertexBuffer;
42     private final ByteBuffer mTextureBuffer;
43     private final ByteBuffer mIndexBuffer;
44 
RenderPatch(int triangleCount, float dimension, int tessellation)45     public RenderPatch(int triangleCount, float dimension, int tessellation) {
46         mDimension = dimension;
47 
48         int pointCount;
49         int externalPointCount;
50 
51         if (triangleCount < 1) {
52             throw new IllegalArgumentException("Too few triangles to perform tessellation");
53         }
54 
55         switch (tessellation) {
56         case TESSELLATION_BASE:
57             externalPointCount = triangleCount + 2;
58             pointCount = externalPointCount;
59             break;
60         case TESSELLATION_TO_CENTER:
61             if (triangleCount < 3) {
62                 throw new IllegalArgumentException(
63                         "Too few triangles to perform tessellation to center");
64             }
65             externalPointCount = triangleCount;
66             pointCount = triangleCount + 1;
67             break;
68         default:
69             throw new IllegalArgumentException("Wrong tesselation requested");
70         }
71 
72         if (pointCount > Short.MAX_VALUE) {
73             throw new IllegalArgumentException("Number of requested triangles is too big");
74         }
75 
76         mVertexBuffer = ByteBuffer.allocateDirect(pointCount * VERTEX_STRIDE);
77         mVertexBuffer.order(ByteOrder.nativeOrder());
78 
79         mTextureBuffer = ByteBuffer.allocateDirect(pointCount * TEXTURE_STRIDE);
80         mTextureBuffer.order(ByteOrder.nativeOrder());
81 
82         for (int i = 0; i < externalPointCount; ++i) {
83             // Use 45 degree rotation to make quad aligned along axises in case
84             // triangleCount is four.
85             final double angle = Math.PI * 0.25 + (Math.PI * 2.0 * i) / (externalPointCount);
86             // Positions
87             mVertexBuffer.putFloat((float) (dimension * Math.sin(angle)));
88             mVertexBuffer.putFloat((float) (dimension * Math.cos(angle)));
89             mVertexBuffer.putFloat(0.0f);
90             // Texture coordinates.
91             mTextureBuffer.putFloat((float) (0.5 + 0.5 * Math.sin(angle)));
92             mTextureBuffer.putFloat((float) (0.5 - 0.5 * Math.cos(angle)));
93         }
94 
95         if (tessellation == TESSELLATION_TO_CENTER) {
96             // Add center point.
97             mVertexBuffer.putFloat(0.0f);
98             mVertexBuffer.putFloat(0.0f);
99             mVertexBuffer.putFloat(0.0f);
100             mTextureBuffer.putFloat(0.5f);
101             mTextureBuffer.putFloat(0.5f);
102         }
103 
104         mIndexBuffer =
105                 ByteBuffer.allocateDirect(
106                         triangleCount * 3 /* indices per triangle */ * SHORT_SIZE);
107         mIndexBuffer.order(ByteOrder.nativeOrder());
108 
109         switch (tessellation) {
110         case TESSELLATION_BASE:
111             for (int i = 0; i < triangleCount; ++i) {
112                 mIndexBuffer.putShort((short) 0);
113                 mIndexBuffer.putShort((short) (i + 1));
114                 mIndexBuffer.putShort((short) (i + 2));
115             }
116             break;
117         case TESSELLATION_TO_CENTER:
118             for (int i = 0; i < triangleCount; ++i) {
119                 mIndexBuffer.putShort((short)i);
120                 mIndexBuffer.putShort((short)((i + 1) % externalPointCount));
121                 mIndexBuffer.putShort((short)externalPointCount);
122             }
123             break;
124         }
125 
126         if (mVertexBuffer.remaining() != 0 || mTextureBuffer.remaining() != 0 || mIndexBuffer.remaining() != 0) {
127             throw new RuntimeException("Failed to fill buffers");
128         }
129 
130         mVertexBuffer.position(0);
131         mTextureBuffer.position(0);
132         mIndexBuffer.position(0);
133     }
134 
getDimension()135     public float getDimension() {
136         return mDimension;
137     }
138 
getVertexBuffer()139     public ByteBuffer getVertexBuffer() {
140         return mVertexBuffer;
141     }
142 
getTextureBuffer()143     public ByteBuffer getTextureBuffer() {
144         return mTextureBuffer;
145     }
146 
getIndexBuffer()147     public ByteBuffer getIndexBuffer() {
148         return mIndexBuffer;
149     }
150 }