blob: c25d404b9cb5234c62b853116713ad7150d48a4e [file] [log] [blame]
/* Copyright 2017 Google Inc. All rights reserved.
*
* 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.
*/
#ifndef TREASUREHUNT_APP_SRC_MAIN_JNI_TREASUREHUNTRENDERER_H_ // NOLINT
#define TREASUREHUNT_APP_SRC_MAIN_JNI_TREASUREHUNTRENDERER_H_ // NOLINT
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <jni.h>
#include <memory>
#include <string>
#include <thread> // NOLINT
#include <vector>
#include "vr/gvr/capi/include/gvr.h"
#include "vr/gvr/capi/include/gvr_audio.h"
#include "vr/gvr/capi/include/gvr_controller.h"
#include "vr/gvr/capi/include/gvr_types.h"
#include "world_layout_data.h" // NOLINT
class TreasureHuntRenderer {
public:
/**
* Create a TreasureHuntRenderer using a given |gvr_context|.
*
* @param gvr_api The (non-owned) gvr_context.
* @param gvr_audio_api The (owned) gvr::AudioApi context.
*/
TreasureHuntRenderer(gvr_context* gvr_context,
std::unique_ptr<gvr::AudioApi> gvr_audio_api);
/**
* Destructor.
*/
~TreasureHuntRenderer();
/**
* Initialize any GL-related objects. This should be called on the rendering
* thread with a valid GL context.
*/
void InitializeGl();
/**
* Draw the TreasureHunt scene. This should be called on the rendering thread.
*/
void DrawFrame();
/**
* Hide the cube if it's being targeted.
*/
void OnTriggerEvent();
/**
* Pause head tracking.
*/
void OnPause();
/**
* Resume head tracking, refreshing viewer parameters if necessary.
*/
void OnResume();
private:
int CreateTexture(int width, int height, int textureFormat, int textureType);
/*
* Prepares the GvrApi framebuffer for rendering, resizing if needed.
*/
void PrepareFramebuffer();
/**
* Converts a raw text file, saved as a resource, into an OpenGL ES shader.
*
* @param type The type of shader we will be creating.
* @param resId The resource ID of the raw text file.
* @return The shader object handler.
*/
int LoadGLShader(int type, const char** shadercode);
enum ViewType {
kLeftView,
kRightView,
kMultiview
};
/**
* Draws all world-space objects for the given view type.
*
* @param view Specifies which view we are rendering.
*/
void DrawWorld(ViewType view);
/**
* Draws the reticle. The reticle is positioned using viewport parameters,
* so no data about its eye-space position is needed here.
*/
void DrawReticle();
/**
* Draw the cube.
*
* We've set all of our transformation matrices. Now we simply pass them
* into the shader.
*
* @param view Specifies which eye we are rendering: left, right, or both.
*/
void DrawCube(ViewType view);
/**
* Draw the floor.
*
* This feeds in data for the floor into the shader. Note that this doesn't
* feed in data about position of the light, so if we rewrite our code to
* draw the floor first, the lighting might look strange.
*
* @param view Specifies which eye we are rendering: left, right, or both.
*/
void DrawFloor(ViewType view);
/**
* Find a new random position for the object.
*
* We'll rotate it around the Y-axis so it's out of sight, and then up or
* down by a little bit.
*/
void HideObject();
/**
* Update the position of the reticle based on controller data.
* In Cardboard mode, this function simply sets the position to the center
* of the view.
*/
void UpdateReticlePosition();
/**
* Check if user is pointing or looking at the object by calculating whether
* the angle between the user's gaze or controller orientation and the vector
* pointing towards the object is lower than some threshold.
*
* @return true if the user is pointing at the object.
*/
bool IsPointingAtObject();
/**
* Preloads the cube sound sample and starts the spatialized playback at the
* current cube location. This method is executed from a separate thread to
* avoid any delay during construction and app initialization.
*/
void LoadAndPlayCubeSound();
/**
* Process the controller input.
*
* The controller state is updated with the latest touch pad, button clicking
* information, connection state and status of the controller. A log message
* is reported if the controller status or connection state changes. A click
* event is triggered if a click on app/click button is detected.
*/
void ProcessControllerInput();
/*
* Resume the controller api if needed.
*
* If the viewer type is cardboard, set the controller api pointer to null.
* If the viewer type is daydream, initialize the controller api as needed and
* resume.
*/
void ResumeControllerApiAsNeeded();
std::unique_ptr<gvr::GvrApi> gvr_api_;
std::unique_ptr<gvr::AudioApi> gvr_audio_api_;
std::unique_ptr<gvr::BufferViewportList> viewport_list_;
std::unique_ptr<gvr::SwapChain> swapchain_;
gvr::BufferViewport viewport_left_;
gvr::BufferViewport viewport_right_;
std::vector<float> lightpos_;
WorldLayoutData world_layout_data_;
const float* floor_vertices_;
const float* cube_vertices_;
const float* cube_colors_;
const float* cube_found_colors_;
const float* cube_normals_;
const float* reticle_vertices_;
int cube_program_;
int floor_program_;
int reticle_program_;
int cube_position_param_;
int cube_normal_param_;
int cube_color_param_;
int cube_model_param_;
int cube_modelview_param_;
int cube_modelview_projection_param_;
int cube_light_pos_param_;
int floor_position_param_;
int floor_normal_param_;
int floor_color_param_;
int floor_model_param_;
int floor_modelview_param_;
int floor_modelview_projection_param_;
int floor_light_pos_param_;
int reticle_position_param_;
int reticle_modelview_projection_param_;
const gvr::Sizei reticle_render_size_;
const std::array<float, 4> light_pos_world_space_;
gvr::Mat4f head_view_;
gvr::Mat4f model_cube_;
gvr::Mat4f camera_;
gvr::Mat4f view_;
gvr::Mat4f model_floor_;
gvr::Mat4f model_reticle_;
gvr::Mat4f modelview_reticle_;
gvr::Sizei render_size_;
// View-dependent values. These are stored in length two arrays to allow
// syncing with uniforms consumed by the multiview vertex shader. For
// simplicity, we stash valid values in both elements (left, right) of these
// arrays even when multiview is disabled.
std::array<float, 3> light_pos_eye_space_[2];
gvr::Mat4f modelview_projection_cube_[2];
gvr::Mat4f modelview_projection_floor_[2];
gvr::Mat4f modelview_cube_[2];
gvr::Mat4f modelview_floor_[2];
int score_;
float object_distance_;
float reticle_distance_;
bool multiview_enabled_;
gvr::AudioSourceId audio_source_id_;
gvr::AudioSourceId success_source_id_;
std::thread audio_initialization_thread_;
// Controller API entry point.
std::unique_ptr<gvr::ControllerApi> gvr_controller_api_;
// The latest controller state (updated once per frame).
gvr::ControllerState gvr_controller_state_;
gvr::ViewerType gvr_viewer_type_;
};
#endif // TREASUREHUNT_APP_SRC_MAIN_JNI_TREASUREHUNTRENDERER_H_ // NOLINT