OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SuperEllipsoidModel.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2012-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "SuperEllipsoidModel.h"
22 
23 #include "Platform.h"
24 #include "Mathematics.h"
25 
26 #include <cstdlib>
27 
28 namespace MaliSDK
29 {
30  void SuperEllipsoidModel::create(int samples, float n1, float n2, float scale, float** roundedCubeCoordinates, float** roundedCubeNormalVectors, int* numberOfVertices, int* numberOfCoordinates, int* numberOfNormals)
31  {
32  /* Check if samples is different than 0. */
33  if (samples == 0)
34  {
35  LOGE("Number of samples can't be 0.");
36  return;
37  }
38 
39  /*
40  * Computation of the numberOfCoordinates results from the algorithm used in this function.
41  * In the first "for" loop we can see that this loop iterates samples / 2 times. Then in the second loop
42  * we can see that this loop will go samples times.
43  * In total, there are samples / 2 * samples iterations.
44  * Each iteration produces 6 vertices and each vertex has 4 coordinates.
45  */
46  *numberOfCoordinates = samples / 2 * samples * 6 * 4;
47 
48  /* The number of normals is the same except that each normal only has 3 coordinates. */
49  *numberOfNormals = samples / 2 * samples * 6 * 3;
50 
51  /* Allocate memory to store rounded cube's coordinates. */
52  *roundedCubeCoordinates = new float[*numberOfCoordinates];
53 
54  if (roundedCubeCoordinates == NULL)
55  {
56  LOGE("Pointer roundedCubeCoordinates is NULL.");
57  return;
58  }
59 
60  /* Allocate memory to store rounded cube's normal vectors. */
61  *roundedCubeNormalVectors = new float[*numberOfNormals];
62 
63  if (roundedCubeNormalVectors == NULL)
64  {
65  LOGE("Pointer roundedCubeNormalVectors is NULL.");
66  return;
67  }
68 
69  /* Calculate the number of vertices for the rounded cube. */
70  *numberOfVertices = *numberOfCoordinates / 4;
71 
72  /* Values to store temporarily vertices and normal vectors. */
73  Vec3f vertex, normalVector;
74 
75  /* Value vertexIndex determines the beginning of array where vertices should be saved. */
76  int vertexIndex = 0;
77 
78  /* Value normalVectorIndex determines the beginning of array where normal vectors should be saved. */
79  int normalVectorIndex = 0;
80 
81  /* These values will change xzAngle and xyAngle. */
82  float xzAngleDelta = 2.0f * M_PI / samples;
83  float xyAngleDelta = 2.0f * M_PI / samples;
84 
85  /* Angle used to compute vertices and normal vectors. */
86  float xyAngle = -M_PI / 2.0f;
87 
88  /* This loop goes samples / 2 times because in each second loop we create 2 triangles. */
89  for (int j = 0; j < samples / 2; j++)
90  {
91  /* Angle used to compute vertices and normal vectors. */
92  float xzAngle = -M_PI;
93 
94  for (int i = 0; i < samples; i++)
95  {
96  /* Triangle #1 */
97  /* Calculate first vertex and normal vector. */
98  vertex = sample (xyAngle, xzAngle, n1, n2, scale);
99  normalVector = calculateNormal(xyAngle, xzAngle, n1, n2, scale);
100 
101  /* Put vertex and normal vector coordinates into array. */
102  storeVertexAndNormalVectorInArray(vertex, normalVector, vertexIndex, normalVectorIndex, *roundedCubeCoordinates, *roundedCubeNormalVectors);
103 
104  /* Calculate second vertex and normal vector. */
105  vertex = sample (xyAngle + xyAngleDelta, xzAngle, n1, n2, scale);
106  normalVector = calculateNormal(xyAngle + xyAngleDelta, xzAngle, n1, n2, scale);
107 
108  /* Put vertex and normal vector coordinates into array. */
109  storeVertexAndNormalVectorInArray(vertex, normalVector, vertexIndex, normalVectorIndex, *roundedCubeCoordinates, *roundedCubeNormalVectors);
110 
111  /* Calculate third vertex and normal vector. */
112  vertex = sample (xyAngle + xyAngleDelta, xzAngle + xzAngleDelta, n1, n2, scale);
113  normalVector = calculateNormal(xyAngle + xyAngleDelta, xzAngle + xzAngleDelta, n1, n2, scale);
114 
115  /* Put vertex and normal vector coordinates into array. */
116  storeVertexAndNormalVectorInArray(vertex, normalVector, vertexIndex, normalVectorIndex, *roundedCubeCoordinates, *roundedCubeNormalVectors);
117 
118  /* Triangle #2 */
119  /* Calculate first vertex and normal vector. */
120  vertex = sample (xyAngle, xzAngle, n1, n2, scale);
121  normalVector = calculateNormal(xyAngle, xzAngle, n1, n2, scale);
122 
123  /* Put vertex and normal vector coordinates into array. */
124  storeVertexAndNormalVectorInArray(vertex, normalVector, vertexIndex, normalVectorIndex, *roundedCubeCoordinates, *roundedCubeNormalVectors);
125 
126  /* Calculate second vertex and normal vector. */
127  vertex = sample (xyAngle + xyAngleDelta, xzAngle + xzAngleDelta, n1, n2, scale);
128  normalVector = calculateNormal(xyAngle + xyAngleDelta, xzAngle + xzAngleDelta, n1, n2, scale);
129 
130  /* Put vertex and normal vector coordinates into array. */
131  storeVertexAndNormalVectorInArray(vertex, normalVector, vertexIndex, normalVectorIndex, *roundedCubeCoordinates, *roundedCubeNormalVectors);
132 
133  /* Calculate third vertex and normal vector. */
134  vertex = sample (xyAngle, xzAngle + xzAngleDelta, n1, n2, scale);
135  normalVector = calculateNormal(xyAngle, xzAngle + xzAngleDelta, n1, n2, scale);
136 
137  /* Put vertex and normal vector coordinates into array. */
138  storeVertexAndNormalVectorInArray(vertex, normalVector, vertexIndex, normalVectorIndex, *roundedCubeCoordinates, *roundedCubeNormalVectors);
139 
140  /* Change xzAngle value. */
141  xzAngle += xzAngleDelta;
142  }
143 
144  /* Change xyAngle value. */
145  xyAngle += xyAngleDelta;
146  }
147  }
148 
149  Vec3f SuperEllipsoidModel::calculateNormal(float xyAngle, float xzAngle, float n1, float n2, float scale)
150  {
151  /* Pre-calculate sine and cosine values for both angles. */
152  float cosPhi = cosf(xyAngle);
153  float cosBeta = cosf(xzAngle);
154  float sinPhi = sinf(xyAngle);
155  float sinBeta = sinf(xzAngle);
156 
157  /*
158  * The equations for x, y and z coordinates are:
159  * x = 1 / rx * cos^(2 - n1)(xyAngle) * cos^(2 - n2)(xzAngle)
160  * y = 1 / ry * sin^(2 - n1)(xyAngle)
161  * z = 1 / rz * cos^(2 - n1)(xyAngle) * sin^(2 - n2)(xzAngle)
162  *
163  * where:
164  * -M_PI/2 <= xyAngle <= M_PI/2
165  * -M_PI <= xzAngle <= M_PI
166  * 0 < n1, n2 < infinity
167  *
168  * As for two-dimensional case rx, ry, and rz are scale factors for each axis (axis intercept).
169  */
170 
171  /* Normal vector to be returned. */
172  Vec3f normal;
173 
174  normal.x = signum(cosPhi) * powf(fabs(cosPhi), 2 - n1) * signum(cosBeta) * powf(fabs(cosBeta), 2 - n2) / scale;
175  normal.y = signum(sinPhi) * powf(fabs(sinPhi), 2 - n1) / scale;
176  normal.z = signum(cosPhi) * powf(fabs(cosPhi), 2 - n1) * signum(sinBeta) * powf(fabs(sinBeta), 2 - n2) / scale;
177 
178  /* Normalize vector. */
179  normal.normalize();
180 
181  return normal;
182  }
183 
184  Vec3f SuperEllipsoidModel::sample(float xyAngle, float xzAngle, float n1, float n2, float scale)
185  {
186  /* Pre-calculate sine and cosine values for both angles. */
187  const float xyAngleCos = cosf(xyAngle);
188  const float xzAngleCos = cosf(xzAngle);
189  const float xyAngleSin = sinf(xyAngle);
190  const float xzAngleSin = sinf(xzAngle);
191 
192  /*
193  * The equations for x, y and z coordinates are given below:
194  *
195  * x = rx * cos^n1(xyAngle) * cos^n2(xzAngle)
196  * y = ry * sin^n1(xyAngle)
197  * z = rz * cos^n1(xyAngle) * sin^n2(xzAngle)
198  *
199  * where:
200  *
201  * -M_PI/2 <= xyAngle <= M_PI/2
202  * -M_PI <= xzAngle <= M_PI
203  * 0 < n1, n2 < infinity
204  *
205  * As for two-dimensional case rx, ry, and rz are scale factors for each axis (axis intercept).
206  */
207 
208  /* Vertex to be returned. */
209  Vec3f vertex;
210 
211  vertex.x = scale * MaliSDK::signum(xyAngleCos) * powf(fabs(xyAngleCos), n1) * MaliSDK::signum(xzAngleCos) * powf(fabs(xzAngleCos), n2);
212  vertex.y = scale * MaliSDK::signum(xyAngleSin) * powf(fabs(xyAngleSin), n1);
213  vertex.z = scale * MaliSDK::signum(xyAngleCos) * powf(fabs(xyAngleCos), n1) * MaliSDK::signum(xzAngleSin) * powf(fabs(xzAngleSin), n2);
214 
215  return vertex;
216  }
217 
218  void SuperEllipsoidModel::storeVertexAndNormalVectorInArray(const Vec3f& vertex, const Vec3f& normalVector, int& vertexIndex, int& normalVectorIndex, float* roundedCubeCoordinates, float* roundedCubeNormalVectors)
219  {
220  /* Save vertex and increment counter/index. */
221  roundedCubeCoordinates[vertexIndex++] = vertex.x;
222  roundedCubeCoordinates[vertexIndex++] = vertex.y;
223  roundedCubeCoordinates[vertexIndex++] = vertex.z;
224  roundedCubeCoordinates[vertexIndex++] = 1.0f;
225 
226  /* Save normal vector and increment counter/index. */
227  roundedCubeNormalVectors[normalVectorIndex++] = normalVector.x;
228  roundedCubeNormalVectors[normalVectorIndex++] = normalVector.y;
229  roundedCubeNormalVectors[normalVectorIndex++] = normalVector.z;
230  }
231 }
static void storeVertexAndNormalVectorInArray(const Vec3f &vertex, const Vec3f &normalVector, int &vertexIndex, int &normalVectorIndex, float *roundedCubeCoordinates, float *roundedCubeNormalVectors)
Put vertex and normal vector values into vertex array and normal vector array.
static Vec3f calculateNormal(float xyAngle, float xzAngle, float n1, float n2, float scale)
Compute normal vector of a super ellipsoid.
static Vec3f sample(float xyAngle, float xzAngle, float n1, float n2, float scale)
Compute vertex of a super ellipsoid.
A 3D floating point vector.
Definition: VectorTypes.h:83
float signum(float f)
Get the sign of a number.
Definition: Mathematics.h:58
GLsizei samples
Definition: gl2ext.h:707
#define M_PI
The value of pi.
Definition: Mathematics.h:37
static void create(int samples, float n1, float n2, float scale, float **roundedCubeCoordinates, float **roundedCubeNormalVectors, int *numberOfVertices, int *numberOfCoordinates, int *numberOfNormals)
Function that generates vertices and normal vectors of rounded cube.
Matrix scale
Definition: RotoZoom.cpp:64
float * roundedCubeNormalVectors
Definition: Native.cpp:94
float * roundedCubeCoordinates
Definition: Native.cpp:91
#define LOGE(...)
Definition: AstcTextures.h:30
void normalize(void)
Normalize 3D floating point vector.
Definition: VectorTypes.h:91