1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Copyright 2013 The Chromium Authors. All rights reserved. 2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Use of this source code is governed by a BSD-style license that can be 3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// found in the LICENSE file. 4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// This example program is based on Simple_VertexShader.c from: 6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// 8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Book: OpenGL(R) ES 2.0 Programming Guide 9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// ISBN-10: 0321502795 11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// ISBN-13: 9780321502797 12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Publisher: Addison-Wesley Professional 13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// URLs: http://safari.informit.com/9780321563835 14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// http://www.opengles-book.com 15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// 16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "mojo/examples/sample_app/spinning_cube.h" 18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <math.h> 20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <stdlib.h> 21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <string.h> 22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <GLES2/gl2.h> 23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <GLES2/gl2ext.h> 24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectnamespace examples { 26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectnamespace { 28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectconst float kPi = 3.14159265359f; 30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint GenerateCube(GLuint *vbo_vertices, 32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLuint *vbo_indices) { 33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const int num_indices = 36; 34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const GLfloat cube_vertices[] = { 36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, -0.5f, -0.5f, 37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, -0.5f, 0.5f, 38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, -0.5f, 0.5f, 39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, -0.5f, -0.5f, 40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, 0.5f, -0.5f, 41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, 0.5f, 0.5f, 42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, 0.5f, 0.5f, 43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, 0.5f, -0.5f, 44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, -0.5f, -0.5f, 45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, 0.5f, -0.5f, 46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, 0.5f, -0.5f, 47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, -0.5f, -0.5f, 48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, -0.5f, 0.5f, 49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, 0.5f, 0.5f, 50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, 0.5f, 0.5f, 51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, -0.5f, 0.5f, 52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, -0.5f, -0.5f, 53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, -0.5f, 0.5f, 54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, 0.5f, 0.5f, 55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project -0.5f, 0.5f, -0.5f, 56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, -0.5f, -0.5f, 57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, -0.5f, 0.5f, 58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, 0.5f, 0.5f, 59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0.5f, 0.5f, -0.5f, 60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project }; 61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const GLushort cube_indices[] = { 63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0, 2, 1, 64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 0, 3, 2, 65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 4, 5, 6, 66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 4, 6, 7, 67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 8, 9, 10, 68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 8, 10, 11, 69656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 12, 15, 14, 70656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 12, 14, 13, 71656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 16, 17, 18, 72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 16, 18, 19, 73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 20, 23, 22, 74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 20, 22, 21 75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project }; 76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 77656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (vbo_vertices) { 78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glGenBuffers(1, vbo_vertices); 79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glBindBuffer(GL_ARRAY_BUFFER, *vbo_vertices); 80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glBufferData(GL_ARRAY_BUFFER, 81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sizeof(cube_vertices), 82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project cube_vertices, 83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GL_STATIC_DRAW); 84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glBindBuffer(GL_ARRAY_BUFFER, 0); 85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (vbo_indices) { 88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glGenBuffers(1, vbo_indices); 89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *vbo_indices); 90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glBufferData(GL_ELEMENT_ARRAY_BUFFER, 91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sizeof(cube_indices), 92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project cube_indices, 93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GL_STATIC_DRAW); 94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return num_indices; 98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectGLuint LoadShader(GLenum type, 101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const char* shader_source) { 102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLuint shader = glCreateShader(type); 103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glShaderSource(shader, 1, &shader_source, NULL); 104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glCompileShader(shader); 105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLint compiled = 0; 107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!compiled) { 110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glDeleteShader(shader); 111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 113656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return shader; 115656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 116656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 117656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectGLuint LoadProgram(const char* vertext_shader_source, 118656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const char* fragment_shader_source) { 119656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER, 120656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project vertext_shader_source); 121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!vertex_shader) 122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER, 125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project fragment_shader_source); 126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!fragment_shader) { 127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glDeleteShader(vertex_shader); 128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLuint program_object = glCreateProgram(); 132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glAttachShader(program_object, vertex_shader); 133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glAttachShader(program_object, fragment_shader); 134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glLinkProgram(program_object); 136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glDeleteShader(vertex_shader); 138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glDeleteShader(fragment_shader); 139656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLint linked = 0; 141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glGetProgramiv(program_object, GL_LINK_STATUS, &linked); 142656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 143656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!linked) { 144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project glDeleteProgram(program_object); 145656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 148656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return program_object; 149656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 150656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 151656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectclass ESMatrix { 152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project public: 153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat m[4][4]; 154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ESMatrix() { 156656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project LoadZero(); 157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void LoadZero() { 160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project memset(this, 0x0, sizeof(ESMatrix)); 161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void LoadIdentity() { 164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project LoadZero(); 165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[0][0] = 1.0f; 166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[1][1] = 1.0f; 167656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[2][2] = 1.0f; 168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[3][3] = 1.0f; 169656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 170656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 171656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void Multiply(ESMatrix* a, ESMatrix* b) { 172656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ESMatrix result; 173656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for (int i = 0; i < 4; ++i) { 174656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project result.m[i][0] = (a->m[i][0] * b->m[0][0]) + 175656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][1] * b->m[1][0]) + 176656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][2] * b->m[2][0]) + 177656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][3] * b->m[3][0]); 178656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 179656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project result.m[i][1] = (a->m[i][0] * b->m[0][1]) + 180656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][1] * b->m[1][1]) + 181656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][2] * b->m[2][1]) + 182656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][3] * b->m[3][1]); 183656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 184656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project result.m[i][2] = (a->m[i][0] * b->m[0][2]) + 185656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][1] * b->m[1][2]) + 186656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][2] * b->m[2][2]) + 187656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][3] * b->m[3][2]); 188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project result.m[i][3] = (a->m[i][0] * b->m[0][3]) + 190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][1] * b->m[1][3]) + 191656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][2] * b->m[2][3]) + 192656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (a->m[i][3] * b->m[3][3]); 193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *this = result; 195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void Frustum(float left, 198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float right, 199656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float bottom, 200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float top, 201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float near_z, 202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float far_z) { 203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float delta_x = right - left; 204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float delta_y = top - bottom; 205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project float delta_z = far_z - near_z; 206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if ((near_z <= 0.0f) || 208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (far_z <= 0.0f) || 209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (delta_z <= 0.0f) || 210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (delta_y <= 0.0f) || 211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (delta_y <= 0.0f)) 212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return; 213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 214656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ESMatrix frust; 215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[0][0] = 2.0f * near_z / delta_x; 216656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f; 217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 218656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[1][1] = 2.0f * near_z / delta_y; 219656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f; 220656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 221656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[2][0] = (right + left) / delta_x; 222656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[2][1] = (top + bottom) / delta_y; 223656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[2][2] = -(near_z + far_z) / delta_z; 224656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[2][3] = -1.0f; 225656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 226656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[3][2] = -2.0f * near_z * far_z / delta_z; 227656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f; 228656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project Multiply(&frust, this); 230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void Perspective(float fov_y, float aspect, float near_z, float far_z) { 233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat frustum_h = tanf(fov_y / 360.0f * kPi) * near_z; 234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat frustum_w = frustum_h * aspect; 235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project Frustum(-frustum_w, frustum_w, -frustum_h, frustum_h, near_z, far_z); 236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 237656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void Translate(GLfloat tx, GLfloat ty, GLfloat tz) { 239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[3][0] += m[0][0] * tx + m[1][0] * ty + m[2][0] * tz; 240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[3][1] += m[0][1] * tx + m[1][1] * ty + m[2][1] * tz; 241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[3][2] += m[0][2] * tx + m[1][2] * ty + m[2][2] * tz; 242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project m[3][3] += m[0][3] * tx + m[1][3] * ty + m[2][3] * tz; 243656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 245656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project void Rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { 246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat mag = sqrtf(x * x + y * y + z * z); 247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat sin_angle = sinf(angle * kPi / 180.0f); 249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat cos_angle = cosf(angle * kPi / 180.0f); 250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (mag > 0.0f) { 251656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs; 252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project GLfloat one_minus_cos; 253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ESMatrix rotation; 254656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 255 x /= mag; 256 y /= mag; 257 z /= mag; 258 259 xx = x * x; 260 yy = y * y; 261 zz = z * z; 262 xy = x * y; 263 yz = y * z; 264 zx = z * x; 265 xs = x * sin_angle; 266 ys = y * sin_angle; 267 zs = z * sin_angle; 268 one_minus_cos = 1.0f - cos_angle; 269 270 rotation.m[0][0] = (one_minus_cos * xx) + cos_angle; 271 rotation.m[0][1] = (one_minus_cos * xy) - zs; 272 rotation.m[0][2] = (one_minus_cos * zx) + ys; 273 rotation.m[0][3] = 0.0F; 274 275 rotation.m[1][0] = (one_minus_cos * xy) + zs; 276 rotation.m[1][1] = (one_minus_cos * yy) + cos_angle; 277 rotation.m[1][2] = (one_minus_cos * yz) - xs; 278 rotation.m[1][3] = 0.0F; 279 280 rotation.m[2][0] = (one_minus_cos * zx) - ys; 281 rotation.m[2][1] = (one_minus_cos * yz) + xs; 282 rotation.m[2][2] = (one_minus_cos * zz) + cos_angle; 283 rotation.m[2][3] = 0.0F; 284 285 rotation.m[3][0] = 0.0F; 286 rotation.m[3][1] = 0.0F; 287 rotation.m[3][2] = 0.0F; 288 rotation.m[3][3] = 1.0F; 289 290 Multiply(&rotation, this); 291 } 292 } 293}; 294 295float RotationForTimeDelta(float delta_time) { 296 return delta_time * 40.0f; 297} 298 299float RotationForDragDistance(float drag_distance) { 300 return drag_distance / 5; // Arbitrary damping. 301} 302 303} // namespace 304 305class SpinningCube::GLState { 306 public: 307 GLState(); 308 309 void OnGLContextLost(); 310 311 GLfloat angle_; // Survives losing the GL context. 312 313 GLuint program_object_; 314 GLint position_location_; 315 GLint mvp_location_; 316 GLint color_location_; 317 GLuint vbo_vertices_; 318 GLuint vbo_indices_; 319 int num_indices_; 320 ESMatrix mvp_matrix_; 321}; 322 323SpinningCube::GLState::GLState() 324 : angle_(0) { 325 OnGLContextLost(); 326} 327 328void SpinningCube::GLState::OnGLContextLost() { 329 program_object_ = 0; 330 position_location_ = 0; 331 mvp_location_ = 0; 332 color_location_ = 0; 333 vbo_vertices_ = 0; 334 vbo_indices_ = 0; 335 num_indices_ = 0; 336} 337 338SpinningCube::SpinningCube() 339 : initialized_(false), 340 width_(0), 341 height_(0), 342 state_(new GLState()), 343 fling_multiplier_(1.0f), 344 direction_(1), 345 color_() { 346 state_->angle_ = 45.0f; 347 set_color(0.0, 1.0, 0.0); 348} 349 350SpinningCube::~SpinningCube() { 351 if (!initialized_) 352 return; 353 if (state_->vbo_vertices_) 354 glDeleteBuffers(1, &state_->vbo_vertices_); 355 if (state_->vbo_indices_) 356 glDeleteBuffers(1, &state_->vbo_indices_); 357 if (state_->program_object_) 358 glDeleteProgram(state_->program_object_); 359} 360 361void SpinningCube::Init(uint32_t width, uint32_t height) { 362 width_ = width; 363 height_ = height; 364 365 const char vertext_shader_source[] = 366 "uniform mat4 u_mvpMatrix; \n" 367 "attribute vec4 a_position; \n" 368 "void main() \n" 369 "{ \n" 370 " gl_Position = u_mvpMatrix * a_position; \n" 371 "} \n"; 372 373 const char fragment_shader_source[] = 374 "precision mediump float; \n" 375 "uniform vec4 u_color; \n" 376 "void main() \n" 377 "{ \n" 378 " gl_FragColor = u_color; \n" 379 "} \n"; 380 381 state_->program_object_ = LoadProgram( 382 vertext_shader_source, fragment_shader_source); 383 state_->position_location_ = glGetAttribLocation( 384 state_->program_object_, "a_position"); 385 state_->mvp_location_ = glGetUniformLocation( 386 state_->program_object_, "u_mvpMatrix"); 387 state_->color_location_ = glGetUniformLocation( 388 state_->program_object_, "u_color"); 389 state_->num_indices_ = GenerateCube( 390 &state_->vbo_vertices_, &state_->vbo_indices_); 391 392 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 393 initialized_ = true; 394} 395 396void SpinningCube::OnGLContextLost() { 397 initialized_ = false; 398 height_ = 0; 399 width_ = 0; 400 state_->OnGLContextLost(); 401} 402 403void SpinningCube::SetFlingMultiplier(float drag_distance, 404 float drag_time) { 405 fling_multiplier_ = RotationForDragDistance(drag_distance) / 406 RotationForTimeDelta(drag_time); 407 408} 409 410void SpinningCube::UpdateForTimeDelta(float delta_time) { 411 state_->angle_ += RotationForTimeDelta(delta_time) * fling_multiplier_; 412 if (state_->angle_ >= 360.0f) 413 state_->angle_ -= 360.0f; 414 415 // Arbitrary 50-step linear reduction in spin speed. 416 if (fling_multiplier_ > 1.0f) { 417 fling_multiplier_ = 418 std::max(1.0f, fling_multiplier_ - (fling_multiplier_ - 1.0f) / 50); 419 } 420 421 Update(); 422} 423 424void SpinningCube::UpdateForDragDistance(float distance) { 425 state_->angle_ += RotationForDragDistance(distance); 426 if (state_->angle_ >= 360.0f ) 427 state_->angle_ -= 360.0f; 428 429 Update(); 430} 431 432void SpinningCube::Draw() { 433 glViewport(0, 0, width_, height_); 434 glClear(GL_COLOR_BUFFER_BIT); 435 glUseProgram(state_->program_object_); 436 glBindBuffer(GL_ARRAY_BUFFER, state_->vbo_vertices_); 437 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state_->vbo_indices_); 438 glVertexAttribPointer(state_->position_location_, 439 3, 440 GL_FLOAT, 441 GL_FALSE, 3 * sizeof(GLfloat), 442 0); 443 glEnableVertexAttribArray(state_->position_location_); 444 glUniformMatrix4fv(state_->mvp_location_, 445 1, 446 GL_FALSE, 447 (GLfloat*) &state_->mvp_matrix_.m[0][0]); 448 glUniform4f(state_->color_location_, color_[0], color_[1], color_[2], 1.0); 449 glDrawElements(GL_TRIANGLES, 450 state_->num_indices_, 451 GL_UNSIGNED_SHORT, 452 0); 453} 454 455void SpinningCube::Update() { 456 float aspect = static_cast<GLfloat>(width_) / static_cast<GLfloat>(height_); 457 458 ESMatrix perspective; 459 perspective.LoadIdentity(); 460 perspective.Perspective(60.0f, aspect, 1.0f, 20.0f ); 461 462 ESMatrix modelview; 463 modelview.LoadIdentity(); 464 modelview.Translate(0.0, 0.0, -2.0); 465 modelview.Rotate(state_->angle_ * direction_, 1.0, 0.0, 1.0); 466 467 state_->mvp_matrix_.Multiply(&modelview, &perspective); 468} 469 470} // namespace examples 471