OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Native.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 
51 #include <jni.h>
52 #include <android/log.h>
53 
54 #include <cstdlib>
55 #include <cmath>
56 #include <iostream>
57 #include <sstream>
58 #include <string>
59 
60 #include "Common.h"
61 #include "CubeModel.h"
62 #include "Matrix.h"
63 #include "Native.h"
64 #include "PlaneModel.h"
65 #include "Shader.h"
66 #include "SuperEllipsoidModel.h"
67 #include "Text.h"
68 #include "Texture.h"
69 #include "Timer.h"
70 
71 using namespace std;
72 using namespace MaliSDK;
73 
74 /* Asset directories and filenames */
75 const string resourceDirectory = "/data/data/com.arm.malideveloper.openglessdk.occlusionQueries/files/";
76 
77 /* Window properties. */
78 int windowWidth = 0;
79 int windowHeight = 0;
80 
81 /* Timer */
83 
84 /* Timer variable to calculate FPS. */
86 
87 /* Id of OpenGL program we use for rendering. */
89 
90 /* Pointer to an array that stores vertices of rounded cube. */
91 float* roundedCubeCoordinates = NULL;
92 
93 /* Pointer to an array that stores normal vectors of rounded cube. */
95 
96 /* This value represents number of rounded cube vertices. */
98 
99 /* Represents a number of rounded cube's coordinates. */
101 
102 /* Represents a number of rounded cube's normal vectors. */
104 
105 /* Array that stores random position of each cube. */
107 
108 /* Minimum distance between cubes. */
109 const float minimumDistance = ROUNDED_CUBE_SCALE_FACTOR * 2.0f + 0.1f;
110 
111 /* Array of queries for each of numberOfCubes cubes. */
113 
114 /* Flag that informs us what mode is turned on (if it's occlusion query mode or not). */
115 bool occlusionQueriesOn = false;
116 
117 /* This is the angle that is used to rotate camera around Y axis. */
118 float angleY = 0.0f;
119 
120 /* This value informs us how far camera is located from point (0, 0, 0). */
121 const float cameraRadius = 22.0f;
122 
123 /* This value is used to translate camera along the Y axis. */
124 const float yCameraTranslation = 1.25f;
125 
126 /* Matrices that will be used to setup perspective view. */
138 
139 /* Variables that will be used to store locations of the attributes and uniforms.*/
144 
145 /* Array to store sorted positions of the cubes. Each cube has 2 coordinates. */
147 
148 /* Scaling factor to scale up the plane. */
149 const float planeScalingFactor = 40.0f;
150 
151 /* Determines how many times an area (where the cubes are located) should be smaller than original plane. */
152 const float planeDividend = 3.0f;
153 
154 const float cubeColor[] = {0.0f, 0.75f, 0.0f, 1.0f};
155 const float planeColor[] = {1.0f, 0.8f, 0.0f, 1.0f};
156 const float planeLocation[] = {0.0f, 0.0f, 0.0f};
157 
158 /* Vertex Array Objects for plane, normal cube and rounded cube. */
162 
163 /* This buffer object holds the plane's vertices. */
165 
166 /* This buffer object holds the plan's normal vectors. */
168 
169 /* This buffer object holds the normal cubes' vertices. */
171 
172 /* This buffer object holds the rounded cubes' vertices. */
174 
175 /* This buffer object holds the rounded cubes' normal vectors. */
177 
178 /* Pointer to an array that stores the cubes' vertices. */
179 float* normalCubeVertices = NULL;
180 
181 /* Determines the size of the dynamically allocated normalCubeVertices array. */
184 
185 /* Pointer to an array that stores the plane's vertices. */
186 float* planeVertices = NULL;
187 
188 /* Number of plane vertices and vertex coordinates that make up a plane shape. */
191 
192 /* Pointer to an array that stores the plane's normal vectors. */
193 float* planeNormalVectors = NULL;
194 
195 /* Determines the size of the dynamically allocated plane Normals array. */
197 
198 /* Flag indicating that the rendering mode has changed (occlusion query OFF => ON) */
199 bool modeChanged = false;
200 
201 /* Counter for the number of rounded cubes drawn each frame. */
203 
204 /* Text object to indicate whether occlusion queries are turned on or not. */
206 
215 inline float distanceBetweenPoints(const Vec2f& point1, const Vec2f& point2)
216 {
217  return sqrtf((point2.x - point1.x) * (point2.x - point1.x) + (point2.y - point1.y) * (point2.y - point1.y));
218 }
219 
229 inline bool inNeighbourhood(const Vec2f& point, float minDistance, int j)
230 {
231  for (int i = 0; i < j; i++)
232  {
233  if (distanceBetweenPoints(point, randomCubesPositions[i]) < minDistance)
234  {
235  return true;
236  }
237  }
238  return false;
239 }
240 
246 inline float uniformRandomNumber()
247 {
248  return rand() / float(RAND_MAX);
249 }
250 
260 void generateCubesLocations(float planeWidth, float planeHeight, float minDistance)
261 {
262  /*
263  * xRange and zRange are both minimum (-xRange, -zRange) and maximum (+xRange, +zRange) values respectively for X axis and Z axes.
264  * These two values ensure that cubes will not partially land outside the plane. To prevent such a situation we have to
265  * restrict the bounds of our plane. We also want camera to fly around the cubes and
266  * have the plane still visible (we don't want to see the edges of the plane - "end of the world").
267  * That's why we divide planeWidth and planeHeight by planeDividend - this will give us a smaller plane
268  * that a part of the bigger, original plane.
269  */
270  float xRange = planeWidth / planeDividend;
271  float zRange = planeHeight / planeDividend;
272 
273  /* This variable is used to prevent the situation that this function will iterate for
274  * infinite number of times to find locations for a cube - we can't locate infinite number of cubes
275  * that don't overlap on a finite plane. */
276  float loopsCounter = 0;
277 
278  /* We generate the first point which can be randomly chosen from points on the plane
279  * and we save it to the array.
280  * Generation of this point is based on equation for generating random numbers
281  * in given interval. If we want to get a random number in an interval [a, b]
282  * we can use equation: rand()%(b - a) + a, where rand() generates a number
283  * between 0 and 1. */
284  Vec2f firstRandomPoint = {(xRange + xRange) * uniformRandomNumber() - xRange,
285  (zRange + zRange) * uniformRandomNumber() - zRange};
286 
287  randomCubesPositions[0] = firstRandomPoint;
288 
289  for (int i = 1; i < NUMBER_OF_CUBES; i++)
290  {
291  /* Check if the loop has not iterated too many times. */
292  if (loopsCounter > NUMBER_OF_CUBES * NUMBER_OF_CUBES)
293  {
294  return;
295  }
296 
297  /* We choose another random point on a plane. */
298  Vec2f randomPoint = {(xRange + xRange) * uniformRandomNumber() - xRange,
299  (zRange + zRange) * uniformRandomNumber() - zRange};
300 
301  /* And check if it's a proper distance from any other point that is already stored in the array. */
302  if (!inNeighbourhood(randomPoint, minDistance, i))
303  {
304  /* If it is, we can save it to the array of random cubes positions. */
305  randomCubesPositions[i] = randomPoint;
306  }
307  else
308  {
309  /* Otherwise, decrement the i counter and try again. */
310  i -= 1;
311  }
312 
313  /* Increase loop counter. */
314  loopsCounter++;
315  }
316 }
317 
325 void sortCubePositions(float* arrayToSort)
326 {
327  /* The upper limit position of sorted elements. We subtract 4 because we will refer to the 4 array's
328  * cells ahead and we don't want to go out of bounds of the array. */
329  int max = (NUMBER_OF_CUBES * 2) - 4;
330 
331  bool swapped = true;
332 
333  while(swapped)
334  {
335  swapped = false;
336 
337  for (int i = 0; i <= max; i += 2)
338  {
339  /* Temporarily store location points. */
340  Vec2f firstCubeLocation, secondCubeLocation;
341 
342  firstCubeLocation.x = arrayToSort[i];
343  firstCubeLocation.y = arrayToSort[i + 1];
344 
345  secondCubeLocation.x = arrayToSort[i + 2];
346  secondCubeLocation.y = arrayToSort[i + 3];
347 
348  Vec3f first_cube_location = {firstCubeLocation.x, 1, firstCubeLocation.y};
349  Vec3f second_cube_location = {secondCubeLocation.x, 1, secondCubeLocation.y};
350  Vec3f transformed_first_cube_location = Matrix::vertexTransform(&first_cube_location, &rotatedViewMatrix);
351  Vec3f transformed_second_cube_location = Matrix::vertexTransform(&second_cube_location, &rotatedViewMatrix);
352 
353  if (transformed_first_cube_location.z < transformed_second_cube_location.z)
354  {
355  /* Swap coordinates' positions. */
356  arrayToSort[i] = secondCubeLocation.x;
357  arrayToSort[i + 1] = secondCubeLocation.y;
358 
359  arrayToSort[i + 2] = firstCubeLocation.x;
360  arrayToSort[i + 3] = firstCubeLocation.y;
361 
362  swapped = true;
363  }
364  } /* for (int i = 0; i <= max; i += 2) */
365  }/* while(swapped) */
366 }
367 
375 {
376  for (int i = 0; i < NUMBER_OF_CUBES; i++)
377  {
380  }
381 }
382 
388 inline void sendCubeLocationVectorToUniform(int whichCube)
389 {
390  /* Array to be sent to the vertex shader.*/
391  float tempArray[3];
392 
393  /* We send roundedCubeScaleFactor to translate cubes a little bit up so they won't intersect with the plane.*/
394  tempArray[0] = sortedCubesPositions[2 * whichCube];
395  tempArray[1] = ROUNDED_CUBE_SCALE_FACTOR;
396  tempArray[2] = sortedCubesPositions[2 * whichCube + 1];
397 
398  cubeModelMatrix = Matrix::createTranslation(tempArray[0],
399  tempArray[1],
400  tempArray[2]);
402  cubeWorldInverseMatrix = Matrix::matrixInvert(&cubeMvpMatrix);
403  cubeNormalMatrix = Matrix::matrixInvert (&cubeModelMatrix);
404 
405  Matrix::matrixTranspose(&cubeNormalMatrix);
406 
407  /* Send array to the shader. */
408  GL_CHECK(glUniformMatrix4fv(normalMatrixUniformLocation,
409  1,
410  GL_FALSE,
412  GL_CHECK(glUniformMatrix4fv(worldInverseMatrixUniformLocation,
413  1,
414  GL_FALSE,
416  GL_CHECK(glUniformMatrix4fv(mvpMatrixUniformLocation,
417  1,
418  GL_FALSE,
420 }
421 
428 void setupGraphics(int width, int height)
429 {
430  /* This line ensures that everytime we run the new instance of the program, rand() will generate different numbers. */
431  srand((unsigned int)time(NULL));
432 
433  /* Store window resolution. */
435  windowWidth = width;
436 
437  /* Initialize scaling matrix. */
438  Matrix scaling = Matrix::createScaling(planeScalingFactor,
441 
442  /* Initialize vectors that will be passed to matrixCameralookAt function. */
443  const Vec3f eyeVector = {0.0f, yCameraTranslation, cameraRadius};
444  const Vec3f lookAtPoint = {0.0f, 0.0f, 0.0f};
445  const Vec3f upVector = {0.0f, 1.0f, 0.0f};
446 
447  /* Calculate matrices. */
449  float(windowWidth)/float(windowHeight),
450  0.1f,
451  50.0f);
452  viewMatrix = Matrix::matrixCameraLookAt(eyeVector,
453  lookAtPoint,
454  upVector);
455  planeModelMatrix = Matrix::createTranslation(planeLocation[0],
456  planeLocation[1],
457  planeLocation[2]);
458  planeNormalMatrix = Matrix::matrixInvert(&planeModelMatrix);
459 
460  Matrix::matrixTranspose(&planeNormalMatrix);
461 
462  /* Set up the text object. */
464  text->addString(0, 0, "Occlusion query OFF", 255, 0, 0, 255);
465 
466  /* Set clear color. */
467  GL_CHECK(glClearColor(0.3f, 0.6f, 0.70f, 1.0f));
468 
469  /* Enable depth test and set depth function to GL_LEQUAL. */
470  GL_CHECK(glEnable (GL_DEPTH_TEST));
471  GL_CHECK(glDepthFunc(GL_LEQUAL));
472 
473  /* Set shaders up. */
475  string fragmentShaderPath = resourceDirectory + "fragment.frag";
477  string vertexShaderPath = resourceDirectory + "vertex.vert";
478 
479  Shader::processShader(&vertexShaderId,
480  vertexShaderPath.c_str(),
481  GL_VERTEX_SHADER);
482  Shader::processShader(&fragmentShaderId,
483  fragmentShaderPath.c_str(),
484  GL_FRAGMENT_SHADER);
485 
486  /* [Create program object] */
487  programId = GL_CHECK(glCreateProgram());
488  /* [Create program object] */
489 
490  /* [Attach vertex and fragment shader objects to rendering program] */
491  GL_CHECK(glAttachShader(programId, vertexShaderId));
492  GL_CHECK(glAttachShader(programId, fragmentShaderId));
493  /* [Attach vertex and fragment shader objects to rendering program] */
494 
495  /* [Link the program object] */
496  GL_CHECK(glLinkProgram(programId));
497  /* [Link the program object] */
498  /* [Set active program object] */
499  GL_CHECK(glUseProgram (programId));
500  /* [Set active program object] */
501 
502  /* Retrieve program uniform and attribute locations. */
503  /* [Get program attrib locations] */
504  GLuint normalAttributeLocation = GL_CHECK(glGetAttribLocation (programId, "normal"));
505  GLuint verticesAttributeLocation = GL_CHECK(glGetAttribLocation (programId, "vertex"));
506  /* [Get program attrib locations] */
507 
508  colorUniformLocation = GL_CHECK(glGetUniformLocation(programId, "color"));
509  normalMatrixUniformLocation = GL_CHECK(glGetUniformLocation(programId, "normalMatrix"));
510  worldInverseMatrixUniformLocation = GL_CHECK(glGetUniformLocation(programId, "worldInverseMatrix"));
511  mvpMatrixUniformLocation = GL_CHECK(glGetUniformLocation(programId, "mvpMatrix"));
512 
513  ASSERT(colorUniformLocation != -1, "Could not retrieve uniform location: color");
514  ASSERT(verticesAttributeLocation != -1, "Could not retrieve attribute location: vertex");
515  ASSERT(normalAttributeLocation != -1, "Could not retrieve attribute location: normal");
516  ASSERT(normalMatrixUniformLocation != -1, "Could not retrieve uniform location: normalMatrix");
517  ASSERT(worldInverseMatrixUniformLocation != -1, "Could not retrieve uniform location: worldInverseMatrix");
518  ASSERT(mvpMatrixUniformLocation != -1, "Could not retrieve uniform location: mvpMatrix");
519 
520  /* Generate super ellipsoid. */
521  SuperEllipsoidModel::create(NUMBER_OF_SAMPLES,
522  SQUARENESS_1,
523  SQUARENESS_2,
530  /* Generate triangular representation of a cube. */
531  CubeModel::getTriangleRepresentation(NORMAL_CUBE_SCALE_FACTOR,
535  /* [Generate triangular representation of a plane] */
536  PlaneModel::getTriangleRepresentation(&numberOfPlaneVertices,
538  &planeVertices);
539  /* [Generate triangular representation of a plane] */
540  /* [Get plane normals] */
541  PlaneModel::getNormals(&sizeOfPlaneNormalsArray,
543  /* [Get plane normals] */
544 
545  /* Make sure the models'coordinates were created successfully. */
546  ASSERT(roundedCubeCoordinates != NULL, "Could not create super ellipsoid's coordinates.");
547  ASSERT(roundedCubeNormalVectors != NULL, "Could not create super ellipsoid's normal vectors.");
548  ASSERT(normalCubeVertices != NULL, "Could not create triangular representation of a cube.");
549  ASSERT(planeVertices != NULL, "Could not create triangular representation of a plane.");
550  ASSERT(planeNormalVectors != NULL, "Could not create plane's normal vector.");
551 
552  /* Scale the plane up to fill the screen. */
553  PlaneModel::transform(scaling, numberOfPlaneVertexCoordinates, &planeVertices);
554 
555  /* Generate cubes' center locations. */
557 
558  /* Rewrite Vec2f randomCubesPosition array to simple array of floats. */
560 
561  /* Generate buffer objects. */
562  /* [Generate buffer objects for plane geometry] */
563  GL_CHECK(glGenBuffers(1, &planeVerticesBufferId));
564  GL_CHECK(glGenBuffers(1, &planeNormalVectorsBufferId));
565  /* [Generate buffer objects for plane geometry] */
566  GL_CHECK(glGenBuffers(1, &normalCubeBufferId));
567  GL_CHECK(glGenBuffers(1, &roundedCubeVerticesBufferId));
568  GL_CHECK(glGenBuffers(1, &roundedCubeNormalVectorsBufferId));
569 
570  /* Generate vertex array objects. */
571  /* [Generate Vertex array object for plane geometry] */
572  GL_CHECK(glGenVertexArrays(1, &planeVertexArrayObjectId));
573  /* [Generate Vertex array object for plane geometry] */
574  GL_CHECK(glGenVertexArrays(1, &normalCubeVertexArrayObjectId));
575  GL_CHECK(glGenVertexArrays(1, &roundedCubeVertexArrayObjectId));
576 
577  /* This vertex array object stores the plane's vertices and normal vectors. */
578  /* [Bind vertex array object] */
579  GL_CHECK(glBindVertexArray(planeVertexArrayObjectId));
580  /* [Bind vertex array object] */
581  {
582  /* [Copy plane coordinates to the buffer object] */
583  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER,
585  GL_CHECK(glBufferData (GL_ARRAY_BUFFER,
586  numberOfPlaneVertexCoordinates * sizeof(float),
588  GL_STATIC_DRAW));
589  /* [Copy plane coordinates to the buffer object] */
590  /* [Set vertex attrib pointer for plane coordinates] */
591  GL_CHECK(glVertexAttribPointer(verticesAttributeLocation,
592  4,
593  GL_FLOAT,
594  GL_FALSE,
595  0,
596  0));
597  /* [Set vertex attrib pointer for plane coordinates] */
598 
599  /* [Copy plane normals to the buffer object] */
600  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER,
602  GL_CHECK(glBufferData (GL_ARRAY_BUFFER,
603  sizeOfPlaneNormalsArray * sizeof(float),
605  GL_STATIC_DRAW));
606  /* [Copy plane normals to the buffer object] */
607  /* [Set vertex attrib pointer for plane normals] */
608  GL_CHECK(glVertexAttribPointer(normalAttributeLocation,
609  4,
610  GL_FLOAT,
611  GL_FALSE,
612  0,
613  0));
614  /* [Set vertex attrib pointer for plane normals] */
615 
616  /* [Enable plane vertex attrib arrays] */
617  GL_CHECK(glEnableVertexAttribArray(verticesAttributeLocation));
618  GL_CHECK(glEnableVertexAttribArray(normalAttributeLocation));
619  /* [Enable plane vertex attrib arrays] */
620  }
621 
622  /* This vertex array object stores the normal cubes' vertices. */
623  GL_CHECK(glBindVertexArray(normalCubeVertexArrayObjectId));
624  {
625  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER,
627  GL_CHECK(glBufferData (GL_ARRAY_BUFFER,
628  numberOfCubeCoordinates * sizeof(float),
630  GL_STATIC_DRAW));
631  GL_CHECK(glVertexAttribPointer(verticesAttributeLocation,
632  3,
633  GL_FLOAT,
634  GL_FALSE,
635  0,
636  0));
637 
638  GL_CHECK(glEnableVertexAttribArray(verticesAttributeLocation));
639  }
640 
641  /* This vertex array object stores rounded cube's vertices and normal vectors. */
642  GL_CHECK(glBindVertexArray(roundedCubeVertexArrayObjectId));
643  {
644  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER,
646  GL_CHECK(glBufferData (GL_ARRAY_BUFFER,
647  numberOfRoundedCubeCoordinates * sizeof(float),
649  GL_STATIC_DRAW));
650  GL_CHECK(glVertexAttribPointer(verticesAttributeLocation,
651  4,
652  GL_FLOAT,
653  GL_FALSE,
654  0,
655  0));
656 
657  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER,
659  GL_CHECK(glBufferData (GL_ARRAY_BUFFER,
660  numberOfRoundedCubeNormalVectors * sizeof(float),
662  GL_STATIC_DRAW));
663  GL_CHECK(glVertexAttribPointer(normalAttributeLocation,
664  4,
665  GL_FLOAT,
666  GL_FALSE,
667  0,
668  0));
669 
670  GL_CHECK(glEnableVertexAttribArray(verticesAttributeLocation));
671  GL_CHECK(glEnableVertexAttribArray(normalAttributeLocation));
672  }
673 
674  /* [Generate query objects] */
675  GL_CHECK(glGenQueries(NUMBER_OF_CUBES, cubeQuery));
676  /* [Generate query objects] */
677 
678  /* Define blending function that will be used when enabled. */
679  GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
680 
681  /* Release allocated memory. */
682  if (normalCubeVertices != NULL)
683  {
684  free(normalCubeVertices);
685  normalCubeVertices = NULL;
686  }
687 
688  if (planeVertices != NULL)
689  {
690  free(planeVertices);
691  planeVertices = NULL;
692  }
693 
694  if (planeNormalVectors != NULL)
695  {
696  free(planeNormalVectors);
697  planeNormalVectors = NULL;
698  }
699 
700  if(roundedCubeCoordinates != NULL)
701  {
702  delete[] roundedCubeCoordinates;
703  roundedCubeCoordinates = NULL;
704  }
705 
706  if(roundedCubeNormalVectors != NULL)
707  {
708  delete[] roundedCubeNormalVectors;
710  }
711 
712  fpsTimer.reset();
713  timer.reset();
714 }
715 
722 void draw(void)
723 {
725 
726  /* Set active program object. */
727  GL_CHECK(glUseProgram(programId));
728 
729  /* Draw the cubes. */
730  {
731  GL_CHECK(glUniform4fv(colorUniformLocation,
732  1,
733  cubeColor));
734 
735  if (occlusionQueriesOn)
736  {
737  /* [Bind normal cubes vertex array object] */
738  GL_CHECK(glBindVertexArray(normalCubeVertexArrayObjectId));
739  /* [Bind normal cubes vertex array object] */
740  /* [Set color mask to GL_FALSE] */
741  GL_CHECK(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
742  /* [Set color mask to GL_FALSE] */
743 
744  /* [Issue the occlusion test] */
745  for (int i = 0; i < NUMBER_OF_CUBES; i++)
746  {
748  /* Begin occlusion query. */
749  GL_CHECK(glBeginQuery(GL_ANY_SAMPLES_PASSED, cubeQuery[i]));
750  {
751  GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, numberOfCubeVertices));
752  }
753  GL_CHECK(glEndQuery(GL_ANY_SAMPLES_PASSED));
754  /* End occlusion query. */
755  }
756  /* [Issue the occlusion test] */
757 
758  /* [Set color mask to GL_TRUE] */
759  /* Clear depth buffer and enable color mask to make rounded cubes visible. */
760  GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
761  /* [Set color mask to GL_TRUE] */
762 
763  if (modeChanged)
764  {
765  GL_CHECK(glClear(GL_DEPTH_BUFFER_BIT));
766  }
767 
768  /* Clear color and depth buffers. */
769  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
770 
771  /* [Bind rounded cubes vertex array object] */
772  /* Draw rounded cubes. */
773  GL_CHECK(glBindVertexArray(roundedCubeVertexArrayObjectId));
774  /* [Bind rounded cubes vertex array object] */
775 
776  for(int i = 0; i < NUMBER_OF_CUBES; i++)
777  {
778  GLuint queryResult = GL_FALSE;
779 
780  /* [Check query result] */
781  GL_CHECK(glGetQueryObjectuiv(cubeQuery[i], GL_QUERY_RESULT, &queryResult));
782  /* [Check query result] */
783 
784  /* If the cube has become visible in this frame, render it again as a rounded cube. */
785  if (queryResult == GL_TRUE)
786  {
788 
789  /* [Draw rounded cube] */
790  GL_CHECK(glDrawArrays(GL_TRIANGLES,
791  0,
793  /* [Draw rounded cube] */
794 
796  }
797  }
798  }
799  else
800  {
801  /* [Draw for disabled occlusion query mode] */
802  /* Draw all rounded cubes without using occlusion queries. */
803  GL_CHECK(glBindVertexArray(roundedCubeVertexArrayObjectId));
804 
805  for(int i = 0; i < NUMBER_OF_CUBES; i++)
806  {
808 
809  GL_CHECK(glDrawArrays(GL_TRIANGLES,
810  0,
812  }
813 
815  /* [Draw for disabled occlusion query mode] */
816  }
817  } /* Draw the cubes. */
818 
819  /* [Draw the plane] */
820  {
821  GL_CHECK(glBindVertexArray (planeVertexArrayObjectId));
822  GL_CHECK(glUniform4fv (colorUniformLocation,
823  1,
824  planeColor));
825  GL_CHECK(glUniformMatrix4fv(normalMatrixUniformLocation,
826  1,
827  GL_FALSE,
829  GL_CHECK(glUniformMatrix4fv(worldInverseMatrixUniformLocation,
830  1,
831  GL_FALSE,
833  GL_CHECK(glUniformMatrix4fv(mvpMatrixUniformLocation,
834  1,
835  GL_FALSE,
837  GL_CHECK(glDrawArrays (GL_TRIANGLES,
838  0,
840  }
841  /* [Draw the plane] */
842 }
843 
848 {
849  if(fpsTimer.isTimePassed(1.0f))
850  {
851  /* Calculate FPS. */
852  float FPS = fpsTimer.getFPS();
853 
854  LOGI("FPS:\t%.1f", FPS);
855  LOGI("Number of Cubes drawn: %d\n", numberOfRoundedCubesDrawn);
856  }
857 
858  /* Clear color and depth buffers. */
859  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
860 
861  /* Increase angleY. */
862  angleY += 0.25f;
863 
864  if(angleY >= 360)
865  {
866  angleY = 0.0f;
867  }
868 
869  /* Rotation matrix used to rotate the view. */
870  Matrix yRotationMatrix = Matrix::createRotationY(-angleY);
871 
872  /* Multiply viewMatrix and yRotationMatrix to make camera rotate around the scene. */
873  rotatedViewMatrix = viewMatrix * yRotationMatrix;
875  planeWorldInverseMatrix = Matrix::matrixInvert(&planeMvpMatrix);
876 
877  /* [Sort positions] */
878  /* Sort the cubes' positions. We have to do it in every frame because camera constantly moves around the scene.
879  * It is important that the cubes are rendered front to back because the occlusion test is done per draw call.
880  * If the cubes are draw out of order then some cubes may pass the occlusion test even when they end up being
881  * occluded by geometry drawn later. */
883  /* [Sort positions] */
884 
885  modeChanged = false;
886 
887  /* Check timer to know if we should turn off/on occlusion queries. */
888  if(timer.getTime() > TIME_INTERVAL)
889  {
891 
893  {
894  /* Mark that mode has changed */
895  modeChanged = true;
896 
897  LOGI("\nOcclusion query ON\n");
898  text->clear();
899  text->addString(0, 0, "Occlusion query ON", 255, 0, 0, 255);
900  }
901  else
902  {
903  LOGI("\nOcclusion query OFF\n");
904  text->clear();
905  text->addString(0, 0, "Occlusion query OFF", 255, 0, 0, 255);
906  }
907 
908  timer.reset();
909  }
910 
911  draw();
912 
913  /* Enable blending (required for Text drawing). */
914  GL_CHECK(glEnable(GL_BLEND));
915 
916  text->draw();
917 
918  /* Enable blending (required for Text drawing). */
919  GL_CHECK(glDisable(GL_BLEND));
920 }
921 
925 void uninit()
926 {
927  /* Delete the program. */
928  GL_CHECK(glDeleteProgram(programId));
929 
930  /* Delete the buffer objects. */
931  GL_CHECK(glDeleteBuffers(1, &planeVerticesBufferId));
932  GL_CHECK(glDeleteBuffers(1, &planeNormalVectorsBufferId));
933  GL_CHECK(glDeleteBuffers(1, &normalCubeBufferId));
934  GL_CHECK(glDeleteBuffers(1, &roundedCubeVerticesBufferId));
935  GL_CHECK(glDeleteBuffers(1, &roundedCubeNormalVectorsBufferId));
936 
937  /* Delete the vertex array objects. */
938  GL_CHECK(glDeleteVertexArrays(1, &planeVertexArrayObjectId));
939  GL_CHECK(glDeleteVertexArrays(1, &normalCubeVertexArrayObjectId));
940  GL_CHECK(glDeleteVertexArrays(1, &roundedCubeVertexArrayObjectId));
941 
942  /* Delete the query objects. */
943  GL_CHECK(glDeleteQueries(NUMBER_OF_CUBES, cubeQuery));
944 }
945 
946 extern "C"
947 {
949  jint width,
950  jint height);
951  JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_occlusionQueries_NativeLibrary_step (JNIEnv*, jobject);
953 };
954 
956  jint width,
957  jint height)
958 {
959  setupGraphics(width, height);
960 }
961 
963 {
964  renderFrame();
965 }
966 
968 {
969  uninit();
970 }
void setupGraphics(int width, int height)
Definition: Native.cpp:1256
GLuint planeNormalVectorsBufferId
Definition: Native.cpp:167
A 2D floating point vector.
Definition: VectorTypes.h:72
Matrix planeMvpMatrix
Definition: Native.cpp:132
void generateCubesLocations(float planeWidth, float planeHeight, float minDistance)
Generate random cubes' center locations.
Definition: Native.cpp:260
GLuint planeVertexArrayObjectId
Definition: Native.cpp:159
const Vec3f upVector
Definition: Native.cpp:573
#define GL_CHECK(x)
Definition: Native.cpp:64
const float cameraRadius
Definition: Native.cpp:121
float getTime()
Returns the time passed since object creation or since reset() was last called.
Definition: Timer.cpp:109
Timer fpsTimer
Definition: Native.cpp:85
GLuint planeVerticesBufferId
Definition: Native.cpp:164
float projectionMatrix[16]
Definition: Native.cpp:156
Functions for drawing text in OpenGL ES.
Definition: Text.h:44
int windowHeight
Definition: Native.cpp:574
const string resourceDirectory
Definition: Native.cpp:67
float getFPS()
Returns the FPS (Frames Per Second).
Definition: Timer.cpp:125
#define LOGI(...)
Definition: Native.cpp:53
int numberOfPlaneVertexCoordinates
Definition: Native.cpp:190
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
#define SQUARENESS_2
Definition: Native.h:37
float * planeNormalVectors
Definition: Native.cpp:193
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_occlusionQueries_NativeLibrary_init(JNIEnv *, jobject, jint width, jint height)
Definition: Native.cpp:955
Matrix cubeWorldInverseMatrix
Definition: Native.cpp:130
GLuint vertexShaderId
Definition: Native.cpp:57
GLuint programId
Definition: Native.cpp:137
Functions for manipulating matrices.
Definition: Matrix.h:31
GLint colorUniformLocation
Definition: Native.cpp:143
bool inNeighbourhood(const Vec2f &point, float minDistance, int j)
Check if the rounded cubes are a proper distance from each other to prevent cubes overlapping...
Definition: Native.cpp:229
void draw()
Definition: Native.cpp:267
void sortCubePositions(float *arrayToSort)
Function that is used to sort cubes' center positions from the nearest to the furthest, relative to the camera position.
Definition: Native.cpp:325
GLuint normalCubeVertexArrayObjectId
Definition: Native.cpp:160
const float planeScalingFactor
Definition: Native.cpp:149
GLint worldInverseMatrixUniformLocation
Definition: Native.cpp:142
#define TIME_INTERVAL
Definition: Native.cpp:98
GLuint cubeQuery[NUMBER_OF_CUBES]
Definition: Native.cpp:112
const float planeLocation[]
Definition: Native.cpp:156
Provides a platform independent high resolution timer.
Definition: Timer.h:37
void clear(void)
Removes the current string from the class.
Definition: Text.cpp:142
Text * text
Definition: Native.cpp:205
Matrix cubeModelMatrix
Definition: Native.cpp:129
void matrixPerspective(float *matrix, float fieldOfView, float aspectRatio, float zNear, float zFar)
Create a perspective projection matrix and store the results in the first parameter.
Definition: Matrix.cpp:96
#define NORMAL_CUBE_SCALE_FACTOR
Definition: Native.h:43
bool modeChanged
Definition: Native.cpp:199
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
int numberOfCubeCoordinates
Definition: Native.cpp:182
Matrix planeNormalMatrix
Definition: Native.cpp:131
GLuint normalCubeBufferId
Definition: Native.cpp:170
A 3D floating point vector.
Definition: VectorTypes.h:83
const float yCameraTranslation
Definition: Native.cpp:124
Matrix cubeMvpMatrix
Definition: Native.cpp:128
const Vec3f lookAtPoint
Definition: Native.cpp:569
void reset()
Resets the timer to 0.0f.
Definition: Timer.cpp:100
int numberOfCubeVertices
Definition: Native.cpp:57
Matrix cubeNormalMatrix
Definition: Native.cpp:127
void uninit()
Delete created objects and free allocated memory.
Definition: Native.cpp:1706
int numberOfPlaneVertices
Definition: Native.cpp:189
GLfloat GLfloat f
Definition: gl2ext.h:2707
void addString(int xPosition, int yPosition, const char *string, int red, int green, int blue, int alpha)
Add a std::string to be drawn to the screen.
Definition: Text.cpp:157
Matrix planeModelMatrix
Definition: Native.cpp:133
GLint mvpMatrixUniformLocation
Definition: Native.cpp:141
bool occlusionQueriesOn
Definition: Native.cpp:115
const float cubeColor[]
Definition: Native.cpp:154
void renderFrame(void)
Definition: Native.cpp:1536
float distanceBetweenPoints(const Vec2f &point1, const Vec2f &point2)
Compute Euclidean 2-dimensional distance between two points on XY plane.
Definition: Native.cpp:215
Matrix planeWorldInverseMatrix
Definition: Native.cpp:134
const float planeColor[]
Definition: Native.cpp:155
GLuint roundedCubeVerticesBufferId
Definition: Native.cpp:173
float uniformRandomNumber()
Generate random number in the 0.0 to 1.0 range.
Definition: Native.cpp:246
const float minimumDistance
Definition: Native.cpp:109
float max(float x, float y)
Definition: noise.cpp:29
const float planeDividend
Definition: Native.cpp:152
float degreesToRadians(float degrees)
Convert an angle in degrees to radians.
Definition: Mathematics.h:86
float * roundedCubeNormalVectors
Definition: Native.cpp:94
float angleY
Definition: Native.cpp:118
int numberOfRoundedCubesDrawn
Definition: Native.cpp:202
Timer timer
Definition: Native.cpp:1059
float sortedCubesPositions[2 *NUMBER_OF_CUBES]
Definition: Native.cpp:146
int windowWidth
Definition: Native.cpp:575
void sendCubeLocationVectorToUniform(int whichCube)
Sends center position of a cube to the vertex shader's uniform.
Definition: Native.cpp:388
#define SQUARENESS_1
Definition: Native.h:36
float * planeVertices
Definition: Native.cpp:186
float * roundedCubeCoordinates
Definition: Native.cpp:91
int numberOfRoundedCubeCoordinates
Definition: Native.cpp:100
int numberOfRoundedCubesVertices
Definition: Native.cpp:97
GLuint roundedCubeNormalVectorsBufferId
Definition: Native.cpp:176
#define ASSERT(x, s)
Definition: common.h:45
precision highp float
Definition: hiz_cull.cs:37
GLuint fragmentShaderId
Definition: Native.cpp:55
GLint GLsizei width
Definition: gl2ext.h:179
Matrix rotatedViewMatrix
Definition: Native.cpp:136
Vec2f randomCubesPositions[NUMBER_OF_CUBES]
Definition: Native.cpp:106
Matrix viewMatrix[VIEWS]
Definition: Native.cpp:138
int numberOfRoundedCubeNormalVectors
Definition: Native.cpp:103
bool isTimePassed(float seconds=1.0f)
Tests if 'seconds' seconds have passed since reset() or this method was called.
Definition: Timer.cpp:141
void draw(void)
Draw the text to the screen.
Definition: Text.cpp:265
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
GLuint roundedCubeVertexArrayObjectId
Definition: Native.cpp:161
#define NUMBER_OF_CUBES
Definition: Native.cpp:72
#define NUMBER_OF_SAMPLES
Definition: Native.h:31
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_occlusionQueries_NativeLibrary_uninit(JNIEnv *, jobject)
Definition: Native.cpp:967
#define ROUNDED_CUBE_SCALE_FACTOR
Definition: Native.h:42
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_occlusionQueries_NativeLibrary_step(JNIEnv *, jobject)
Definition: Native.cpp:962
uniform float time
Definition: spawn.cs:50
float * normalCubeVertices
Definition: Native.cpp:179
int sizeOfPlaneNormalsArray
Definition: Native.cpp:196
GLint normalMatrixUniformLocation
Definition: Native.cpp:140
void rewriteVec2fArrayToFloatArray()
convert Vec2f array to an array of floats.
Definition: Native.cpp:374