mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-17 18:36:43 +02:00
#23 GoogleVR support; minor fixes
This commit is contained in:
11
src/cache.h
11
src/cache.h
@@ -775,13 +775,10 @@ struct WaterCache {
|
||||
|
||||
// render mirror reflection
|
||||
Core::setTarget(reflect, CLEAR_ALL);
|
||||
Core::validateRenderState();
|
||||
Camera *camera = (Camera*)game->getCamera();
|
||||
game->setupBinding();
|
||||
|
||||
mat4 mProj = Core::mProj;
|
||||
mat4 mView = Core::mView;
|
||||
mat4 mViewInv = Core::mViewInv;
|
||||
|
||||
// merge visible rooms for all items
|
||||
int roomsList[256];
|
||||
int roomsCount = 0;
|
||||
@@ -835,12 +832,8 @@ struct WaterCache {
|
||||
Core::invalidateTarget(false, true);
|
||||
game->setClipParams(1.0f, NO_CLIP_PLANE);
|
||||
|
||||
Core::mProj = mProj;
|
||||
Core::mView = mView;
|
||||
Core::mViewInv = mViewInv;
|
||||
|
||||
camera->reflectPlane = NULL;
|
||||
camera->setup(false);
|
||||
camera->setup(true);
|
||||
}
|
||||
|
||||
void render() {
|
||||
|
116
src/camera.h
116
src/camera.h
@@ -68,9 +68,9 @@ struct Camera : ICamera {
|
||||
return eye.room;
|
||||
}
|
||||
|
||||
void updateListener() {
|
||||
void updateListener(const mat4 &matrix) {
|
||||
Sound::flipped = level->state.flags.flipped;
|
||||
Sound::listener[cameraIndex].matrix = mViewInv;
|
||||
Sound::listener[cameraIndex].matrix = matrix;
|
||||
if (cameraIndex == 0) { // reverb effect only for main player
|
||||
TR::Room &r = level->rooms[getRoomIndex()];
|
||||
int h = (r.info.yBottom - r.info.yTop) / 1024;
|
||||
@@ -148,6 +148,9 @@ struct Camera : ICamera {
|
||||
fpHead.pos -= joint.rot * vec3(0, 48, -24);
|
||||
}
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
fpHead.rot = quat(vec3(1, 0, 0), PI);
|
||||
|
||||
mViewInv.identity();
|
||||
mViewInv.setRot(fpHead.rot);
|
||||
mViewInv.setPos(fpHead.pos);
|
||||
@@ -155,7 +158,6 @@ struct Camera : ICamera {
|
||||
eye.pos = mViewInv.getPos();
|
||||
eye.room = owner->getRoomIndex();
|
||||
|
||||
level->getSector(eye.room, fpHead.pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -302,8 +304,6 @@ struct Camera : ICamera {
|
||||
|
||||
if (eye.pos.y > floor) eye.pos.y = floor;
|
||||
if (eye.pos.y < ceiling) eye.pos.y = ceiling;
|
||||
|
||||
level->getSector(eye.room, eye.pos);
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
@@ -350,8 +350,6 @@ struct Camera : ICamera {
|
||||
mViewInv = mat4(eye.pos, target.pos, vec3(0, -1, 0));
|
||||
} else
|
||||
updateFirstPerson();
|
||||
|
||||
level->getSector(eye.room, eye.pos);
|
||||
} else {
|
||||
Controller *lookAt = NULL;
|
||||
|
||||
@@ -371,43 +369,47 @@ struct Camera : ICamera {
|
||||
owner->lookAt(NULL);
|
||||
}
|
||||
|
||||
vec3 advAngleOld = advAngle;
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) {
|
||||
advAngle = vec3(0.0f);
|
||||
} else {
|
||||
vec3 advAngleOld = advAngle;
|
||||
|
||||
if (Input::down[ikMouseL]) {
|
||||
vec2 delta = Input::mouse.pos - Input::mouse.start.L;
|
||||
advAngle.x -= delta.y * 0.01f;
|
||||
advAngle.y += delta.x * 0.01f;
|
||||
advAngle.y = clamp(advAngle.y, -PI, PI);
|
||||
Input::mouse.start.L = Input::mouse.pos;
|
||||
}
|
||||
|
||||
// TODO: use player index
|
||||
if (Input::state[cameraIndex][cLook]) {
|
||||
float d = 2.0f * Core::deltaTime;
|
||||
|
||||
advAngle.x += Input::joy[cameraIndex].L.y * d;
|
||||
advAngle.y += Input::joy[cameraIndex].L.x * d;
|
||||
|
||||
if (Input::state[cameraIndex][cUp]) advAngle.x -= d;
|
||||
if (Input::state[cameraIndex][cDown]) advAngle.x += d;
|
||||
if (Input::state[cameraIndex][cLeft]) advAngle.y += d;
|
||||
if (Input::state[cameraIndex][cRight]) advAngle.y -= d;
|
||||
}
|
||||
|
||||
if (advAngleOld == advAngle) {
|
||||
if (advTimer > 0.0f) {
|
||||
advTimer = max(0.0f, advTimer - Core::deltaTime);
|
||||
if (Input::down[ikMouseL]) {
|
||||
vec2 delta = Input::mouse.pos - Input::mouse.start.L;
|
||||
advAngle.x -= delta.y * 0.01f;
|
||||
advAngle.y += delta.x * 0.01f;
|
||||
advAngle.y = clamp(advAngle.y, -PI, PI);
|
||||
Input::mouse.start.L = Input::mouse.pos;
|
||||
}
|
||||
} else
|
||||
advTimer = -1.0f;
|
||||
|
||||
if (owner->velocity != 0.0f && advTimer < 0.0f && !Input::down[ikMouseL])
|
||||
advTimer = -advTimer;
|
||||
// TODO: use player index
|
||||
if (Input::state[cameraIndex][cLook]) {
|
||||
float d = 2.0f * Core::deltaTime;
|
||||
|
||||
if (advTimer == 0.0f && advAngle != 0.0f) {
|
||||
float t = 10.0f * Core::deltaTime;
|
||||
advAngle.x = lerp(clampAngle(advAngle.x), 0.0f, t);
|
||||
advAngle.y = lerp(clampAngle(advAngle.y), 0.0f, t);
|
||||
advAngle.x += Input::joy[cameraIndex].L.y * d;
|
||||
advAngle.y += Input::joy[cameraIndex].L.x * d;
|
||||
|
||||
if (Input::state[cameraIndex][cUp]) advAngle.x -= d;
|
||||
if (Input::state[cameraIndex][cDown]) advAngle.x += d;
|
||||
if (Input::state[cameraIndex][cLeft]) advAngle.y += d;
|
||||
if (Input::state[cameraIndex][cRight]) advAngle.y -= d;
|
||||
}
|
||||
|
||||
if (advAngleOld == advAngle) {
|
||||
if (advTimer > 0.0f) {
|
||||
advTimer = max(0.0f, advTimer - Core::deltaTime);
|
||||
}
|
||||
} else
|
||||
advTimer = -1.0f;
|
||||
|
||||
if (owner->velocity != 0.0f && advTimer < 0.0f && !Input::down[ikMouseL])
|
||||
advTimer = -advTimer;
|
||||
|
||||
if (advTimer == 0.0f && advAngle != 0.0f) {
|
||||
float t = 10.0f * Core::deltaTime;
|
||||
advAngle.x = lerp(clampAngle(advAngle.x), 0.0f, t);
|
||||
advAngle.y = lerp(clampAngle(advAngle.y), 0.0f, t);
|
||||
}
|
||||
}
|
||||
|
||||
targetAngle = owner->angle + advAngle;
|
||||
@@ -466,13 +468,15 @@ struct Camera : ICamera {
|
||||
mViewInv = mat4(eye.pos, target.pos, vec3(0, -1, 0));
|
||||
} else
|
||||
updateFirstPerson();
|
||||
|
||||
if (Core::settings.detail.vr) {
|
||||
mViewInv = mViewInv * Input::hmd.eye[0];
|
||||
}
|
||||
}
|
||||
updateListener();
|
||||
|
||||
|
||||
level->getSector(eye.room, eye.pos);
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
updateListener(mViewInv * Input::hmd.head);
|
||||
else
|
||||
updateListener(mViewInv);
|
||||
|
||||
smooth = true;
|
||||
}
|
||||
|
||||
@@ -480,30 +484,34 @@ struct Camera : ICamera {
|
||||
if (calcMatrices) {
|
||||
Core::mViewInv = mViewInv;
|
||||
|
||||
if (Core::settings.detail.vr)
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
Core::mViewInv = Core::mViewInv * Input::hmd.eye[Core::eye == -1.0f ? 0 : 1];
|
||||
|
||||
if (shake > 0.0f)
|
||||
Core::mViewInv.setPos(Core::mViewInv.getPos() + vec3(0.0f, sinf(shake * PI * 7) * shake * 48.0f, 0.0f));
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_ON)
|
||||
Core::mViewInv.setPos(Core::mViewInv.getPos() + Core::mViewInv.right().xyz() * (Core::eye * (firstPerson ? 8.0f : 32.0f) ));
|
||||
|
||||
if (reflectPlane) {
|
||||
Core::mViewInv = mat4(*reflectPlane) * Core::mViewInv;
|
||||
Core::mViewInv.scale(vec3(1.0f, -1.0f, 1.0f));
|
||||
}
|
||||
|
||||
Core::mView = Core::mViewInv.inverseOrtho();
|
||||
if (shake > 0.0f)
|
||||
Core::mView.translate(vec3(0.0f, sinf(shake * PI * 7) * shake * 48.0f, 0.0f));
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_ON)
|
||||
Core::mView.translate(Core::mViewInv.right().xyz() * (-Core::eye * (firstPerson ? 8.0f : 32.0f) ));
|
||||
|
||||
if (Core::settings.detail.vr)
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
Core::mProj = Input::hmd.proj[Core::eye == -1.0f ? 0 : 1];
|
||||
else
|
||||
Core::mProj = mat4(fov, aspect, znear, zfar);
|
||||
}
|
||||
|
||||
Core::setViewProj(Core::mView, Core::mProj);
|
||||
Core::viewPos = Core::mViewInv.getPos();
|
||||
|
||||
Core::viewPos = Core::mViewInv.offset().xyz();
|
||||
// update room for eye (with HMD offset)
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
level->getSector(eye.room, Core::viewPos);
|
||||
|
||||
frustum->pos = Core::viewPos;
|
||||
frustum->calcPlanes(Core::mViewProj);
|
||||
|
45
src/core.h
45
src/core.h
@@ -49,6 +49,8 @@
|
||||
#define glProgramBinary glProgramBinaryOES
|
||||
|
||||
#define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES
|
||||
|
||||
extern void osToggleVR(bool enable);
|
||||
#elif __RPI__
|
||||
#define MOBILE
|
||||
#include <GLES2/gl2.h>
|
||||
@@ -277,7 +279,7 @@ struct KeySet {
|
||||
namespace Core {
|
||||
float deltaTime;
|
||||
int lastTime;
|
||||
int width, height;
|
||||
int x, y, width, height;
|
||||
|
||||
struct Support {
|
||||
int maxVectors;
|
||||
@@ -298,12 +300,12 @@ namespace Core {
|
||||
#endif
|
||||
} support;
|
||||
|
||||
#define SETTINGS_VERSION 1
|
||||
#define SETTINGS_VERSION 2
|
||||
#define SETTINGS_READING 0xFF
|
||||
|
||||
struct Settings {
|
||||
enum Quality { LOW, MEDIUM, HIGH };
|
||||
enum Stereo { STEREO_OFF, STEREO_ON, STEREO_SPLIT };
|
||||
enum Stereo { STEREO_OFF, STEREO_ON, STEREO_SPLIT, STEREO_VR };
|
||||
|
||||
uint8 version;
|
||||
|
||||
@@ -319,7 +321,6 @@ namespace Core {
|
||||
};
|
||||
uint8 vsync;
|
||||
uint8 stereo;
|
||||
uint8 vr;
|
||||
void setFilter(Quality value) {
|
||||
if (value > MEDIUM && !(support.maxAniso > 1))
|
||||
value = MEDIUM;
|
||||
@@ -674,7 +675,7 @@ namespace Core {
|
||||
} reqTarget;
|
||||
|
||||
struct Stats {
|
||||
int dips, tris, frame, fps, fpsTime;
|
||||
int dips, tris, rt, frame, fps, fpsTime;
|
||||
#ifdef PROFILE
|
||||
int tFrame;
|
||||
#endif
|
||||
@@ -682,12 +683,12 @@ namespace Core {
|
||||
Stats() : frame(0), fps(0), fpsTime(0) {}
|
||||
|
||||
void start() {
|
||||
dips = tris = 0;
|
||||
dips = tris = rt = 0;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
if (fpsTime < Core::getTime()) {
|
||||
LOG("FPS: %d DIP: %d TRI: %d\n", fps, dips, tris);
|
||||
LOG("FPS: %d DIP: %d TRI: %d RT: %d\n", fps, dips, tris, rt);
|
||||
#ifdef PROFILE
|
||||
LOG("frame time: %d mcs\n", tFrame / 1000);
|
||||
#endif
|
||||
@@ -751,6 +752,7 @@ namespace Core {
|
||||
}
|
||||
|
||||
void init() {
|
||||
x = y = 0;
|
||||
#ifdef USE_INFLATE
|
||||
tinf_init();
|
||||
#endif
|
||||
@@ -941,6 +943,10 @@ namespace Core {
|
||||
support.colorHalf ? "full" : (support.texHalf ? (support.texHalfLinear ? "linear" : "nearest") : "false"));
|
||||
LOG("\n");
|
||||
|
||||
#ifndef _PSP
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
#endif
|
||||
|
||||
#ifdef FFP
|
||||
#ifdef _PSP
|
||||
Core::width = 480;
|
||||
@@ -1116,6 +1122,9 @@ namespace Core {
|
||||
|
||||
eyeTex[0] = eyeTex[1] = NULL;
|
||||
|
||||
memset(&active, 0, sizeof(active));
|
||||
renderState = 0;
|
||||
|
||||
resetTime();
|
||||
}
|
||||
|
||||
@@ -1194,6 +1203,7 @@ namespace Core {
|
||||
sceGuDrawBufferList(GU_PSM_5650, target->offset, target->width);
|
||||
*/
|
||||
#else
|
||||
Core::stats.rt++;
|
||||
if (!target) { // may be a null
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
|
||||
} else {
|
||||
@@ -1223,6 +1233,7 @@ namespace Core {
|
||||
sceGuViewport(2048 + int(viewport.x), 2048 + int(viewport.y), int(viewport.z), int(viewport.w));
|
||||
#else
|
||||
glViewport(int(viewport.x), int(viewport.y), int(viewport.z), int(viewport.w));
|
||||
glScissor(int(viewport.x), int(viewport.y), int(viewport.z), int(viewport.w));
|
||||
#endif
|
||||
}
|
||||
renderState &= ~RS_VIEWPORT;
|
||||
@@ -1468,16 +1479,30 @@ namespace Core {
|
||||
#endif
|
||||
}
|
||||
|
||||
void beginFrame() {
|
||||
//memset(&active, 0, sizeof(active));
|
||||
setViewport(0, 0, Core::width, Core::height);
|
||||
void reset() {
|
||||
#ifndef _PSP
|
||||
if (Core::support.VAO)
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
#endif
|
||||
|
||||
memset(&active, 0, sizeof(active));
|
||||
renderState = 0;
|
||||
|
||||
setViewport(Core::x, Core::y, Core::width, Core::height);
|
||||
viewportDef = viewport;
|
||||
|
||||
setCulling(cfFront);
|
||||
setBlending(bmAlpha);
|
||||
setDepthTest(true);
|
||||
setDepthWrite(true);
|
||||
setColorWrite(true, true, true, true);
|
||||
validateRenderState();
|
||||
}
|
||||
|
||||
void beginFrame() {
|
||||
Core::stats.start();
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,9 @@
|
||||
#define MAX_TRIGGER_COMMANDS 32
|
||||
#define MAX_MESHES 512
|
||||
|
||||
// Lara's height in units / height in meters
|
||||
#define ONE_METER (768.0f / 1.8f)
|
||||
|
||||
#define TR1_TYPES_START 0
|
||||
#define TR2_TYPES_START 1000
|
||||
#define TR3_TYPES_START 2000
|
||||
|
34
src/game.h
34
src/game.h
@@ -39,6 +39,11 @@ void loadSettings(Stream *stream, void *userData) {
|
||||
delete stream;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
osToggleVR(true);
|
||||
#endif
|
||||
|
||||
Core::settings.version = SETTINGS_VERSION;
|
||||
shaderCache = new ShaderCache();
|
||||
Game::startLevel((Stream*)userData);
|
||||
@@ -162,22 +167,37 @@ namespace Game {
|
||||
return true;
|
||||
}
|
||||
|
||||
void render() {
|
||||
if (Core::settings.version == SETTINGS_READING)
|
||||
return;
|
||||
void frameBegin() {
|
||||
if (Core::settings.version == SETTINGS_READING) return;
|
||||
Core::reset();
|
||||
Core::beginFrame();
|
||||
level->renderPrepare();
|
||||
}
|
||||
|
||||
void frameRender() {
|
||||
if (Core::settings.version == SETTINGS_READING) return;
|
||||
|
||||
PROFILE_MARKER("RENDER");
|
||||
PROFILE_TIMING(Core::stats.tFrame);
|
||||
Core::beginFrame();
|
||||
level->render();
|
||||
UI::renderTouch();
|
||||
|
||||
level->render();
|
||||
#ifdef _DEBUG
|
||||
level->renderDebug();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void frameEnd() {
|
||||
if (Core::settings.version == SETTINGS_READING) return;
|
||||
|
||||
UI::renderTouch();
|
||||
Core::endFrame();
|
||||
}
|
||||
|
||||
void render() {
|
||||
frameBegin();
|
||||
frameRender();
|
||||
frameEnd();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -32,6 +32,7 @@ namespace Input {
|
||||
} touch[6];
|
||||
|
||||
struct HMD {
|
||||
mat4 head;
|
||||
mat4 eye[2];
|
||||
mat4 proj[2];
|
||||
mat4 controllers[2];
|
||||
@@ -46,7 +47,10 @@ namespace Input {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
//
|
||||
eye[0].identity();
|
||||
eye[1].identity();
|
||||
proj[0].identity();
|
||||
proj[1].identity();
|
||||
}
|
||||
} hmd;
|
||||
|
||||
|
155
src/inventory.h
155
src/inventory.h
@@ -129,7 +129,13 @@ static const OptionItem optDetail[] = {
|
||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_VSYNC, SETTINGS( detail.vsync ), STR_OFF, 0, 1 ),
|
||||
#endif
|
||||
#ifndef _PSP
|
||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_STEREO, SETTINGS( detail.stereo ), STR_OFF, 0, 2 ),
|
||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_STEREO, SETTINGS( detail.stereo ), STR_OFF, 0,
|
||||
#if /*defined(_WIN32) ||*/ defined(ANDROID)
|
||||
3 /* with VR option */
|
||||
#else
|
||||
2 /* without VR support */
|
||||
#endif
|
||||
),
|
||||
#endif
|
||||
OptionItem( ),
|
||||
OptionItem( OptionItem::TYPE_BUTTON, STR_APPLY ),
|
||||
@@ -218,6 +224,8 @@ struct Inventory {
|
||||
TR::LevelID nextLevel; // toggle result
|
||||
ControlKey lastKey;
|
||||
|
||||
mat4 head;
|
||||
|
||||
int slot;
|
||||
Core::Settings settings;
|
||||
|
||||
@@ -423,14 +431,11 @@ struct Inventory {
|
||||
|
||||
Core::setBasis(joints, m.mCount);
|
||||
|
||||
Core::setBlending(bmNone);
|
||||
Core::setBlending(bmAlpha);
|
||||
mesh->transparent = 0;
|
||||
mesh->renderModel(desc.model);
|
||||
|
||||
Core::setBlending(bmAlpha);
|
||||
mesh->transparent = 1;
|
||||
mesh->renderModel(desc.model);
|
||||
|
||||
Core::setBlending(bmAdd);
|
||||
Core::setDepthWrite(false);
|
||||
mesh->transparent = 2;
|
||||
@@ -675,6 +680,8 @@ struct Inventory {
|
||||
|
||||
index = targetIndex = pageItemIndex[page];
|
||||
|
||||
head = Input::hmd.head.inverseOrtho();
|
||||
|
||||
//if (type == TR::Entity::INV_PASSPORT) // toggle after death
|
||||
// chooseItem();
|
||||
}
|
||||
@@ -1090,6 +1097,9 @@ struct Inventory {
|
||||
}
|
||||
|
||||
void prepareBackground() {
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
return;
|
||||
|
||||
#ifdef _PSP
|
||||
return;
|
||||
#endif
|
||||
@@ -1206,9 +1216,7 @@ struct Inventory {
|
||||
y = options[i].render(x, y, width, slot == i, &stg);
|
||||
}
|
||||
|
||||
void renderItemText(Item *item) {
|
||||
float eye = UI::width * Core::eye * 0.01f;
|
||||
|
||||
void renderItemText(float eye, Item *item) {
|
||||
if (item->type == TR::Entity::INV_PASSPORT && phaseChoose == 1.0f) {
|
||||
//
|
||||
} else
|
||||
@@ -1257,6 +1265,8 @@ struct Inventory {
|
||||
if (phaseSelect < 1.0f)
|
||||
angle = lerpAngle(angle, getAngle(targetIndex, count), hermite(phaseSelect));
|
||||
|
||||
Basis basis = Basis(quat(vec3(1, 0, 0), ringTilt), vec3(0));
|
||||
|
||||
int itemIndex = 0;
|
||||
for (int i = 0; i < itemsCount; i++) {
|
||||
Item *item = items[i];
|
||||
@@ -1266,7 +1276,6 @@ struct Inventory {
|
||||
|
||||
float a = getAngle(itemIndex, count) - angle - collapseAngle;
|
||||
float ia = item->angle;
|
||||
float ra = ringTilt;
|
||||
float rd = radius;
|
||||
float rh = ringHeight;
|
||||
|
||||
@@ -1276,10 +1285,9 @@ struct Inventory {
|
||||
rd += 296 * phaseChoose;
|
||||
}
|
||||
|
||||
Basis basis = Basis(quat(vec3(1, 0, 0), ra), vec3(0.0f));
|
||||
basis = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item->desc.page * INVENTORY_HEIGHT - rh, 0));
|
||||
Basis b = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item->desc.page * INVENTORY_HEIGHT - rh, 0));
|
||||
|
||||
item->render(game, basis);
|
||||
item->render(game, b);
|
||||
|
||||
itemIndex++;
|
||||
}
|
||||
@@ -1387,23 +1395,32 @@ struct Inventory {
|
||||
#endif
|
||||
Index indices[6] = { 0, 1, 2, 0, 2, 3 };
|
||||
Vertex vertices[4];
|
||||
vertices[ 0].coord = short4(-32767, 32767, 0, 0);
|
||||
vertices[ 1].coord = short4( 32767, 32767, 0, 0);
|
||||
vertices[ 2].coord = short4( 32767, -32767, 0, 0);
|
||||
vertices[ 3].coord = short4(-32767, -32767, 0, 0);
|
||||
vertices[ 0].light =
|
||||
vertices[ 1].light =
|
||||
vertices[ 2].light =
|
||||
vertices[ 3].light = ubyte4(255, 255, 255, uint8(phaseRing * 255));
|
||||
vertices[ 0].texCoord = short4( 0, 32767, 0, 0);
|
||||
vertices[ 1].texCoord = short4(32767, 32767, 0, 0);
|
||||
vertices[ 2].texCoord = short4(32767, 0, 0, 0);
|
||||
vertices[ 3].texCoord = short4( 0, 0, 0, 0);
|
||||
vertices[0].coord = short4(-32767, 32767, 0, 0);
|
||||
vertices[1].coord = short4( 32767, 32767, 0, 0);
|
||||
vertices[2].coord = short4( 32767, -32767, 0, 0);
|
||||
vertices[3].coord = short4(-32767, -32767, 0, 0);
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) {
|
||||
vertices[0].light =
|
||||
vertices[1].light =
|
||||
vertices[2].light =
|
||||
vertices[3].light = ubyte4(0, 0, 0, uint8(phaseRing * 255));
|
||||
} else {
|
||||
vertices[0].light =
|
||||
vertices[1].light =
|
||||
vertices[2].light =
|
||||
vertices[3].light = ubyte4(255, 255, 255, uint8(phaseRing * 255));
|
||||
}
|
||||
vertices[0].texCoord = short4( 0, 32767, 0, 0);
|
||||
vertices[1].texCoord = short4(32767, 32767, 0, 0);
|
||||
vertices[2].texCoord = short4(32767, 0, 0, 0);
|
||||
vertices[3].texCoord = short4( 0, 0, 0, 0);
|
||||
|
||||
game->setShader(Core::passFilter, Shader::DEFAULT, false, false);
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
Core::whiteTex->bind(sDiffuse); // black background
|
||||
else
|
||||
background[0]->bind(sDiffuse); // blured grayscale image
|
||||
|
||||
// blured grayscale image
|
||||
background[0]->bind(sDiffuse);
|
||||
Core::setBlending(phaseRing < 1.0f ? bmAlpha : bmNone);
|
||||
game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices));
|
||||
}
|
||||
@@ -1414,17 +1431,57 @@ struct Inventory {
|
||||
|
||||
Core::setDepthTest(false);
|
||||
|
||||
if (background[0]) {
|
||||
if (background[1])
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) {
|
||||
if (game->getLevel()->isTitle()) {
|
||||
if (background[0]) {
|
||||
renderTitleBG();
|
||||
}
|
||||
} else
|
||||
renderGameBG();
|
||||
else
|
||||
renderTitleBG();
|
||||
} else {
|
||||
if (background[0]) {
|
||||
if (background[1])
|
||||
renderGameBG();
|
||||
else
|
||||
renderTitleBG();
|
||||
}
|
||||
}
|
||||
|
||||
Core::setBlending(bmAlpha);
|
||||
Core::setDepthTest(true);
|
||||
}
|
||||
|
||||
void setupCamera(float aspect, bool ui = false) {
|
||||
vec3 pos = vec3(0, 0, -1286);
|
||||
|
||||
if (ui) {
|
||||
pos.x += UI::width * 0.5f;
|
||||
pos.y += UI::height * 0.5f;
|
||||
pos.z += 1024.0f;
|
||||
}
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
pos.z -= 256.0f;
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_ON)
|
||||
pos.x += Core::eye * 8.0f;
|
||||
|
||||
Core::mViewInv = mat4(pos, pos + vec3(0, 0, 1), vec3(0, -1, 0));
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
Core::mViewInv = Core::mViewInv * head * Input::hmd.eye[Core::eye == -1.0f ? 0 : 1];
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
Core::mProj = Input::hmd.proj[Core::eye == -1.0f ? 0 : 1];
|
||||
else
|
||||
Core::mProj = mat4(70.0f, aspect, 32.0f, 2048.0f);
|
||||
|
||||
Core::mView = Core::mViewInv.inverseOrtho();
|
||||
Core::viewPos = Core::mViewInv.getPos();
|
||||
|
||||
Core::setViewProj(Core::mView, Core::mProj);
|
||||
}
|
||||
|
||||
void render(float aspect) {
|
||||
if (!isActive() && titleTimer == 0.0f)
|
||||
return;
|
||||
@@ -1437,17 +1494,7 @@ struct Inventory {
|
||||
|
||||
Core::mLightProj.identity();
|
||||
|
||||
Core::mView.identity();
|
||||
Core::mView.translate(vec3(-Core::eye * 8.0f, 0, -1286)); // y = -96 in title
|
||||
|
||||
Core::mView.up() *= -1.0f;
|
||||
Core::mView.dir() *= -1.0f;
|
||||
Core::mViewInv = Core::mView.inverseOrtho();
|
||||
|
||||
Core::mProj = mat4(70.0f, aspect, 32.0f, 2048.0f);
|
||||
Core::setViewProj(Core::mView, Core::mProj);
|
||||
|
||||
Core::viewPos = Core::mViewInv.getPos();
|
||||
setupCamera(aspect);
|
||||
|
||||
Core::whiteTex->bind(sShadow);
|
||||
game->setShader(Core::passCompose, Shader::ENTITY, false, false);
|
||||
@@ -1477,6 +1524,12 @@ struct Inventory {
|
||||
|
||||
float eye = UI::width * Core::eye * 0.01f;
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) {
|
||||
setupCamera(1.0f, true);
|
||||
Core::active.shader->setParam(uViewProj, Core::mViewProj);
|
||||
eye = 0.0f;
|
||||
}
|
||||
|
||||
if (!game->getLevel()->isTitle())
|
||||
UI::textOut(vec2(-eye, 32), pageTitle[page], UI::aCenter, UI::width);
|
||||
|
||||
@@ -1490,17 +1543,19 @@ struct Inventory {
|
||||
UI::textOut(vec2(-eye, 480 - 16), "]", UI::aRight, UI::width - 20);
|
||||
}
|
||||
|
||||
if (index == targetIndex)
|
||||
renderItemText(items[getGlobalIndex(page, index)]);
|
||||
if (index == targetIndex && page == targetPage)
|
||||
renderItemText(eye, items[getGlobalIndex(page, index)]);
|
||||
|
||||
// inventory controls help
|
||||
float dx = 32.0f - eye;
|
||||
char buf[64];
|
||||
sprintf(buf, STR[STR_HELP_SELECT], STR[STR_KEY_FIRST + ikEnter] );
|
||||
UI::textOut(vec2(dx, 480 - 64), buf, UI::aLeft, UI::width);
|
||||
if (chosen) {
|
||||
sprintf(buf, STR[STR_HELP_BACK], STR[STR_KEY_FIRST + Core::settings.controls[playerIndex].keys[ cInventory ].key] );
|
||||
UI::textOut(vec2(0, 480 - 64), buf, UI::aRight, UI::width - dx);
|
||||
if (page == targetPage) {
|
||||
float dx = 32.0f - eye;
|
||||
char buf[64];
|
||||
sprintf(buf, STR[STR_HELP_SELECT], STR[STR_KEY_FIRST + ikEnter] );
|
||||
UI::textOut(vec2(dx, 480 - 64), buf, UI::aLeft, UI::width);
|
||||
if (chosen) {
|
||||
sprintf(buf, STR[STR_HELP_BACK], STR[STR_KEY_FIRST + Core::settings.controls[playerIndex].keys[ cInventory ].key] );
|
||||
UI::textOut(vec2(0, 480 - 64), buf, UI::aRight, UI::width - dx);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
93
src/lara.h
93
src/lara.h
@@ -183,8 +183,8 @@ struct Lara : Character {
|
||||
|
||||
#define LARA_RGUN_JOINT 10
|
||||
#define LARA_LGUN_JOINT 13
|
||||
#define LARA_RGUN_OFFSET vec3( 10, -50, 0)
|
||||
#define LARA_LGUN_OFFSET vec3(-10, -50, 0)
|
||||
#define LARA_RGUN_OFFSET vec3(-10, -50, 0)
|
||||
#define LARA_LGUN_OFFSET vec3( 10, -50, 0)
|
||||
|
||||
enum {
|
||||
BODY_HIP = 0x0001,
|
||||
@@ -474,6 +474,7 @@ struct Lara : Character {
|
||||
|
||||
if (level->extra.braid > -1)
|
||||
braid = new Braid(this, (level->version & (TR::VER_TR2 | TR::VER_TR3)) ? vec3(-2.0f, -16.0f, -48.0f) : vec3(-4.0f, 24.0f, -48.0f));
|
||||
reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
||||
#ifdef _DEBUG
|
||||
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, STAND_ONWATER); // gym (pool)
|
||||
//reset(0, vec3(74858, 3072, 20795), 0); // level 1 (dart)
|
||||
@@ -941,7 +942,8 @@ struct Lara : Character {
|
||||
|
||||
shots++;
|
||||
|
||||
game->addMuzzleFlash(this, i ? LARA_LGUN_JOINT : LARA_RGUN_JOINT, i ? LARA_LGUN_OFFSET : LARA_RGUN_OFFSET, 1 + camera->cameraIndex);
|
||||
if (wpnCurrent != Weapon::SHOTGUN)
|
||||
game->addMuzzleFlash(this, i ? LARA_LGUN_JOINT : LARA_RGUN_JOINT, i ? LARA_LGUN_OFFSET : LARA_RGUN_OFFSET, 1 + camera->cameraIndex);
|
||||
|
||||
// TODO: use new trace code
|
||||
int joint = wpnCurrent == Weapon::SHOTGUN ? 8 : (i ? 11 : 8);
|
||||
@@ -1151,6 +1153,10 @@ struct Lara : Character {
|
||||
return vec3(atan2f(dir.y, sqrtf(dir.x * dir.x + dir.z * dir.z)) - angle.x, atan2f(dir.x, dir.z) - angle.y + PI, 0.0f);
|
||||
}
|
||||
|
||||
vec3 getAngleAbs(const vec3 &dir) {
|
||||
return vec3(-atan2f(dir.y, sqrtf(dir.x * dir.x + dir.z * dir.z)), -atan2f(dir.x, dir.z), 0.0f);
|
||||
}
|
||||
|
||||
virtual void lookAt(Controller *target) {
|
||||
if (health <= 0.0f)
|
||||
return;
|
||||
@@ -1439,10 +1445,8 @@ struct Lara : Character {
|
||||
flags.invisible = true;
|
||||
if (!environment)
|
||||
environment = new Texture(256, 256, Texture::RGBA, Texture::CUBEMAP | Texture::MIPMAPS);
|
||||
Core::beginFrame();
|
||||
game->renderEnvironment(getRoomIndex(), pos - vec3(0.0f, 384.0f, 0.0f), &environment, 0, Core::passCompose);
|
||||
environment->generateMipMap();
|
||||
Core::endFrame();
|
||||
flags.invisible = false;
|
||||
}
|
||||
|
||||
@@ -2637,28 +2641,51 @@ struct Lara : Character {
|
||||
|
||||
Input::Joystick &joy = Input::joy[Core::settings.controls[pid].joyIndex];
|
||||
|
||||
if ((state == STATE_STOP || state == STATE_SURF_TREAD || state == STATE_HANG) && fabsf(joy.L.x) < 0.5f && fabsf(joy.L.y) < 0.5f)
|
||||
return input;
|
||||
if (!((state == STATE_STOP || state == STATE_SURF_TREAD || state == STATE_HANG) && fabsf(joy.L.x) < 0.5f && fabsf(joy.L.y) < 0.5f)) {
|
||||
bool moving = state == STATE_RUN || state == STATE_WALK || state == STATE_BACK || state == STATE_FAST_BACK || state == STATE_SURF_SWIM || state == STATE_SURF_BACK || state == STATE_FORWARD_JUMP;
|
||||
|
||||
bool moving = state == STATE_RUN || state == STATE_WALK || state == STATE_BACK || state == STATE_FAST_BACK || state == STATE_SURF_SWIM || state == STATE_SURF_BACK || state == STATE_FORWARD_JUMP;
|
||||
if (!moving) {
|
||||
if (fabsf(joy.L.x) < fabsf(joy.L.y))
|
||||
joy.L.x = 0.0f;
|
||||
else
|
||||
joy.L.y = 0.0f;
|
||||
}
|
||||
|
||||
if (!moving) {
|
||||
if (fabsf(joy.L.x) < fabsf(joy.L.y))
|
||||
joy.L.x = 0.0f;
|
||||
else
|
||||
joy.L.y = 0.0f;
|
||||
if (joy.L.x != 0.0f) {
|
||||
input |= (joy.L.x < 0.0f) ? LEFT : RIGHT;
|
||||
if (moving || stand == STAND_UNDERWATER || stand == STAND_ONWATER)
|
||||
rotFactor.y = min(fabsf(joy.L.x) / 0.9f, 1.0f);
|
||||
}
|
||||
|
||||
if (joy.L.y != 0.0f) {
|
||||
input |= (joy.L.y < 0.0f) ? FORTH : BACK;
|
||||
if (stand == STAND_UNDERWATER)
|
||||
rotFactor.x = min(fabsf(joy.L.y) / 0.9f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (joy.L.x != 0.0f) {
|
||||
input |= (joy.L.x < 0.0f) ? LEFT : RIGHT;
|
||||
if (moving || stand == STAND_UNDERWATER || stand == STAND_ONWATER)
|
||||
rotFactor.y = min(fabsf(joy.L.x) / 0.9f, 1.0f);
|
||||
}
|
||||
// VR control
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR && camera->firstPerson && canFreeRotate()) {
|
||||
if (!(input & WALK)) {
|
||||
input &= ~(LEFT | RIGHT);
|
||||
}
|
||||
|
||||
if (joy.L.y != 0.0f) {
|
||||
input |= (joy.L.y < 0.0f) ? FORTH : BACK;
|
||||
if (stand == STAND_UNDERWATER)
|
||||
rotFactor.x = min(fabsf(joy.L.y) / 0.9f, 1.0f);
|
||||
vec3 ang = getAngleAbs(Input::hmd.head.dir().xyz());
|
||||
|
||||
angle.y = ang.y;
|
||||
// rotFactor = vec2(1.0f);
|
||||
// ang.y = shortAngle(angle.y, ang.y);
|
||||
// if (fabsf(ang.y) > 5 * DEG2RAD)
|
||||
// input |= ang.y < 0.0f ? LEFT : RIGHT;
|
||||
|
||||
if (stand == STAND_UNDERWATER) {
|
||||
input &= ~(FORTH | BACK);
|
||||
|
||||
angle.x = ang.x;
|
||||
// ang.x = shortAngle(angle.x, ang.x);
|
||||
// if (fabsf(ang.x) > 5 * DEG2RAD)
|
||||
// input |= ang.x < 0.0f ? FORTH : BACK;
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
@@ -2669,6 +2696,7 @@ struct Lara : Character {
|
||||
|| state == STATE_DEATH
|
||||
|| state == STATE_UNDERWATER_DEATH
|
||||
|| state == STATE_HANG
|
||||
|| state == STATE_HANG_UP
|
||||
|| state == STATE_HANG_LEFT
|
||||
|| state == STATE_HANG_RIGHT
|
||||
|| state == STATE_PUSH_BLOCK
|
||||
@@ -2682,9 +2710,12 @@ struct Lara : Character {
|
||||
|| state == STATE_SPECIAL
|
||||
|| state == STATE_REACH
|
||||
|| state == STATE_SWAN_DIVE
|
||||
|| state == STATE_FAST_DIVE
|
||||
|| state == STATE_HANDSTAND
|
||||
|| state == STATE_ROLL_1
|
||||
|| state == STATE_ROLL_2
|
||||
|| state == STATE_MIDAS_USE
|
||||
|| state == STATE_MIDAS_DEATH
|
||||
// make me sick!
|
||||
// || state == STATE_BACK_JUMP
|
||||
// || state == STATE_LEFT_JUMP
|
||||
@@ -2694,6 +2725,10 @@ struct Lara : Character {
|
||||
|| animation.index == ANIM_CLIMB_JUMP;
|
||||
}
|
||||
|
||||
bool canFreeRotate() {
|
||||
return !(useHeadAnimation() || state == STATE_SLIDE || state == STATE_SLIDE_BACK);
|
||||
}
|
||||
|
||||
virtual void doCustomCommand(int curFrame, int prevFrame) {
|
||||
switch (state) {
|
||||
case STATE_PICK_UP : {
|
||||
@@ -2765,7 +2800,7 @@ struct Lara : Character {
|
||||
else
|
||||
hit(Core::deltaTime * 150.0f);
|
||||
} else
|
||||
if (oxygen < LARA_MAX_OXYGEN)
|
||||
if (oxygen < LARA_MAX_OXYGEN && health > 0.0f)
|
||||
oxygen = min(LARA_MAX_OXYGEN, oxygen += Core::deltaTime * 10.0f);
|
||||
|
||||
usedKey = TR::Entity::LARA;
|
||||
@@ -2811,9 +2846,12 @@ struct Lara : Character {
|
||||
w *= TURN_WATER_FAST;
|
||||
else if (state == STATE_TREAD || state == STATE_SURF_TREAD || state == STATE_SURF_SWIM || state == STATE_SURF_BACK)
|
||||
w *= TURN_WATER_FAST;
|
||||
else if (state == STATE_RUN)
|
||||
w *= sign(w) != sign(tilt) ? 0.0f : w * TURN_FAST * tilt / LARA_TILT_MAX;
|
||||
else if (state == STATE_FAST_TURN)
|
||||
else if (state == STATE_RUN) {
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
w *= TURN_FAST;
|
||||
else
|
||||
w *= sign(w) != sign(tilt) ? 0.0f : w * TURN_FAST * tilt / LARA_TILT_MAX;
|
||||
} else if (state == STATE_FAST_TURN)
|
||||
w *= TURN_FAST;
|
||||
else if (state == STATE_FAST_BACK)
|
||||
w *= TURN_FAST_BACK;
|
||||
@@ -2928,7 +2966,8 @@ struct Lara : Character {
|
||||
if (stand == STAND_UNDERWATER)
|
||||
vTilt *= 2.0f;
|
||||
vTilt *= rotFactor.y;
|
||||
updateTilt(state == STATE_RUN || stand == STAND_UNDERWATER, vTilt.x, vTilt.y);
|
||||
bool VR = (Core::settings.detail.stereo == Core::Settings::STEREO_VR) && camera->firstPerson;
|
||||
updateTilt((state == STATE_RUN || stand == STAND_UNDERWATER) && !VR, vTilt.x, vTilt.y);
|
||||
|
||||
collisionOffset = vec3(0.0f);
|
||||
|
||||
|
160
src/level.h
160
src/level.h
@@ -235,6 +235,11 @@ struct Level : IGame {
|
||||
|
||||
bool redraw = settings.detail.stereo != Core::settings.detail.stereo;
|
||||
|
||||
#ifdef ANDROID
|
||||
if ((settings.detail.stereo == Core::Settings::STEREO_VR) ^ (Core::settings.detail.stereo == Core::Settings::STEREO_VR))
|
||||
osToggleVR(settings.detail.stereo == Core::Settings::STEREO_VR);
|
||||
#endif
|
||||
|
||||
Core::settings = settings;
|
||||
|
||||
Stream::cacheWrite("settings", (char*)&settings, sizeof(settings));
|
||||
@@ -611,10 +616,10 @@ struct Level : IGame {
|
||||
track = TR::LEVEL_INFO[level.id].ambientTrack;
|
||||
|
||||
if (level.state.flags.track == track) {
|
||||
if (sndTrack) {
|
||||
sndTrack->replay();
|
||||
sndTrack->setVolume(1.0f, 0.2f);
|
||||
}
|
||||
// if (sndTrack) {
|
||||
// sndTrack->replay();
|
||||
// sndTrack->setVolume(1.0f, 0.2f);
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -708,6 +713,10 @@ struct Level : IGame {
|
||||
camera->doCutscene(lara->pos, lara->angle.y);
|
||||
}
|
||||
*/
|
||||
|
||||
Core::setTarget(NULL);
|
||||
Core::validateRenderState();
|
||||
|
||||
Core::resetTime();
|
||||
}
|
||||
|
||||
@@ -1206,7 +1215,6 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void initReflections() {
|
||||
Core::beginFrame();
|
||||
for (int i = 0; i < level.entitiesBaseCount; i++) {
|
||||
TR::Entity &e = level.entities[i];
|
||||
if (e.type == TR::Entity::CRYSTAL) {
|
||||
@@ -1215,7 +1223,6 @@ struct Level : IGame {
|
||||
c->environment->generateMipMap();
|
||||
}
|
||||
}
|
||||
Core::endFrame();
|
||||
}
|
||||
|
||||
void setMainLight(Controller *controller) {
|
||||
@@ -1788,6 +1795,24 @@ struct Level : IGame {
|
||||
}
|
||||
}
|
||||
|
||||
void renderOpaque(int *roomsList, int roomsCount) {
|
||||
renderRooms(roomsList, roomsCount, 0);
|
||||
renderEntities(0);
|
||||
}
|
||||
|
||||
void renderTransparent(int *roomsList, int roomsCount) {
|
||||
renderRooms(roomsList, roomsCount, 1);
|
||||
renderEntities(1);
|
||||
}
|
||||
|
||||
void renderAdditive(int *roomsList, int roomsCount) {
|
||||
vec4 oldFog = Core::fogParams;
|
||||
Core::fogParams = FOG_BLACK; // don't apply fog for additive
|
||||
renderRooms(roomsList, roomsCount, 2);
|
||||
renderEntities(2);
|
||||
Core::fogParams = oldFog;
|
||||
}
|
||||
|
||||
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) {
|
||||
PROFILE_MARKER("VIEW");
|
||||
|
||||
@@ -1849,7 +1874,10 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
if (water) {
|
||||
Core::setTarget(NULL, (Core::settings.detail.stereo == Core::Settings::STEREO_OFF && players[1] == NULL) ? CLEAR_ALL : 0); // render to back buffer
|
||||
//bool clear = Core::settings.detail.stereo == Core::Settings::STEREO_VR;
|
||||
//clear |= Core::settings.detail.stereo == Core::Settings::STEREO_OFF && players[1] == NULL;
|
||||
bool clear = true;
|
||||
Core::setTarget(NULL, clear ? CLEAR_ALL : 0); // render to back buffer
|
||||
setupBinding();
|
||||
}
|
||||
|
||||
@@ -1857,12 +1885,11 @@ struct Level : IGame {
|
||||
|
||||
updateLighting();
|
||||
|
||||
// opaque pass
|
||||
renderRooms(roomsList, roomsCount, 0);
|
||||
renderEntities(0);
|
||||
// alpha blending pass
|
||||
renderRooms(roomsList, roomsCount, 1);
|
||||
renderEntities(1);
|
||||
renderOpaque(roomsList, roomsCount);
|
||||
renderTransparent(roomsList, roomsCount);
|
||||
|
||||
if (camera->isUnderwater())
|
||||
renderAdditive(roomsList, roomsCount);
|
||||
|
||||
Core::setBlending(bmNone);
|
||||
if (water && waterCache && waterCache->visible) {
|
||||
@@ -1875,13 +1902,9 @@ struct Level : IGame {
|
||||
setupBinding();
|
||||
}
|
||||
|
||||
// additive blending pass
|
||||
vec4 oldFog = Core::fogParams;
|
||||
Core::fogParams = FOG_BLACK; // don't apply fog for additive
|
||||
renderRooms(roomsList, roomsCount, 2);
|
||||
renderEntities(2);
|
||||
Core::fogParams = oldFog;
|
||||
|
||||
if (!camera->isUnderwater())
|
||||
renderAdditive(roomsList, roomsCount);
|
||||
|
||||
Core::setBlending(bmNone);
|
||||
|
||||
if (showUI) {
|
||||
@@ -1931,7 +1954,9 @@ struct Level : IGame {
|
||||
|
||||
void renderShadows(int roomIndex) {
|
||||
PROFILE_MARKER("PASS_SHADOW");
|
||||
float oldEye = Core::eye;
|
||||
Core::eye = 0.0f;
|
||||
|
||||
Core::pass = Core::passShadow;
|
||||
shadow->unbind(sShadow);
|
||||
bool colorShadow = shadow->format == Texture::RGBA ? true : false;
|
||||
@@ -1948,13 +1973,15 @@ struct Level : IGame {
|
||||
Core::setCulling(cfFront);
|
||||
if (colorShadow)
|
||||
Core::setClearColor(vec4(0.0f));
|
||||
|
||||
Core::eye = oldEye;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void renderDebug() {
|
||||
if (level.isTitle() || inventory.titleTimer > 1.0f) return;
|
||||
|
||||
Core::setViewport(0, 0, Core::width, Core::height);
|
||||
Core::setViewport(Core::x, Core::y, Core::width, Core::height);
|
||||
camera->setup(true);
|
||||
|
||||
if (Input::down[ikF]) {
|
||||
@@ -2156,28 +2183,34 @@ struct Level : IGame {
|
||||
#endif
|
||||
|
||||
void setViewport(int view, int eye, bool isUI) {
|
||||
float vX = float(Core::x);
|
||||
float vY = float(Core::y);
|
||||
float vW = float(Core::width);
|
||||
float vH = float(Core::height);
|
||||
|
||||
float aspect = vW / vH;
|
||||
|
||||
if (Core::defaultTarget) {
|
||||
vX = 0.0f;
|
||||
vY = 0.0f;
|
||||
vW = float(Core::defaultTarget->width);
|
||||
vH = float(Core::defaultTarget->height);
|
||||
}
|
||||
|
||||
vec4 &vp = Core::viewportDef;
|
||||
|
||||
|
||||
if (players[1] != NULL) {
|
||||
vp = vec4(vW * 0.5f * view, 0.0f, vW * 0.5f, vH);
|
||||
vp = vec4(vX + vW * 0.5f * view, vY, vW * 0.5f, vH);
|
||||
if (Core::settings.detail.stereo != Core::Settings::STEREO_SPLIT)
|
||||
aspect *= 0.5f;
|
||||
} else
|
||||
vp = vec4(0.0f, 0.0f, vW, vH);
|
||||
|
||||
switch (eye) {
|
||||
case -1 : vp = vec4(vp.x - vp.x * 0.5f, vp.y, vp.z * 0.5f, vp.w); break;
|
||||
case +1 : vp = vec4(vW * 0.5f + vp.x / 2.0f, vp.y, vp.z * 0.5f, vp.w); break;
|
||||
vp = vec4(vX, vY, vW, vH);
|
||||
|
||||
if (Core::settings.detail.stereo != Core::Settings::STEREO_VR) {
|
||||
switch (eye) {
|
||||
case -1 : vp = vec4(vX + vp.x - vp.x * 0.5f, vY + vp.y, vp.z * 0.5f, vp.w); break;
|
||||
case +1 : vp = vec4(vX + vW * 0.5f + vp.x / 2.0f, vY + vp.y, vp.z * 0.5f, vp.w); break;
|
||||
}
|
||||
}
|
||||
|
||||
Core::eye = float(eye);
|
||||
@@ -2188,15 +2221,23 @@ struct Level : IGame {
|
||||
camera->aspect = aspect;
|
||||
}
|
||||
|
||||
void renderGame(bool showUI) {
|
||||
void renderPrepare() {
|
||||
Core::invalidateTarget(true, true);
|
||||
|
||||
if (ambientCache)
|
||||
ambientCache->processQueue();
|
||||
|
||||
if (shadow)
|
||||
renderShadows(player->getRoomIndex());
|
||||
|
||||
Core::setTarget(NULL, CLEAR_ALL);
|
||||
Core::validateRenderState();
|
||||
}
|
||||
|
||||
void renderGame(bool showUI) {
|
||||
//if (Core::settings.detail.stereo || Core::settings.detail.splitscreen) {
|
||||
Core::setTarget(NULL, CLEAR_ALL);
|
||||
Core::validateRenderState();
|
||||
// Core::setTarget(NULL, CLEAR_ALL);
|
||||
// Core::validateRenderState();
|
||||
//}
|
||||
|
||||
/* // catsuit test
|
||||
@@ -2215,6 +2256,8 @@ struct Level : IGame {
|
||||
mesh->renderQuad();
|
||||
return;
|
||||
*/
|
||||
vec4 vp = Core::viewportDef;
|
||||
|
||||
int viewsCount = players[1] ? 2 : 1;
|
||||
for (int view = 0; view < viewsCount; view++) {
|
||||
player = players[view];
|
||||
@@ -2224,12 +2267,12 @@ struct Level : IGame {
|
||||
params->clipSign = 1.0f;
|
||||
params->waterHeight = params->clipHeight;
|
||||
|
||||
if (shadow)
|
||||
if (shadow && view == 1)
|
||||
renderShadows(player->getRoomIndex());
|
||||
|
||||
if (shadow) shadow->bind(sShadow);
|
||||
Core::pass = Core::passCompose;
|
||||
|
||||
/*
|
||||
if (view == 0 && Input::hmd.ready) {
|
||||
Core::settings.detail.vr = true;
|
||||
|
||||
@@ -2255,9 +2298,11 @@ struct Level : IGame {
|
||||
Core::defaultTarget = oldTarget;
|
||||
Core::setTarget(NULL, CLEAR_ALL);
|
||||
Core::viewportDef = vp;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_ON) { // left/right SBS stereo
|
||||
float oldEye = Core::eye;
|
||||
|
||||
setViewport(view, -1, false);
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true, showUI);
|
||||
@@ -2265,15 +2310,16 @@ struct Level : IGame {
|
||||
setViewport(view, 1, false);
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true, showUI);
|
||||
|
||||
Core::eye = oldEye;
|
||||
} else {
|
||||
setViewport(view, 0, false);
|
||||
setViewport(view, int(Core::eye), false);
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true, showUI);
|
||||
}
|
||||
}
|
||||
|
||||
Core::eye = 0;
|
||||
Core::viewportDef = vec4(0.0f, 0.0f, float(Core::width), float(Core::height));
|
||||
Core::viewportDef = vp;
|
||||
|
||||
player = players[0];
|
||||
camera = player->camera;
|
||||
@@ -2301,18 +2347,27 @@ struct Level : IGame {
|
||||
|
||||
float eye = inventory.active ? 0.0f : UI::width * Core::eye * 0.02f;
|
||||
|
||||
vec2 pos;
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
pos = vec2((UI::width - size.x) * 0.5f - eye * 4.0f, 96);
|
||||
else
|
||||
pos = vec2(UI::width - 32 - size.x - eye, 32);
|
||||
|
||||
if (!player->dozy && (player->stand == Lara::STAND_ONWATER || player->stand == Character::STAND_UNDERWATER)) {
|
||||
UI::renderBar(UI::BAR_OXYGEN, pos, size, oxygen);
|
||||
pos.y += 16.0f;
|
||||
}
|
||||
|
||||
if ((!inventory.active && (!player->emptyHands() || player->damageTime > 0.0f || health <= 0.2f))) {
|
||||
UI::renderBar(UI::BAR_HEALTH, vec2(UI::width - 32 - size.x - eye, 32), size, health);
|
||||
UI::renderBar(UI::BAR_HEALTH, pos, size, health);
|
||||
pos.y += 32.0f;
|
||||
|
||||
if (!inventory.active && !player->emptyHands()) { // ammo
|
||||
int index = inventory.contains(player->getCurrentWeaponInv());
|
||||
if (index > -1)
|
||||
inventory.renderItemCount(inventory.items[index], vec2(UI::width - 32 - size.x - eye, 64), size.x);
|
||||
inventory.renderItemCount(inventory.items[index], pos, size.x);
|
||||
}
|
||||
}
|
||||
|
||||
if (!player->dozy && (player->stand == Lara::STAND_ONWATER || player->stand == Character::STAND_UNDERWATER))
|
||||
UI::renderBar(UI::BAR_OXYGEN, vec2(32 - eye, 32), size, oxygen);
|
||||
}
|
||||
|
||||
if (!level.isTitle())
|
||||
@@ -2324,11 +2379,12 @@ struct Level : IGame {
|
||||
void renderInventoryEye(int eye) {
|
||||
float aspect = float(Core::width) / float(Core::height);
|
||||
|
||||
switch (eye) {
|
||||
case -1 : Core::setViewport(0, 0, Core::width / 2, Core::height); break;
|
||||
case 0 : Core::setViewport(0, 0, Core::width, Core::height); break;
|
||||
case +1 : Core::setViewport(Core::width / 2, 0, Core::width / 2, Core::height); break;
|
||||
}
|
||||
if (Core::settings.detail.stereo != Core::Settings::STEREO_VR)
|
||||
switch (eye) {
|
||||
case -1 : Core::setViewport(Core::x, Core::y, Core::width / 2, Core::height); break;
|
||||
case 0 : Core::setViewport(Core::x, Core::y, Core::width, Core::height); break;
|
||||
case +1 : Core::setViewport(Core::x + Core::width / 2, Core::y, Core::width / 2, Core::height); break;
|
||||
}
|
||||
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT)
|
||||
eye = 0;
|
||||
@@ -2351,14 +2407,16 @@ struct Level : IGame {
|
||||
if (!(level.isTitle() || inventory.titleTimer > 0.0f))
|
||||
inventory.renderBackground();
|
||||
|
||||
float oldEye = Core::eye;
|
||||
|
||||
if ((Core::settings.detail.stereo == Core::Settings::STEREO_ON) || (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT && players[1])) {
|
||||
renderInventoryEye(-1);
|
||||
renderInventoryEye(+1);
|
||||
} else
|
||||
renderInventoryEye(0);
|
||||
renderInventoryEye(int(Core::eye));
|
||||
|
||||
Core::setViewport(0, 0, Core::width, Core::height);
|
||||
Core::eye = 0.0f;
|
||||
Core::setViewport(Core::x, Core::y, Core::width, Core::height);
|
||||
Core::eye = oldEye;
|
||||
}
|
||||
|
||||
void render() {
|
||||
|
14
src/mesh.h
14
src/mesh.h
@@ -200,6 +200,7 @@ struct Mesh {
|
||||
range.bind(VAO);
|
||||
bind(true);
|
||||
range.setup(vBuffer);
|
||||
unbind();
|
||||
} else
|
||||
#endif
|
||||
range.aIndex = -1;
|
||||
@@ -217,12 +218,21 @@ struct Mesh {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void unbind() {
|
||||
if (Core::support.VAO)
|
||||
glBindVertexArray(Core::active.VAO = 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Core::active.iBuffer = 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, Core::active.vBuffer = 0);
|
||||
}
|
||||
|
||||
void render(const MeshRange &range) {
|
||||
if (range.aIndex == -1)
|
||||
bind();
|
||||
|
||||
#ifndef _PSP
|
||||
range.bind(VAO);
|
||||
#endif
|
||||
|
||||
bind();
|
||||
if (range.aIndex == -1)
|
||||
range.setup(vBuffer);
|
||||
|
||||
@@ -707,7 +717,7 @@ struct MeshBuilder {
|
||||
#ifdef GENERATE_WATER_PLANE
|
||||
plane.vStart = vStartCommon;
|
||||
plane.iStart = iCount;
|
||||
plane.iCount = PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
|
||||
plane.iCount = SQR(PLANE_DETAIL * 2) * 6;
|
||||
|
||||
baseIdx = vCount - vStartCommon;
|
||||
for (int16 j = -PLANE_DETAIL; j <= PLANE_DETAIL; j++)
|
||||
|
@@ -1,11 +1,12 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion '26.0.2'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.xproger.openlara"
|
||||
minSdkVersion 18
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 18
|
||||
versionCode 1
|
||||
versionName "0.1"
|
||||
@@ -36,4 +37,6 @@ android {
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
|
||||
compile 'com.google.vr:sdk-base:1.80.0'
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
android:versionCode="1"
|
||||
android:versionName="0.1" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="18" />
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26" />
|
||||
<supports-screens android:smallScreens="true" android:largeScreens="true" android:normalScreens="true" android:xlargeScreens="true" />
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "game.h"
|
||||
|
||||
JavaVM *jvm;
|
||||
|
||||
#define JNI_METHOD(return_type, method_name) \
|
||||
JNIEXPORT return_type JNICALL \
|
||||
Java_org_xproger_openlara_Wrapper_##method_name
|
||||
@@ -29,12 +31,24 @@ void osJoyVibrate(int index, float L, float R) {
|
||||
//
|
||||
}
|
||||
|
||||
void osToggleVR(bool enable) {
|
||||
JNIEnv *jniEnv;
|
||||
jvm->AttachCurrentThread(&jniEnv, NULL);
|
||||
|
||||
jboolean v = enable;
|
||||
jclass c = jniEnv->FindClass("org/xproger/openlara/MainActivity");
|
||||
jmethodID m = jniEnv->GetStaticMethodID(c, "toggleVR", "(Z)V");
|
||||
jniEnv->CallStaticVoidMethod(c, m, v);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
char Stream::cacheDir[255];
|
||||
char Stream::contentDir[255];
|
||||
|
||||
JNI_METHOD(void, nativeInit)(JNIEnv* env, jobject obj, jstring contentDir, jstring cacheDir) {
|
||||
env->GetJavaVM(&jvm);
|
||||
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
startTime = t.tv_sec;
|
||||
@@ -51,7 +65,8 @@ JNI_METHOD(void, nativeInit)(JNIEnv* env, jobject obj, jstring contentDir, jstri
|
||||
strcat(Stream::cacheDir, str);
|
||||
env->ReleaseStringUTFChars(cacheDir, str);
|
||||
|
||||
Game::init();
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&Core::defaultFBO);
|
||||
Game::init("level/1/LEVEL2.PSX");
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeFree)(JNIEnv* env) {
|
||||
@@ -63,14 +78,29 @@ JNI_METHOD(void, nativeReset)(JNIEnv* env) {
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeUpdate)(JNIEnv* env) {
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&Core::defaultFBO);
|
||||
|
||||
Game::update();
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeRender)(JNIEnv* env) {
|
||||
Game::render();
|
||||
JNI_METHOD(void, nativeFrameBegin)(JNIEnv* env) {
|
||||
Game::frameBegin();
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeResize)(JNIEnv* env, jobject obj, jint w, jint h) {
|
||||
JNI_METHOD(void, nativeFrameEnd)(JNIEnv* env) {
|
||||
Game::frameEnd();
|
||||
Core::reset();
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeFrameRender)(JNIEnv* env) {
|
||||
Game::frameRender();
|
||||
Core::reset();
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeResize)(JNIEnv* env, jobject obj, jint x, jint y, jint w, jint h) {
|
||||
Core::viewportDef = vec4(float(x), float(y), float(w), float(h));
|
||||
Core::x = x;
|
||||
Core::y = y;
|
||||
Core::width = w;
|
||||
Core::height = h;
|
||||
}
|
||||
@@ -101,7 +131,6 @@ JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfl
|
||||
case -4 : Input::setJoyPos(id, jkR, vec2(DeadZone(x), DeadZone(y))); break;
|
||||
default : {
|
||||
int btn = int(x);
|
||||
LOG("key %d = %d\n", btn, state);
|
||||
if (btn < 0)
|
||||
Input::setJoyDown(id, JoyKey(jkNone - btn), state != -1);
|
||||
else
|
||||
@@ -111,16 +140,6 @@ JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfl
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == -100) {
|
||||
/*
|
||||
switch (state) {
|
||||
case 0 : Input::head.basis.rot.x = x; Input::head.basis.rot.y = y; break;
|
||||
case 1 : Input::head.basis.rot.z = x; Input::head.basis.rot.w = y; Input::head.set(); break;
|
||||
}
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
// touch
|
||||
InputKey key = Input::getTouch(id);
|
||||
if (key == ikNone) return;
|
||||
@@ -129,6 +148,37 @@ JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfl
|
||||
Input::setDown(key, state == 2);
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeSetVR)(JNIEnv* env, jobject obj, jboolean enabled) {
|
||||
Core::Settings settings = Core::settings;
|
||||
settings.detail.stereo = enabled ? Core::Settings::STEREO_VR : Core::Settings::STEREO_OFF;
|
||||
Game::level->applySettings(settings);
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeSetHead)(JNIEnv* env, jobject obj, jfloatArray head) {
|
||||
jfloat *mHead = env->GetFloatArrayElements(head, NULL);
|
||||
memcpy(&Input::hmd.head, mHead, sizeof(float) * 16);
|
||||
Input::hmd.head = Input::hmd.head.inverseOrtho();
|
||||
env->ReleaseFloatArrayElements(head, mHead, 0);
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeSetEye)(JNIEnv* env, jobject obj, jint eye, jfloatArray proj, jfloatArray view) {
|
||||
Core::eye = float(eye);
|
||||
if (eye == 0) return;
|
||||
eye = eye == -1 ? 0 : 1;
|
||||
|
||||
jfloat *mProj = env->GetFloatArrayElements(proj, NULL);
|
||||
jfloat *mView = env->GetFloatArrayElements(view, NULL);
|
||||
|
||||
memcpy(&Input::hmd.proj[eye], mProj, sizeof(float) * 16);
|
||||
memcpy(&Input::hmd.eye[eye], mView, sizeof(float) * 16);
|
||||
|
||||
Input::hmd.eye[eye].setPos(Input::hmd.eye[eye].getPos() * ONE_METER);
|
||||
Input::hmd.eye[eye] = Input::hmd.eye[eye].inverseOrtho();
|
||||
|
||||
env->ReleaseFloatArrayElements(proj, mProj, 0);
|
||||
env->ReleaseFloatArrayElements(view, mView, 0);
|
||||
}
|
||||
|
||||
JNI_METHOD(void, nativeSoundFill)(JNIEnv* env, jobject obj, jshortArray buffer) {
|
||||
jshort *frames = env->GetShortArrayElements(buffer, NULL);
|
||||
jsize count = env->GetArrayLength(buffer) / 2;
|
||||
|
@@ -2,20 +2,10 @@ package org.xproger.openlara;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioTrack;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.opengl.GLSurfaceView.Renderer;
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Environment;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
@@ -26,12 +16,24 @@ import android.view.View.OnKeyListener;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
//import android.util.Log;
|
||||
|
||||
public class MainActivity extends Activity implements OnTouchListener, OnKeyListener, OnGenericMotionListener, SensorEventListener {
|
||||
import com.google.vr.sdk.base.AndroidCompat;
|
||||
import com.google.vr.sdk.base.Eye;
|
||||
import com.google.vr.sdk.base.GvrActivity;
|
||||
import com.google.vr.sdk.base.GvrView;
|
||||
import com.google.vr.sdk.base.HeadTransform;
|
||||
import com.google.vr.sdk.base.Viewport;
|
||||
|
||||
public class MainActivity extends GvrActivity implements OnTouchListener, OnKeyListener, OnGenericMotionListener {
|
||||
static GvrView gvrView;
|
||||
|
||||
private Wrapper wrapper;
|
||||
private ArrayList joyList = new ArrayList();
|
||||
|
||||
public static void toggleVR(boolean enable) {
|
||||
gvrView.setStereoModeEnabled(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
@@ -45,10 +47,11 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
GLSurfaceView view = new GLSurfaceView(this);
|
||||
//GLSurfaceView view = new GLSurfaceView(this);
|
||||
final GvrView view = new GvrView(this);
|
||||
view.setEGLContextClientVersion(2);
|
||||
view.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
|
||||
view.setPreserveEGLContextOnPause(true);
|
||||
//view.setPreserveEGLContextOnPause(true);
|
||||
view.setRenderer(wrapper = new Wrapper());
|
||||
|
||||
view.setFocusable(true);
|
||||
@@ -57,13 +60,30 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList
|
||||
view.setOnTouchListener(this);
|
||||
view.setOnGenericMotionListener(this);
|
||||
view.setOnKeyListener(this);
|
||||
//setAsyncReprojectionEnabled(true);
|
||||
//setSustainedPerformanceMode(this, true);
|
||||
view.setTransitionViewEnabled(false);
|
||||
|
||||
if (view.setAsyncReprojectionEnabled(true)) {
|
||||
AndroidCompat.setSustainedPerformanceMode(this, true);
|
||||
}
|
||||
|
||||
//AndroidCompat.setVrModeEnabled(this, false);
|
||||
view.setStereoModeEnabled(false);
|
||||
view.setDistortionCorrectionEnabled(true);
|
||||
|
||||
view.setOnCloseButtonListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
view.setStereoModeEnabled(false);
|
||||
wrapper.toggleVR = true;
|
||||
}
|
||||
});
|
||||
|
||||
setGvrView(view);
|
||||
|
||||
setContentView(view);
|
||||
/*
|
||||
SensorManager sm = (SensorManager)getSystemService(SENSOR_SERVICE);
|
||||
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_FASTEST);
|
||||
*/
|
||||
|
||||
gvrView = view;
|
||||
|
||||
try {
|
||||
String content = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
wrapper.onCreate(content + "/OpenLara/", getCacheDir().getAbsolutePath() + "/");
|
||||
@@ -115,16 +135,6 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor arg0, int arg1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
wrapper.onTouch(-100, 0, -event.values[1], event.values[0]);
|
||||
wrapper.onTouch(-100, 1, event.values[2], event.values[3]);
|
||||
}
|
||||
|
||||
boolean isGamepad(int src) {
|
||||
return (src & (InputDevice.SOURCE_GAMEPAD | InputDevice.SOURCE_JOYSTICK)) != 0;
|
||||
}
|
||||
@@ -285,17 +295,23 @@ class Touch {
|
||||
}
|
||||
}
|
||||
|
||||
class Wrapper implements Renderer {
|
||||
class Wrapper implements GvrView.StereoRenderer {
|
||||
public static native void nativeInit(String contentDir, String cacheDir);
|
||||
public static native void nativeFree();
|
||||
public static native void nativeReset();
|
||||
public static native void nativeResize(int w, int h);
|
||||
public static native void nativeResize(int x, int y, int w, int h);
|
||||
public static native void nativeUpdate();
|
||||
public static native void nativeRender();
|
||||
public static native void nativeSetVR(boolean enabled);
|
||||
public static native void nativeSetHead(float head[]);
|
||||
public static native void nativeSetEye(int eye, float proj[], float view[]);
|
||||
public static native void nativeFrameBegin();
|
||||
public static native void nativeFrameEnd();
|
||||
public static native void nativeFrameRender();
|
||||
public static native void nativeTouch(int id, int state, float x, float y);
|
||||
public static native void nativeSoundFill(short buffer[]);
|
||||
|
||||
Boolean ready = false;
|
||||
Boolean toggleVR = false;
|
||||
private String contentDir;
|
||||
private String cacheDir;
|
||||
private ArrayList<Touch> touch = new ArrayList<>();
|
||||
@@ -330,7 +346,26 @@ class Wrapper implements Renderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
public void onSurfaceChanged(int width, int height) {
|
||||
nativeResize(0, 0, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(EGLConfig config) {
|
||||
if (!ready) {
|
||||
nativeInit(contentDir, cacheDir);
|
||||
sound.play();
|
||||
ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRendererShutdown() {
|
||||
//
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewFrame(HeadTransform headTransform) {
|
||||
synchronized (this) {
|
||||
for (int i = 0; i < touch.size(); i++) {
|
||||
Touch t = touch.get(i);
|
||||
@@ -338,21 +373,37 @@ class Wrapper implements Renderer {
|
||||
}
|
||||
touch.clear();
|
||||
}
|
||||
nativeUpdate();
|
||||
nativeRender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
nativeResize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
if (!ready) {
|
||||
nativeInit(contentDir, cacheDir);
|
||||
sound.play();
|
||||
ready = true;
|
||||
if (toggleVR) {
|
||||
nativeSetVR(false);
|
||||
toggleVR = false;
|
||||
}
|
||||
|
||||
float view[] = headTransform.getHeadView();
|
||||
nativeSetHead(view);
|
||||
|
||||
nativeUpdate();
|
||||
nativeFrameBegin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawEye(Eye eye) {
|
||||
float proj[] = eye.getPerspective(8.0f, 32.0f * 1024.0f);
|
||||
float view[] = eye.getEyeView();
|
||||
|
||||
int index = 0;
|
||||
if (eye.getType() == Eye.Type.LEFT) index = -1;
|
||||
if (eye.getType() == Eye.Type.RIGHT) index = +1;
|
||||
|
||||
nativeSetEye(index, proj, view);
|
||||
|
||||
nativeResize(eye.getViewport().x, eye.getViewport().y, eye.getViewport().width, eye.getViewport().height);
|
||||
nativeFrameRender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishFrame(Viewport viewport) {
|
||||
nativeResize(viewport.x, viewport.y, viewport.width, viewport.height);
|
||||
nativeFrameEnd();
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#Tue Mar 20 22:10:10 MSK 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
|
||||
|
@@ -605,7 +605,6 @@ void vrUpdateView() {
|
||||
mat4 vL = head * convToMat4(hmd->GetEyeToHeadTransform(vr::Eye_Left));
|
||||
mat4 vR = head * convToMat4(hmd->GetEyeToHeadTransform(vr::Eye_Right));
|
||||
|
||||
const float ONE_METER = 768.0f / 1.8f; // Lara's height in units / height in meters
|
||||
vL.setPos(vL.getPos() * ONE_METER);
|
||||
vR.setPos(vR.getPos() * ONE_METER);
|
||||
|
||||
|
@@ -215,6 +215,7 @@ struct MuzzleFlash : Controller {
|
||||
MuzzleFlash(IGame *game, int entity) : Controller(game, entity), owner(NULL), joint(0), lightIndex(-1) {
|
||||
pos.z += (level->version & (TR::VER_TR2 | TR::VER_TR3)) ? 180.0f : 150.0f;
|
||||
activate();
|
||||
timer = 0.0f;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
|
3
src/ui.h
3
src/ui.h
@@ -2,6 +2,7 @@
|
||||
#define H_UI
|
||||
|
||||
#include "core.h"
|
||||
#include "mesh.h"
|
||||
#include "controller.h"
|
||||
|
||||
enum StringID {
|
||||
@@ -13,6 +14,7 @@ enum StringID {
|
||||
, STR_OFF
|
||||
, STR_ON
|
||||
, STR_SPLIT
|
||||
, STR_VR
|
||||
, STR_QUALITY_LOW
|
||||
, STR_QUALITY_MEDIUM
|
||||
, STR_QUALITY_HIGH
|
||||
@@ -122,6 +124,7 @@ const char *STR[STR_MAX] = {
|
||||
, "Off"
|
||||
, "On"
|
||||
, "Split Screen"
|
||||
, "VR"
|
||||
, "Low"
|
||||
, "Medium"
|
||||
, "High"
|
||||
|
Reference in New Issue
Block a user