Use statically linked freeglut, instead of dynamic glut for the obsolete Bullet 2.x demos Add the 'reset' method to b3GpuDynamicsWorld, and use it in the BasicGpuDemo (pretty slow in debug mode, use release mode) Don't crash in btCollisionWorld, if there is no collision dispatcher
268 lines
7.8 KiB
C++
268 lines
7.8 KiB
C++
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "cube.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "shader_util.h"
|
|
#include "transforms.h"
|
|
|
|
namespace tumbler {
|
|
|
|
static const size_t kVertexCount = 24;
|
|
static const int kIndexCount = 36;
|
|
|
|
Cube::Cube(SharedOpenGLContext opengl_context)
|
|
: opengl_context_(opengl_context),
|
|
width_(1),
|
|
height_(1) {
|
|
eye_[0] = eye_[1] = 0.0f;
|
|
eye_[2] = 2.0f;
|
|
orientation_[0] = 0.0f;
|
|
orientation_[1] = 0.0f;
|
|
orientation_[2] = 0.0f;
|
|
orientation_[3] = 1.0f;
|
|
}
|
|
|
|
Cube::~Cube() {
|
|
glDeleteBuffers(3, cube_vbos_);
|
|
glDeleteProgram(shader_program_object_);
|
|
}
|
|
|
|
void Cube::PrepareOpenGL() {
|
|
CreateShaders();
|
|
CreateCube();
|
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
void Cube::Resize(int width, int height) {
|
|
width_ = std::max(width, 1);
|
|
height_ = std::max(height, 1);
|
|
// Set the viewport
|
|
glViewport(0, 0, width_, height_);
|
|
// Compute the perspective projection matrix with a 60 degree FOV.
|
|
GLfloat aspect = static_cast<GLfloat>(width_) / static_cast<GLfloat>(height_);
|
|
transform_4x4::LoadIdentity(perspective_proj_);
|
|
transform_4x4::Perspective(perspective_proj_, 60.0f, aspect, 1.0f, 20.0f);
|
|
}
|
|
|
|
void Cube::Draw() {
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
// Compute a new model-view matrix, then use that to make the composite
|
|
// model-view-projection matrix: MVP = MV . P.
|
|
GLfloat model_view[16];
|
|
ComputeModelViewTransform(model_view);
|
|
transform_4x4::Multiply(mvp_matrix_, model_view, perspective_proj_);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
|
|
glUseProgram(shader_program_object_);
|
|
glEnableVertexAttribArray(position_location_);
|
|
glVertexAttribPointer(position_location_,
|
|
3,
|
|
GL_FLOAT,
|
|
GL_FALSE,
|
|
3 * sizeof(GLfloat),
|
|
NULL);
|
|
glEnableVertexAttribArray(color_location_);
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
|
|
glVertexAttribPointer(color_location_,
|
|
3,
|
|
GL_FLOAT,
|
|
GL_FALSE,
|
|
3 * sizeof(GLfloat),
|
|
NULL);
|
|
glUniformMatrix4fv(mvp_location_, 1, GL_FALSE, mvp_matrix_);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
|
|
glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
bool Cube::CreateShaders() {
|
|
const char vertex_shader_src[] =
|
|
"uniform mat4 u_mvpMatrix; \n"
|
|
"attribute vec4 a_position; \n"
|
|
"attribute vec3 a_color; \n"
|
|
"varying lowp vec4 v_color; \n"
|
|
"void main() \n"
|
|
"{ \n"
|
|
" v_color.xyz = a_color; \n"
|
|
" v_color.w = 1.0; \n"
|
|
" gl_Position = u_mvpMatrix * a_position; \n"
|
|
"} \n";
|
|
|
|
const char fragment_shader_src[] =
|
|
"varying lowp vec4 v_color; \n"
|
|
"void main() \n"
|
|
"{ \n"
|
|
" gl_FragColor = v_color; \n"
|
|
"} \n";
|
|
|
|
// Load the shaders and get a linked program object
|
|
shader_program_object_ =
|
|
shader_util::CreateProgramFromVertexAndFragmentShaders(
|
|
vertex_shader_src, fragment_shader_src);
|
|
if (shader_program_object_ == 0)
|
|
return false;
|
|
position_location_ = glGetAttribLocation(shader_program_object_,
|
|
"a_position");
|
|
color_location_ = glGetAttribLocation(shader_program_object_, "a_color");
|
|
mvp_location_ = glGetUniformLocation(shader_program_object_, "u_mvpMatrix");
|
|
return true;
|
|
}
|
|
|
|
void Cube::CreateCube() {
|
|
static const GLfloat cube_vertices[] = {
|
|
// Vertex coordinates interleaved with color values
|
|
// Bottom
|
|
-0.5f, -0.5f, -0.5f,
|
|
-0.5f, -0.5f, 0.5f,
|
|
0.5f, -0.5f, 0.5f,
|
|
0.5f, -0.5f, -0.5f,
|
|
// Top
|
|
-0.5f, 0.5f, -0.5f,
|
|
-0.5f, 0.5f, 0.5f,
|
|
0.5f, 0.5f, 0.5f,
|
|
0.5f, 0.5f, -0.5f,
|
|
// Back
|
|
-0.5f, -0.5f, -0.5f,
|
|
-0.5f, 0.5f, -0.5f,
|
|
0.5f, 0.5f, -0.5f,
|
|
0.5f, -0.5f, -0.5f,
|
|
// Front
|
|
-0.5f, -0.5f, 0.5f,
|
|
-0.5f, 0.5f, 0.5f,
|
|
0.5f, 0.5f, 0.5f,
|
|
0.5f, -0.5f, 0.5f,
|
|
// Left
|
|
-0.5f, -0.5f, -0.5f,
|
|
-0.5f, -0.5f, 0.5f,
|
|
-0.5f, 0.5f, 0.5f,
|
|
-0.5f, 0.5f, -0.5f,
|
|
// Right
|
|
0.5f, -0.5f, -0.5f,
|
|
0.5f, -0.5f, 0.5f,
|
|
0.5f, 0.5f, 0.5f,
|
|
0.5f, 0.5f, -0.5f
|
|
};
|
|
|
|
static const GLfloat cube_colors[] = {
|
|
// Vertex coordinates interleaved with color values
|
|
// Bottom
|
|
1.0, 0.0, 0.0,
|
|
1.0, 0.0, 0.0,
|
|
1.0, 0.0, 0.0,
|
|
1.0, 0.0, 0.0,
|
|
// Top
|
|
0.0, 1.0, 0.0,
|
|
0.0, 1.0, 0.0,
|
|
0.0, 1.0, 0.0,
|
|
0.0, 1.0, 0.0,
|
|
// Back
|
|
0.0, 0.0, 1.0,
|
|
0.0, 0.0, 1.0,
|
|
0.0, 0.0, 1.0,
|
|
0.0, 0.0, 1.0,
|
|
// Front
|
|
1.0, 0.0, 1.0,
|
|
1.0, 0.0, 1.0,
|
|
1.0, 0.0, 1.0,
|
|
1.0, 0.0, 1.0,
|
|
// Left
|
|
1.0, 1.0, 0.0,
|
|
1.0, 1.0, 0.0,
|
|
1.0, 1.0, 0.0,
|
|
1.0, 1.0, 0.0,
|
|
// Right
|
|
0.0, 1.0, 1.0,
|
|
0.0, 1.0, 1.0,
|
|
0.0, 1.0, 1.0,
|
|
0.0, 1.0, 1.0
|
|
};
|
|
|
|
static const GLushort cube_indices[] = {
|
|
// Bottom
|
|
0, 2, 1,
|
|
0, 3, 2,
|
|
// Top
|
|
4, 5, 6,
|
|
4, 6, 7,
|
|
// Back
|
|
8, 9, 10,
|
|
8, 10, 11,
|
|
// Front
|
|
12, 15, 14,
|
|
12, 14, 13,
|
|
// Left
|
|
16, 17, 18,
|
|
16, 18, 19,
|
|
// Right
|
|
20, 23, 22,
|
|
20, 22, 21
|
|
};
|
|
|
|
// Generate the VBOs and upload them to the graphics context.
|
|
glGenBuffers(3, cube_vbos_);
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
|
|
glBufferData(GL_ARRAY_BUFFER,
|
|
kVertexCount * sizeof(GLfloat) * 3,
|
|
cube_vertices,
|
|
GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
|
|
glBufferData(GL_ARRAY_BUFFER,
|
|
kVertexCount * sizeof(GLfloat) * 3,
|
|
cube_colors,
|
|
GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
|
kIndexCount * sizeof(GL_UNSIGNED_SHORT),
|
|
cube_indices,
|
|
GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
void Cube::ComputeModelViewTransform(GLfloat* model_view) {
|
|
// This method takes into account the possiblity that |orientation_|
|
|
// might not be normalized.
|
|
double sqrx = orientation_[0] * orientation_[0];
|
|
double sqry = orientation_[1] * orientation_[1];
|
|
double sqrz = orientation_[2] * orientation_[2];
|
|
double sqrw = orientation_[3] * orientation_[3];
|
|
double sqrLength = 1.0 / (sqrx + sqry + sqrz + sqrw);
|
|
|
|
transform_4x4::LoadIdentity(model_view);
|
|
model_view[0] = (sqrx - sqry - sqrz + sqrw) * sqrLength;
|
|
model_view[5] = (-sqrx + sqry - sqrz + sqrw) * sqrLength;
|
|
model_view[10] = (-sqrx - sqry + sqrz + sqrw) * sqrLength;
|
|
|
|
double temp1 = orientation_[0] * orientation_[1];
|
|
double temp2 = orientation_[2] * orientation_[3];
|
|
model_view[1] = 2.0 * (temp1 + temp2) * sqrLength;
|
|
model_view[4] = 2.0 * (temp1 - temp2) * sqrLength;
|
|
|
|
temp1 = orientation_[0] * orientation_[2];
|
|
temp2 = orientation_[1] * orientation_[3];
|
|
model_view[2] = 2.0 * (temp1 - temp2) * sqrLength;
|
|
model_view[8] = 2.0 * (temp1 + temp2) * sqrLength;
|
|
temp1 = orientation_[1] * orientation_[2];
|
|
temp2 = orientation_[0] * orientation_[3];
|
|
model_view[6] = 2.0 * (temp1 + temp2) * sqrLength;
|
|
model_view[9] = 2.0 * (temp1 - temp2) * sqrLength;
|
|
model_view[3] = 0.0;
|
|
model_view[7] = 0.0;
|
|
model_view[11] = 0.0;
|
|
|
|
// Concatenate the translation to the eye point.
|
|
model_view[12] = -eye_[0];
|
|
model_view[13] = -eye_[1];
|
|
model_view[14] = -eye_[2];
|
|
model_view[15] = 1.0;
|
|
}
|
|
|
|
} // namespace tumbler
|