Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / NativeClient / cube.cc
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cube.h"
6
7 #include <algorithm>
8
9 #include "shader_util.h"
10 #include "transforms.h"
11
12 namespace tumbler {
13
14 static const size_t kVertexCount = 24;
15 static const int kIndexCount = 36;
16
17 Cube::Cube(SharedOpenGLContext opengl_context)
18     : opengl_context_(opengl_context),
19       width_(1),
20       height_(1) {
21   eye_[0] = eye_[1] = 0.0f;
22   eye_[2] = 2.0f;
23   orientation_[0] = 0.0f;
24   orientation_[1] = 0.0f;
25   orientation_[2] = 0.0f;
26   orientation_[3] = 1.0f;
27 }
28
29 Cube::~Cube() {
30   glDeleteBuffers(3, cube_vbos_);
31   glDeleteProgram(shader_program_object_);
32 }
33
34 void Cube::PrepareOpenGL() {
35   CreateShaders();
36   CreateCube();
37   glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
38   glEnable(GL_DEPTH_TEST);
39 }
40
41 void Cube::Resize(int width, int height) {
42   width_ = std::max(width, 1);
43   height_ = std::max(height, 1);
44   // Set the viewport
45   glViewport(0, 0, width_, height_);
46   // Compute the perspective projection matrix with a 60 degree FOV.
47   GLfloat aspect = static_cast<GLfloat>(width_) / static_cast<GLfloat>(height_);
48   transform_4x4::LoadIdentity(perspective_proj_);
49   transform_4x4::Perspective(perspective_proj_, 60.0f, aspect, 1.0f, 20.0f);
50 }
51
52 void Cube::Draw() {
53   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
54
55   // Compute a new model-view matrix, then use that to make the composite
56   // model-view-projection matrix: MVP = MV . P.
57   GLfloat model_view[16];
58   ComputeModelViewTransform(model_view);
59   transform_4x4::Multiply(mvp_matrix_, model_view, perspective_proj_);
60
61   glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
62   glUseProgram(shader_program_object_);
63   glEnableVertexAttribArray(position_location_);
64   glVertexAttribPointer(position_location_,
65                         3,
66                         GL_FLOAT,
67                         GL_FALSE,
68                         3 * sizeof(GLfloat),
69                         NULL);
70   glEnableVertexAttribArray(color_location_);
71   glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
72   glVertexAttribPointer(color_location_,
73                         3,
74                         GL_FLOAT,
75                         GL_FALSE,
76                         3 * sizeof(GLfloat),
77                         NULL);
78   glUniformMatrix4fv(mvp_location_, 1, GL_FALSE, mvp_matrix_);
79   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
80   glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
81   glBindBuffer(GL_ARRAY_BUFFER, 0);
82   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
83 }
84
85 bool Cube::CreateShaders() {
86   const char vertex_shader_src[] =
87     "uniform mat4 u_mvpMatrix;                   \n"
88     "attribute vec4 a_position;                  \n"
89     "attribute vec3 a_color;                     \n"
90     "varying lowp vec4 v_color;                  \n"
91     "void main()                                 \n"
92     "{                                           \n"
93     "   v_color.xyz = a_color;                   \n"
94     "   v_color.w = 1.0;                         \n"
95     "   gl_Position = u_mvpMatrix * a_position;  \n"
96     "}                                           \n";
97
98   const char fragment_shader_src[] =
99     "varying lowp vec4 v_color;                   \n"
100     "void main()                                  \n"
101     "{                                            \n"
102     "  gl_FragColor = v_color;                    \n"
103     "}                                            \n";
104
105   // Load the shaders and get a linked program object
106   shader_program_object_ =
107       shader_util::CreateProgramFromVertexAndFragmentShaders(
108       vertex_shader_src, fragment_shader_src);
109   if (shader_program_object_ == 0)
110     return false;
111   position_location_ = glGetAttribLocation(shader_program_object_,
112                                            "a_position");
113   color_location_ = glGetAttribLocation(shader_program_object_, "a_color");
114   mvp_location_ = glGetUniformLocation(shader_program_object_, "u_mvpMatrix");
115   return true;
116 }
117
118 void Cube::CreateCube() {
119   static const GLfloat cube_vertices[] = {
120     // Vertex coordinates interleaved with color values
121     // Bottom
122     -0.5f, -0.5f, -0.5f,
123     -0.5f, -0.5f, 0.5f,
124     0.5f, -0.5f, 0.5f,
125     0.5f, -0.5f, -0.5f,
126     // Top
127     -0.5f, 0.5f, -0.5f,
128     -0.5f, 0.5f, 0.5f,
129     0.5f, 0.5f, 0.5f,
130     0.5f, 0.5f, -0.5f,
131     // Back
132     -0.5f, -0.5f, -0.5f,
133     -0.5f, 0.5f, -0.5f,
134     0.5f, 0.5f, -0.5f,
135     0.5f, -0.5f, -0.5f,
136     // Front
137     -0.5f, -0.5f, 0.5f,
138     -0.5f, 0.5f, 0.5f,
139     0.5f, 0.5f, 0.5f,
140     0.5f, -0.5f, 0.5f,
141     // Left
142     -0.5f, -0.5f, -0.5f,
143     -0.5f, -0.5f, 0.5f,
144     -0.5f, 0.5f, 0.5f,
145     -0.5f, 0.5f, -0.5f,
146     // Right
147     0.5f, -0.5f, -0.5f,
148     0.5f, -0.5f, 0.5f,
149     0.5f, 0.5f, 0.5f,
150     0.5f, 0.5f, -0.5f
151   };
152
153   static const GLfloat cube_colors[] = {
154     // Vertex coordinates interleaved with color values
155     // Bottom
156     1.0, 0.0, 0.0,
157     1.0, 0.0, 0.0,
158     1.0, 0.0, 0.0,
159     1.0, 0.0, 0.0,
160     // Top
161     0.0, 1.0, 0.0,
162     0.0, 1.0, 0.0,
163     0.0, 1.0, 0.0,
164     0.0, 1.0, 0.0,
165     // Back
166     0.0, 0.0, 1.0,
167     0.0, 0.0, 1.0,
168     0.0, 0.0, 1.0,
169     0.0, 0.0, 1.0,
170     // Front
171     1.0, 0.0, 1.0,
172     1.0, 0.0, 1.0,
173     1.0, 0.0, 1.0,
174     1.0, 0.0, 1.0,
175     // Left
176     1.0, 1.0, 0.0,
177     1.0, 1.0, 0.0,
178     1.0, 1.0, 0.0,
179     1.0, 1.0, 0.0,
180     // Right
181     0.0, 1.0, 1.0,
182     0.0, 1.0, 1.0,
183     0.0, 1.0, 1.0,
184     0.0, 1.0, 1.0
185   };
186
187   static const GLushort cube_indices[] = {
188     // Bottom
189     0, 2, 1,
190     0, 3, 2,
191     // Top
192     4, 5, 6,
193     4, 6, 7,
194     // Back
195     8, 9, 10,
196     8, 10, 11,
197     // Front
198     12, 15, 14,
199     12, 14, 13,
200     // Left
201     16, 17, 18,
202     16, 18, 19,
203     // Right
204     20, 23, 22,
205     20, 22, 21
206   };
207
208   // Generate the VBOs and upload them to the graphics context.
209   glGenBuffers(3, cube_vbos_);
210   glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
211   glBufferData(GL_ARRAY_BUFFER,
212                kVertexCount * sizeof(GLfloat) * 3,
213                cube_vertices,
214                GL_STATIC_DRAW);
215   glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
216   glBufferData(GL_ARRAY_BUFFER,
217                kVertexCount * sizeof(GLfloat) * 3,
218                cube_colors,
219                GL_STATIC_DRAW);
220   glBindBuffer(GL_ARRAY_BUFFER, 0);
221   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
222   glBufferData(GL_ELEMENT_ARRAY_BUFFER,
223                kIndexCount * sizeof(GL_UNSIGNED_SHORT),
224                cube_indices,
225                GL_STATIC_DRAW);
226   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
227 }
228
229 void Cube::ComputeModelViewTransform(GLfloat* model_view) {
230   // This method takes into account the possiblity that |orientation_|
231   // might not be normalized.
232   double sqrx = orientation_[0] * orientation_[0];
233   double sqry = orientation_[1] * orientation_[1];
234   double sqrz = orientation_[2] * orientation_[2];
235   double sqrw = orientation_[3] * orientation_[3];
236   double sqrLength = 1.0 / (sqrx + sqry + sqrz + sqrw);
237
238   transform_4x4::LoadIdentity(model_view);
239   model_view[0] = (sqrx - sqry - sqrz + sqrw) * sqrLength;
240   model_view[5] = (-sqrx + sqry - sqrz + sqrw) * sqrLength;
241   model_view[10] = (-sqrx - sqry + sqrz + sqrw) * sqrLength;
242
243   double temp1 = orientation_[0] * orientation_[1];
244   double temp2 = orientation_[2] * orientation_[3];
245   model_view[1] = 2.0 * (temp1 + temp2) * sqrLength;
246   model_view[4] = 2.0 * (temp1 - temp2) * sqrLength;
247
248   temp1 = orientation_[0] * orientation_[2];
249   temp2 = orientation_[1] * orientation_[3];
250   model_view[2] = 2.0 * (temp1 - temp2) * sqrLength;
251   model_view[8] = 2.0 * (temp1 + temp2) * sqrLength;
252   temp1 = orientation_[1] * orientation_[2];
253   temp2 = orientation_[0] * orientation_[3];
254   model_view[6] = 2.0 * (temp1 + temp2) * sqrLength;
255   model_view[9] = 2.0 * (temp1 - temp2) * sqrLength;
256   model_view[3] = 0.0;
257   model_view[7] = 0.0;
258   model_view[11] = 0.0;
259
260   // Concatenate the translation to the eye point.
261   model_view[12] = -eye_[0];
262   model_view[13] = -eye_[1];
263   model_view[14] = -eye_[2];
264   model_view[15] = 1.0;
265 }
266
267 }  // namespace tumbler