194 lines
6.5 KiB
C++
194 lines
6.5 KiB
C++
/*
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
* in compliance with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
* or implied. See the License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*/
|
|
#include "FlockingScene.h"
|
|
|
|
#include "WaterMeshNode.h"
|
|
|
|
#include <cstdlib>
|
|
#include <cmath>
|
|
|
|
#include <Trace.h>
|
|
|
|
#include <graphics/PerspectiveMeshNode.h>
|
|
#include <graphics/PerspectiveProgram.h>
|
|
#include <graphics/GLUtils.h>
|
|
#include <graphics/Matrix.h>
|
|
#include <graphics/Mesh.h>
|
|
#include <graphics/ProgramNode.h>
|
|
#include <graphics/TransformationNode.h>
|
|
|
|
FlockingScene::FlockingScene(int width, int height) :
|
|
Scene(width, height), mMainProgram(NULL), mWaterProgram(NULL) {
|
|
for (int i = 0; i < NUM_BOIDS; i++) {
|
|
// Generate a boid with a random position. (-50, 50)
|
|
float x = (rand() % 101) - 50.0f;
|
|
float y = (rand() % 101) - 50.0f;
|
|
mBoids[i] = new Boid(x, y);
|
|
}
|
|
}
|
|
|
|
bool FlockingScene::setUpPrograms() {
|
|
// Main Program
|
|
const char* vertex = GLUtils::openTextFile("vertex/perspective");
|
|
const char* fragment = GLUtils::openTextFile("fragment/perspective");
|
|
if (vertex == NULL || fragment == NULL) {
|
|
return false;
|
|
}
|
|
GLuint programId = GLUtils::createProgram(&vertex, &fragment);
|
|
delete[] vertex;
|
|
delete[] fragment;
|
|
if (programId == 0) {
|
|
return false;
|
|
}
|
|
mMainProgram = new PerspectiveProgram(programId);
|
|
// Water Program
|
|
vertex = GLUtils::openTextFile("vertex/water");
|
|
fragment = GLUtils::openTextFile("fragment/water");
|
|
if (vertex == NULL || fragment == NULL) {
|
|
return false;
|
|
}
|
|
programId = GLUtils::createProgram(&vertex, &fragment);
|
|
delete[] vertex;
|
|
delete[] fragment;
|
|
if (programId == 0) {
|
|
return false;
|
|
}
|
|
mWaterProgram = new PerspectiveProgram(programId);
|
|
return true;
|
|
}
|
|
|
|
Matrix* FlockingScene::setUpModelMatrix() {
|
|
return new Matrix();
|
|
}
|
|
|
|
Matrix* FlockingScene::setUpViewMatrix() {
|
|
// Position the eye in front of the origin.
|
|
float eyeX = 0.0f;
|
|
float eyeY = 0.0f;
|
|
float eyeZ = 10.0f;
|
|
|
|
// We are looking at the origin
|
|
float centerX = 0.0f;
|
|
float centerY = 0.0f;
|
|
float centerZ = 0.0f;
|
|
|
|
// Set our up vector.
|
|
float upX = 0.0f;
|
|
float upY = 1.0f;
|
|
float upZ = 0.0f;
|
|
|
|
// Set the view matrix.
|
|
return Matrix::newLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
|
|
}
|
|
|
|
Matrix* FlockingScene::setUpProjectionMatrix(float width, float height) {
|
|
// Create a new perspective projection matrix. The height will stay the same
|
|
// while the width will vary as per aspect ratio.
|
|
mDisplayRatio = width / height;
|
|
// Set board dimensions
|
|
mBoardHeight = 1000.0f;
|
|
mBoardWidth = mDisplayRatio * mBoardHeight;
|
|
float left = -mDisplayRatio;
|
|
float right = mDisplayRatio;
|
|
float bottom = -1.0f;
|
|
float top = 1.0f;
|
|
float near = 8.0f;
|
|
float far = 12.0f;
|
|
|
|
return Matrix::newFrustum(left, right, bottom, top, near, far);
|
|
}
|
|
|
|
bool FlockingScene::setUpTextures() {
|
|
SCOPED_TRACE();
|
|
mTextureIds.push_back(GLUtils::loadTexture("texture/fish_dark.png"));
|
|
mTextureIds.push_back(GLUtils::loadTexture("texture/background.png"));
|
|
mTextureIds.push_back(GLUtils::loadTexture("texture/water1.png"));
|
|
mTextureIds.push_back(GLUtils::loadTexture("texture/water2.png"));
|
|
return true;
|
|
}
|
|
|
|
bool FlockingScene::setUpMeshes() {
|
|
SCOPED_TRACE();
|
|
mMeshes.push_back(GLUtils::loadMesh("mesh/fish.cob"));
|
|
mMeshes.push_back(GLUtils::loadMesh("mesh/plane.cob"));
|
|
return true;
|
|
}
|
|
|
|
bool FlockingScene::tearDown() {
|
|
SCOPED_TRACE();
|
|
for (int i = 0; i < NUM_BOIDS; i++) {
|
|
delete mBoids[i];
|
|
}
|
|
delete mMainProgram;
|
|
delete mWaterProgram;
|
|
return Scene::tearDown();
|
|
}
|
|
|
|
bool FlockingScene::updateSceneGraphs(int frame) {
|
|
const float MAIN_SCALE = 1.25f; // Scale up as the camera is far away.
|
|
const float LIMIT_X = mBoardWidth / 2.0f;
|
|
const float LIMIT_Y = mBoardHeight / 2.0f;
|
|
|
|
ProgramNode* mainSceneGraph = new ProgramNode(*mMainProgram);
|
|
mSceneGraphs.push_back(mainSceneGraph);
|
|
// Bottom
|
|
Matrix* transformMatrix = Matrix::newScale(MAIN_SCALE * mDisplayRatio, MAIN_SCALE, 0.0f);
|
|
TransformationNode* transformNode = new TransformationNode(transformMatrix);
|
|
mainSceneGraph->addChild(transformNode);
|
|
MeshNode* meshNode = new PerspectiveMeshNode(mMeshes[1], mTextureIds[1]);
|
|
transformNode->addChild(meshNode);
|
|
// Boids
|
|
const float MARGIN = 30.0f; // So the fish dont disappear and appear at the edges.
|
|
for (int i = 0; i < NUM_BOIDS; i++) {
|
|
Boid* b = mBoids[i];
|
|
b->flock((const Boid**) &mBoids, NUM_BOIDS, i, LIMIT_X + MARGIN, LIMIT_Y + MARGIN);
|
|
Vector2D* pos = &(b->mPosition);
|
|
Vector2D* vel = &(b->mVelocity);
|
|
|
|
// Normalize to (-1,1)
|
|
float x = pos->mX / (LIMIT_X * BOID_SCALE) * mDisplayRatio;
|
|
float y = pos->mY / (LIMIT_Y * BOID_SCALE);
|
|
|
|
const float SCALE = BOID_SCALE * MAIN_SCALE;
|
|
transformMatrix = Matrix::newScale(SCALE, SCALE, SCALE);
|
|
transformMatrix->translate(x, y, 1.0f);
|
|
transformMatrix->rotate(atan2(vel->mY, vel->mX) + M_PI, 0, 0, 1);
|
|
transformNode = new TransformationNode(transformMatrix);
|
|
mainSceneGraph->addChild(transformNode);
|
|
meshNode = new PerspectiveMeshNode(mMeshes[0], mTextureIds[0]);
|
|
transformNode->addChild(meshNode);
|
|
}
|
|
ProgramNode* waterSceneGraph = new ProgramNode(*mWaterProgram);
|
|
mSceneGraphs.push_back(waterSceneGraph);
|
|
// Top
|
|
transformMatrix = Matrix::newScale(MAIN_SCALE * mDisplayRatio, MAIN_SCALE, 1.0f);
|
|
transformMatrix->translate(0, 0, 0.1f);
|
|
transformNode = new TransformationNode(transformMatrix);
|
|
waterSceneGraph->addChild(transformNode);
|
|
meshNode = new WaterMeshNode(mMeshes[1], frame, mTextureIds[2], mTextureIds[3]);
|
|
transformNode->addChild(meshNode);
|
|
return true;
|
|
}
|
|
|
|
bool FlockingScene::draw() {
|
|
SCOPED_TRACE();
|
|
drawSceneGraph(0); // Draw fish and pond bottom
|
|
// Use blending.
|
|
glEnable (GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
drawSceneGraph(1); // Draw water
|
|
glDisable(GL_BLEND);
|
|
return true;
|
|
}
|