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) 2014-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 "Common.h"
22 #include "SuperEllipsoidModel.h"
23 
24 #include <cstdlib>
25 
26 namespace MaliSDK
27 {
29  float n1,
30  float n2,
31  float scale,
32  float** roundedCubeCoordinates,
34  int* numberOfVertices,
35  int* numberOfCoordinates,
36  int* numberOfNormals)
37  {
38  /* Check if samples is greater than 0. */
39  ASSERT(samples > 0, "Number of samples has to be greater than 0.");
40 
41  ASSERT(roundedCubeCoordinates != NULL, "Cannot use null pointer while calculating rounded cube coordinates.");
42  ASSERT(roundedCubeNormalVectors != NULL, "Cannot use null pointer while calculating rounded cube normals.");
43  ASSERT(numberOfVertices != NULL, "Invalid parameter: cannot use NULL pointer to store number of vertices.");
44  ASSERT(numberOfCoordinates != NULL, "Invalid parameter: cannot use NULL pointer to store number of coordinates.");
45  ASSERT(numberOfNormals != NULL, "Invalid parameter: cannot use NULL pointer to store number of normals.");
46 
47  /* Computation of the numberOfCoordinates results from the algorithm used in this function.
48  * In the first "for" loop we can see that this loop iterates samples / 2 times. Then in the second loop
49  * we can see that this loop will go samples times.
50  * In total, there are samples / 2 * samples iterations.
51  * Each iteration produces 6 vertices and each vertex has 4 coordinates. */
52  *numberOfVertices = samples / 2 * samples * 6;
53  *numberOfCoordinates = *numberOfVertices * numberOfPointCoordinates;
54 
55  /* The number of normals is the same except that each normal only has 3 coordinates. */
56  *numberOfNormals = samples / 2 * samples * 6 * numberOfPointCoordinates;
57 
58  /* Allocate memory to store rounded cube's coordinates. */
59  *roundedCubeCoordinates = new float[*numberOfCoordinates];
60  /* Allocate memory to store rounded cube's normal vectors. */
61  *roundedCubeNormalVectors = new float[*numberOfNormals];
62 
63  /* Make sure allocation succeeded. */
64  ASSERT(roundedCubeCoordinates != NULL, "Pointer roundedCubeCoordinates is NULL.");
65  ASSERT(roundedCubeNormalVectors != NULL, "Pointer roundedCubeNormalVectors is NULL.");
66 
67  /* Values to store temporarily vertices and normal vectors. */
68  Vec3f vertex, normalVector;
69 
70  /* Value vertexIndex determines the beginning of array where vertices should be saved. */
71  int vertexIndex = 0;
72 
73  /* Value normalVectorIndex determines the beginning of array where normal vectors should be saved. */
74  int normalVectorIndex = 0;
75 
76  /* These values will change xzAngle and xyAngle. */
77  float xzAngleDelta = 2.0f * M_PI / samples;
78  float xyAngleDelta = 2.0f * M_PI / samples;
79 
80  /* Angle used to compute vertices and normal vectors. */
81  float xyAngle = -M_PI / 2.0f;
82 
83  /* This loop goes samples / 2 times because in each second loop we create 2 triangles. */
84  for (int j = 0; j < samples / 2; j++)
85  {
86  /* Angle used to compute vertices and normal vectors. */
87  float xzAngle = -M_PI;
88 
89  for (int i = 0; i < samples; i++)
90  {
91  /* Triangle #1 */
92  /* Calculate first vertex and normal vector. */
93  vertex = sample (xyAngle, xzAngle, n1, n2, scale);
94  normalVector = calculateNormal(xyAngle, xzAngle, n1, n2, scale);
95 
96  /* Put vertex and normal vector coordinates into array. */
98  normalVector,
99  vertexIndex,
100  normalVectorIndex,
101  *roundedCubeCoordinates,
102  *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. */
110  normalVector,
111  vertexIndex,
112  normalVectorIndex,
113  *roundedCubeCoordinates,
114  *roundedCubeNormalVectors);
115 
116  /* Calculate third vertex and normal vector. */
117  vertex = sample (xyAngle + xyAngleDelta, xzAngle + xzAngleDelta, n1, n2, scale);
118  normalVector = calculateNormal(xyAngle + xyAngleDelta, xzAngle + xzAngleDelta, n1, n2, scale);
119 
120  /* Put vertex and normal vector coordinates into array. */
122  normalVector,
123  vertexIndex,
124  normalVectorIndex,
125  *roundedCubeCoordinates,
126  *roundedCubeNormalVectors);
127 
128  /* Triangle #2 */
129  /* Calculate first vertex and normal vector. */
130  vertex = sample (xyAngle, xzAngle, n1, n2, scale);
131  normalVector = calculateNormal(xyAngle, xzAngle, n1, n2, scale);
132 
133  /* Put vertex and normal vector coordinates into array. */
135  normalVector,
136  vertexIndex,
137  normalVectorIndex,
138  *roundedCubeCoordinates,
139  *roundedCubeNormalVectors);
140 
141  /* Calculate second vertex and normal vector. */
142  vertex = sample (xyAngle + xyAngleDelta,
143  xzAngle + xzAngleDelta,
144  n1,
145  n2,
146  scale);
147  normalVector = calculateNormal(xyAngle + xyAngleDelta,
148  xzAngle + xzAngleDelta,
149  n1,
150  n2,
151  scale);
152 
153  /* Put vertex and normal vector coordinates into array. */
155  normalVector,
156  vertexIndex,
157  normalVectorIndex,
158  *roundedCubeCoordinates,
159  *roundedCubeNormalVectors);
160 
161  /* Calculate third vertex and normal vector. */
162  vertex = sample (xyAngle, xzAngle + xzAngleDelta, n1, n2, scale);
163  normalVector = calculateNormal(xyAngle, xzAngle + xzAngleDelta, n1, n2, scale);
164 
165  /* Put vertex and normal vector coordinates into array. */
167  normalVector,
168  vertexIndex,
169  normalVectorIndex,
170  *roundedCubeCoordinates,
171  *roundedCubeNormalVectors);
172 
173  /* Change xzAngle value. */
174  xzAngle += xzAngleDelta;
175  }
176 
177  /* Change xyAngle value. */
178  xyAngle += xyAngleDelta;
179  }
180  }
181 
182  Vec3f SuperEllipsoidModel::calculateNormal(float xyAngle,
183  float xzAngle,
184  float n1,
185  float n2,
186  float scale)
187  {
188  /* Pre-calculate sine and cosine values for both angles. */
189  float cosPhi = cosf(xyAngle);
190  float cosBeta = cosf(xzAngle);
191  float sinPhi = sinf(xyAngle);
192  float sinBeta = sinf(xzAngle);
193 
194  /* The equations for x, y and z coordinates are:
195  * x = 1 / rx * cos^(2 - n1)(xyAngle) * cos^(2 - n2)(xzAngle)
196  * y = 1 / ry * sin^(2 - n1)(xyAngle)
197  * z = 1 / rz * cos^(2 - n1)(xyAngle) * sin^(2 - n2)(xzAngle)
198  *
199  * where:
200  * -M_PI/2 <= xyAngle <= M_PI/2
201  * -M_PI <= xzAngle <= M_PI
202  * 0 < n1, n2 < infinity
203  *
204  * As for two-dimensional case rx, ry, and rz are scale factors for each axis (axis intercept). */
205 
206  /* Normal vector to be returned. */
207  Vec3f normal;
208 
209  normal.x = signum(cosPhi) * powf(fabs(cosPhi), 2 - n1) * signum(cosBeta) * powf(fabs(cosBeta), 2 - n2) / scale;
210  normal.y = signum(sinPhi) * powf(fabs(sinPhi), 2 - n1) / scale;
211  normal.z = signum(cosPhi) * powf(fabs(cosPhi), 2 - n1) * signum(sinBeta) * powf(fabs(sinBeta), 2 - n2) / scale;
212 
213  /* Normalize vector. */
214  normal.normalize();
215 
216  return normal;
217  }
218 
219  Vec3f SuperEllipsoidModel::sample(float xyAngle,
220  float xzAngle,
221  float n1,
222  float n2,
223  float scale)
224  {
225  /* Pre-calculate sine and cosine values for both angles. */
226  const float xyAngleCos = cosf(xyAngle);
227  const float xzAngleCos = cosf(xzAngle);
228  const float xyAngleSin = sinf(xyAngle);
229  const float xzAngleSin = sinf(xzAngle);
230 
231  /* The equations for x, y and z coordinates are given below:
232  *
233  * x = rx * cos^n1(xyAngle) * cos^n2(xzAngle)
234  * y = ry * sin^n1(xyAngle)
235  * z = rz * cos^n1(xyAngle) * sin^n2(xzAngle)
236  *
237  * where:
238  *
239  * -M_PI/2 <= xyAngle <= M_PI/2
240  * -M_PI <= xzAngle <= M_PI
241  * 0 < n1, n2 < infinity
242  *
243  * As for two-dimensional case rx, ry, and rz are scale factors for each axis (axis intercept). */
244 
245  /* Vertex to be returned. */
246  Vec3f vertex;
247 
248  vertex.x = scale * signum(xyAngleCos) * powf(fabs(xyAngleCos), n1) * signum(xzAngleCos) * powf(fabs(xzAngleCos), n2);
249  vertex.y = scale * signum(xyAngleSin) * powf(fabs(xyAngleSin), n1);
250  vertex.z = scale * signum(xyAngleCos) * powf(fabs(xyAngleCos), n1) * signum(xzAngleSin) * powf(fabs(xzAngleSin), n2);
251 
252  return vertex;
253  }
254 
256  const Vec3f& normalVector,
257  int& vertexIndex,
258  int& normalVectorIndex,
259  float* roundedCubeCoordinates,
260  float* roundedCubeNormalVectors)
261  {
262  /* Save vertex and increment counter/index. */
263  roundedCubeCoordinates[vertexIndex++] = vertex.x;
264  roundedCubeCoordinates[vertexIndex++] = vertex.y;
265  roundedCubeCoordinates[vertexIndex++] = vertex.z;
266  roundedCubeCoordinates[vertexIndex++] = 1.0f;
267 
268  /* Save normal vector and increment counter/index. */
269  roundedCubeNormalVectors[normalVectorIndex++] = normalVector.x;
270  roundedCubeNormalVectors[normalVectorIndex++] = normalVector.y;
271  roundedCubeNormalVectors[normalVectorIndex++] = normalVector.z;
272  roundedCubeNormalVectors[normalVectorIndex++] = 1.0f;
273  }
274 }
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.
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
static const int numberOfPointCoordinates
Number of coordinates for a point in 3D space.
float * roundedCubeNormalVectors
Definition: Native.cpp:94
float * roundedCubeCoordinates
Definition: Native.cpp:91
#define ASSERT(x, s)
Definition: common.h:45