OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SphereModel.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 "SphereModel.h"
23 
24 #include <cstdlib>
25 #include <cmath>
26 #include <cassert>
27 
28 namespace MaliSDK
29 {
30  void SphereModel::getPointRepresentation(const float radius, const int numberOfSamples, int* numberOfCoordinates, float** coordinates)
31  {
32  /*
33  * Sphere vertices are created according to rule:
34  * Create a circle at north pole of the sphere, consisting of numberOfSample points.
35  * Create following circles, ending at south pole of sphere. The sphere now consists of numberOfSample circles.
36  * Theta value (indicating longitude) runs from 0 to 2*M_PI.
37  * Radius value (indicating latitude) runs from -radius to radius.
38  */
39 
40  /* Check if parameters have compatible values. */
41  if (radius <= 0.0f)
42  {
43  LOGE("radius value has to be greater than zero.");
44 
45  return;
46  }
47 
48  if (numberOfSamples <= 0)
49  {
50  LOGE("numberOfSamples value has to be greater than zero.");
51 
52  return;
53  }
54  if (coordinates == NULL)
55  {
56  LOGE("Cannot use null pointer while calculating coordinates.");
57 
58  return;
59  }
60 
61  /* Maximum value of an error (used to compare float values). */
62  const float epsilon = 0.001f;
63  /* Index of an array we will put new point coordinates at. */
64  int indexOfSphereArray = 0;
65  /* Maximum longitude. */
66  float maxTheta = (2.0f * M_PI);
67  /* Value of longitude step. */
68  float thetaStep = maxTheta / float(numberOfSamples);
69  /* Value of latitude step. */
70  float radiusStep = (2 * radius) / float(numberOfSamples-1);
71  /* Index of longitude loop. */
72  int thetaIndex = 0;
73  /* Index of latitude loop. */
74  int radiusIndex = 0;
75  /* Number of coordinates which a sphere consists of. Each point (which a sphere consists of) consists of 3 coordinates: x, y, z. */
76  const int numberOfSphereCoordinates = numberOfSamples * numberOfSamples * 3;
77 
78  /* Allocate memory for result array. */
79  *coordinates = (float*) malloc (numberOfSphereCoordinates * sizeof(float));
80 
81  if (*coordinates == NULL)
82  {
83  LOGE("Could not allocate memory for result array.");
84 
85  return;
86  }
87 
88  /* Loop through circles from north to south. */
89  for (float r = -radius;
90  r < radius + epsilon;
91  r = -radius + radiusIndex * radiusStep)
92  {
93  thetaIndex = 0;
94 
95  /* Protect against rounding errors.. */
96  if (r > radius)
97  {
98  r = radius;
99  }
100 
101  /* Loop through all points of the circle. */
102  for (float theta = 0.0f;
103  theta < maxTheta;
104  theta = thetaIndex * thetaStep)
105  {
106  /* Compute x, y and z coordinates for the considered point. */
107  float x = sqrt((radius * radius) - (r * r)) * cosf(theta);
108  float y = sqrt((radius * radius) - (r * r)) * sinf(theta);
109  float z = r;
110 
111  (*coordinates)[indexOfSphereArray] = x;
112  indexOfSphereArray++;
113 
114  (*coordinates)[indexOfSphereArray] = y;
115  indexOfSphereArray++;
116 
117  (*coordinates)[indexOfSphereArray] = z;
118  indexOfSphereArray++;
119 
120  thetaIndex ++;
121  }
122 
123  radiusIndex ++;
124  }
125 
126  if (numberOfCoordinates != NULL)
127  {
128  *numberOfCoordinates = numberOfSphereCoordinates;
129  }
130  }
131 
132  void SphereModel::getTriangleRepresentation(const float radius,
133  const int numberOfSamples,
134  int* numberOfCoordinates,
135  int* numberOfPoints,
136  float** coordinates)
137  {
138  /* Check if parameters have compatible values. */
139  if (radius <= 0.0f)
140  {
141  LOGE("radius value has to be greater than zero.");
142 
143  return;
144  }
145 
146  if (numberOfSamples <= 0)
147  {
148  LOGE("numberOfSamples value has to be greater than zero.");
149 
150  return;
151  }
152  if (coordinates == NULL)
153  {
154  LOGE("Cannot use null pointer while calculating coordinates.");
155 
156  return;
157  }
158  /* Array holding coordinates of points which a sphere consists of. */
159  float* pointCoordinates = NULL;
160  /* Current index used for accessing coordinates array. */
161  int sphereTriangleCoordinateIndex = 0;
162  /* Index of current loop iteration. */
163  int iterationIndex = 1;
164  /* There are 18 coordinates created in one loop: 3 coordinates * 3 triangle vertices * 2 triangles. */
165  int numberOfCoordinatesCreatedInOneLoop = 18;
166  /* Number of coordinates of all triangles which a sphere consists of.
167  * (numberOfSamples - 1) - for each circle (excluding last one)
168  * numberOfSamples - for each point on a single circle
169  * 2 - number of triangles that start at given point
170  * 3 - number of points that make up a triangle
171  * 3 - coordinates per each point.
172  */
173  const int numberOfSphereTrianglePoints = (numberOfSamples - 1) * numberOfSamples * 2 * 3;
174  const int numberOfSphereTriangleCoordinates = numberOfSphereTrianglePoints * 3;
175 
176  /* Compute coordinates of points which make up a sphere. */
177  getPointRepresentation(radius, numberOfSamples, NULL, &pointCoordinates);
178 
179  if (pointCoordinates == NULL)
180  {
181  LOGE("Could not get coordinates of points which make up a sphere.");
182  return;
183  }
184 
185  *coordinates = (float*) malloc (numberOfSphereTriangleCoordinates * sizeof(float));
186 
187  if (*coordinates == NULL)
188  {
189  LOGE("Could not allocate memory for result array.");
190  return;
191  }
192 
193  /* Each point has 3 coordinates: x, y, z. */
194  for (int pointIndex = 0;
195  pointIndex < (numberOfSphereTriangleCoordinates / numberOfCoordinatesCreatedInOneLoop) * 3;
196  pointIndex += 3)
197  {
198  /* First triangle. ==> */
199 
200  /* Building of a triangle is started from point at index described by pointIndex.
201  * Values of x, y and z coordinates are written one after another in pointCoordinates array starting at index of point value.
202  */
203  /* Coordinate x. */
204  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex];
205  sphereTriangleCoordinateIndex++;
206  /* Coordinate y. */
207  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 1];
208  sphereTriangleCoordinateIndex++;
209  /* Coordinate z. */
210  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 2];
211  sphereTriangleCoordinateIndex++;
212 
213  /* Check if this is the last point of circle. */
214  if ((iterationIndex % numberOfSamples) == 0 )
215  {
216  /* Second point of triangle.
217  * If this is the last point lying on a circle,
218  * second point that makes up a triangle is the point with coordinates taken from the first point lying on current circle.
219  * According to example above: the second point for first triangle starting at point D1 (last point on a current circle) is point A1.
220  * Index (to receive x coordinate): [point - 3 * (numberOfSamples)] stands for x coordinate of point D0 (corresponding point from previous circle),
221  * [+ 3] stands for next point (first point of current circle - A1).
222  */
223  /* Coordinate x. */
224  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex - 3 * (numberOfSamples) + 3];
225  sphereTriangleCoordinateIndex++;
226  /* Coordinate y. */
227  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex - 3 * (numberOfSamples) + 3 + 1];
228  sphereTriangleCoordinateIndex++;
229  /* Coordinate z. */
230  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex - 3 * (numberOfSamples) + 3 + 2];
231  sphereTriangleCoordinateIndex++;
232 
233  /* Third point of triangle.
234  * If this is the last point lying on a circle,
235  * third point that makes up a triangle is the point with coordinates taken from the first point lying on next circle.
236  * According to example above: the third point for first triangle starting at point D1 (last point on a current circle) is point A2.
237  * Index (to receive x coordinate): [point + 3] stands for x coordinate of point A2 (first point on next circle).
238  */
239  /* Coordinate x. */
240  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3];
241  sphereTriangleCoordinateIndex++;
242  /* Coordinate y. */
243  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 + 1];
244  sphereTriangleCoordinateIndex++;
245  /* Coordinate z. */
246  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 + 2];
247  sphereTriangleCoordinateIndex++;
248  }
249  else
250  {
251  /* Second point of triangle.
252  * If this is not the last point lying on a circle,
253  * second point that makes up a triangle is the point with coordinates taken from the next point lying on current circle.
254  * According to example above: the second point for first triangle starting at (for example) point A1 (not last point on a circle) is point B1.
255  * Index (to receive x coordinate): [point + 3] stands for x coordinate of point B1 (next point in array).
256  */
257  /* Coordinate x. */
258  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3];
259  sphereTriangleCoordinateIndex++;
260  /* Coordinate y. */
261  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 + 1];
262  sphereTriangleCoordinateIndex++;
263  /* Coordinate z. */
264  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 + 2];
265  sphereTriangleCoordinateIndex++;
266 
267  /* Third point of triangle.
268  * If this is not the last point lying on a circle,
269  * third point that makes up a triangle is the point with coordinates taken from the next from corresponding point lying on next circle.
270  * According to example above: the third point for first triangle starting at (for example) point A1 (not last point on a circle) is point B2.
271  * Index (to receive x coordinate): [point + numberOfSamples * 3] stands for x coordinate of point A2 (corresponding point lying on next circle),
272  * [+ 3] stands for nex point on that circle - B2.
273  */
274  /* Coordinate x. */
275  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + numberOfSamples * 3 + 3];
276  sphereTriangleCoordinateIndex++;
277  /* Coordinate y. */
278  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + numberOfSamples * 3 + 3 + 1];
279  sphereTriangleCoordinateIndex++;
280  /* Coordinate z. */
281  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + numberOfSamples * 3 + 3 + 2];
282  sphereTriangleCoordinateIndex++;
283  }
284  /* <== First triangle. */
285 
286  /* Second triangle. ==> */
287 
288  /* Building of a triangle is started from point at index described by pointIndex.
289  * Values of x, y and z coordinates are written one after another in pointCoordinates array starting at index of point value.
290  */
291  /* Coordinate x. */
292  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex];
293  sphereTriangleCoordinateIndex++;
294  /* Coordinate y. */
295  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 1];
296  sphereTriangleCoordinateIndex++;
297  /* Coordinate z. */
298  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 2];
299  sphereTriangleCoordinateIndex++;
300 
301  /* Check if this is a last point of circle. */
302  if ((iterationIndex % numberOfSamples) == 0 )
303  { /* Second point of triangle.
304  * If this is the last point lying on a circle,
305  * second point that makes up a triangle is the point with coordinates taken from the first point lying on next circle.
306  * According to example above: the second point for first triangle starting at point D1 (last point on a current circle) is point A2.
307  * Index (to receive x coordinate): [point + 3] stands for x coordinate of point A2 (first point on next circle).
308  */
309  /* Coordinate x. */
310  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3];
311  sphereTriangleCoordinateIndex++;
312  /* Coordinate y. */
313  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 + 1];
314  sphereTriangleCoordinateIndex++;
315  /* Coordinate z. */
316  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 + 2];
317  sphereTriangleCoordinateIndex++;
318  }
319  else
320  {
321  /* Second point of triangle.
322  * If this is not the last point lying on a circle,
323  * second point that makes up a triangle is the point with coordinates taken from the next from corresponding point lying on next circle.
324  * According to example above: the second point for first triangle starting at (for example) point A1 (not last point on a circle) is point B2.
325  * Index (to receive x coordinate): [point + numberOfSamples * 3] stands for x coordinate of point A2 (corresponding point lying on next circle),
326  * [+ 3] stands for nex point on that circle - B2.
327  */
328  /* Coordinate x. */
329  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 * numberOfSamples + 3];
330  sphereTriangleCoordinateIndex++;
331  /* Coordinate y. */
332  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 * numberOfSamples + 3 + 1];
333  sphereTriangleCoordinateIndex++;
334  /* Coordinate z. */
335  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 * numberOfSamples + 3 + 2];
336  sphereTriangleCoordinateIndex++;
337  }
338 
339  /* Third point of triangle that makes up a triangle is the point with coordinates taken from the corresponding point lying on next circle.
340  * According to example above: the third point for second triangle starting at point A1 (for example) is point A2.
341  * Index (to receive x coordinate): [point + 3 * (numberOfSamples)] stands for x coordinate of point A2 (corresponding point from next circle).
342  */
343  /* Coordinate x. */
344  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 * numberOfSamples];
345  sphereTriangleCoordinateIndex++;
346  /* Coordinate y. */
347  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 *numberOfSamples + 1];
348  sphereTriangleCoordinateIndex++;
349  /* Coordinate z. */
350  (*coordinates)[sphereTriangleCoordinateIndex] = pointCoordinates[pointIndex + 3 * numberOfSamples + 2];
351  sphereTriangleCoordinateIndex++;
352 
353  /* <== Second triangle. */
354 
355  iterationIndex++;
356  }
357 
358  if (numberOfCoordinates != NULL)
359  {
360  *numberOfCoordinates = numberOfSphereTriangleCoordinates;
361  }
362  if (numberOfPoints != NULL)
363  {
364  *numberOfPoints = numberOfSphereTrianglePoints;
365  }
366  /* Deallocate memory. */
367  free(pointCoordinates);
368  pointCoordinates = NULL;
369  }
370 
371 
372 
373 }
int numberOfSphereTrianglePoints
Definition: Native.cpp:77
static void getTriangleRepresentation(const float radius, const int numberOfSamples, int *numberOfCoordinates, float **coordinates)
Create triangular representation of a sphere.
GLboolean r
Definition: gl2ext.h:306
static void getPointRepresentation(const float radius, const int numberOfSamples, int *numberOfCoordinates, float **coordinates)
Compute coordinates of points which make up a sphere.
Definition: SphereModel.cpp:31
GLfloat GLfloat f
Definition: gl2ext.h:2707
int numberOfSphereTriangleCoordinates
Definition: Native.cpp:75
#define M_PI
The value of pi.
Definition: Mathematics.h:37
GLint GLint GLint GLint GLint x
Definition: gl2ext.h:574
int numberOfSamples
Definition: AntiAlias.cpp:66
#define LOGE(...)
Definition: AstcTextures.h:30
precision highp float
Definition: hiz_cull.cs:37
GLint y
Definition: gl2ext.h:179