diff --git a/src/camera.h b/src/camera.h index 5fe11eb..1d9eff1 100644 --- a/src/camera.h +++ b/src/camera.h @@ -13,6 +13,9 @@ #define CAM_SPEED_FOLLOW 12 #define CAM_SPEED_COMBAT 8 +#define CAM_FOCAL_LENGTH 1536.0f +#define CAM_EYE_SEPARATION 16.0f + #define CAM_FOLLOW_ANGLE 0.0f #define CAM_LOOK_ANGLE_XMAX ( 55.0f * DEG2RAD) #define CAM_LOOK_ANGLE_XMIN (-75.0f * DEG2RAD) @@ -512,7 +515,7 @@ struct Camera : ICamera { 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_SBS || Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) - Core::mViewInv.setPos(Core::mViewInv.getPos() + Core::mViewInv.right().xyz() * (Core::eye * 16.0f) ); + Core::mViewInv.setPos(Core::mViewInv.getPos() + Core::mViewInv.right().xyz() * (Core::eye * CAM_EYE_SEPARATION) ); if (reflectPlane) { Core::mViewInv = mat4(*reflectPlane) * Core::mViewInv; @@ -521,17 +524,19 @@ struct Camera : ICamera { Core::mView = Core::mViewInv.inverseOrtho(); - if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) + if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) { Core::mProj = Input::hmd.proj[Core::eye == -1.0f ? 0 : 1]; - else - Core::mProj = GAPI::perspective(fov, aspect, znear, zfar); + } else { + float eyeSep = (Core::eye * CAM_EYE_SEPARATION) * znear / CAM_FOCAL_LENGTH; + Core::mProj = GAPI::perspective(fov, aspect, znear, zfar, eyeSep); + } } Core::setViewProj(Core::mView, Core::mProj); Core::viewPos = Core::mViewInv.getPos(); // update room for eye (with HMD offset) - if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) + if (Core::settings.detail.isStereo()) level->getSector(eye.room, Core::viewPos.xyz()); frustum->pos = Core::viewPos.xyz(); diff --git a/src/gapi/c3d.h b/src/gapi/c3d.h index 0384821..a7faed7 100644 --- a/src/gapi/c3d.h +++ b/src/gapi/c3d.h @@ -487,7 +487,7 @@ namespace GAPI { return res; } - mat4 perspective(float fov, float aspect, float znear, float zfar) { + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { mat4 m; Mtx_PerspTilt((C3D_Mtx*)&m, fov * DEG2RAD, aspect, znear, zfar, false); diff --git a/src/gapi/d3d11.h b/src/gapi/d3d11.h index bac6aed..cb6ef7e 100644 --- a/src/gapi/d3d11.h +++ b/src/gapi/d3d11.h @@ -717,13 +717,16 @@ namespace GAPI { } } - mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { - return mat4(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar); + mat4 m; + m.ortho(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar); + return m; } - mat4 perspective(float fov, float aspect, float znear, float zfar) { - return mat4(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar); + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { + mat4 m; + m.perspective(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar, eye); + return m; } bool beginFrame() { diff --git a/src/gapi/d3d9.h b/src/gapi/d3d9.h index f96c9b0..f6cad47 100644 --- a/src/gapi/d3d9.h +++ b/src/gapi/d3d9.h @@ -540,11 +540,15 @@ namespace GAPI { } mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { - return mat4(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar); + mat4 m; + m.ortho(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar); + return m; } - mat4 perspective(float fov, float aspect, float znear, float zfar) { - return mat4(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar); + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { + mat4 m; + m.perspective(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar, eye); + return m; } bool beginFrame() { diff --git a/src/gapi/gl.h b/src/gapi/gl.h index cda0718..e1b1b7c 100644 --- a/src/gapi/gl.h +++ b/src/gapi/gl.h @@ -1288,11 +1288,15 @@ namespace GAPI { } mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { - return mat4(mat4::PROJ_NEG_POS, l, r, b, t, znear, zfar); + mat4 m; + m.ortho(mat4::PROJ_NEG_POS, l, r, b, t, znear, zfar); + return m; } - mat4 perspective(float fov, float aspect, float znear, float zfar) { - return mat4(mat4::PROJ_NEG_POS, fov, aspect, znear, zfar); + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { + mat4 m; + m.perspective(mat4::PROJ_NEG_POS, fov, aspect, znear, zfar, eye); + return m; } bool beginFrame() { diff --git a/src/gapi/gu.h b/src/gapi/gu.h index b1dbebb..81ec0fe 100644 --- a/src/gapi/gu.h +++ b/src/gapi/gu.h @@ -296,11 +296,15 @@ namespace GAPI { } mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { - return mat4(mat4::PROJ_NEG_POS, l, r, b, t, znear, zfar); + mat4 m; + m.ortho(mat4::PROJ_NEG_POS, l, r, b, t, znear, zfar); + return m; } - mat4 perspective(float fov, float aspect, float znear, float zfar) { - return mat4(mat4::PROJ_NEG_POS, fov, aspect, znear, zfar); + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { + mat4 m; + m.perspective(mat4::PROJ_NEG_POS, fov, aspect, znear, zfar, eye); + return m; } bool beginFrame() { diff --git a/src/gapi/gxm.h b/src/gapi/gxm.h index 2bae6f0..7478d20 100644 --- a/src/gapi/gxm.h +++ b/src/gapi/gxm.h @@ -1206,11 +1206,15 @@ namespace GAPI { } mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { - return mat4(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar); + mat4 m; + m.ortho(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar); + return m; } - mat4 perspective(float fov, float aspect, float znear, float zfar) { - return mat4(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar); + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { + mat4 m; + m.perspective(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar, eye); + return m; } bool beginFrame() { diff --git a/src/inventory.h b/src/inventory.h index f61f323..b739ae1 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -6,18 +6,24 @@ #include "ui.h" #include "savegame.h" -#define INVENTORY_MAX_ITEMS 32 -#define INVENTORY_MAX_RADIUS 688.0f +#define INV_MAX_ITEMS 32 +#define INV_MAX_RADIUS 688.0f #ifdef _OS_PSP - #define INVENTORY_BG_SIZE 256 + #define INV_BG_SIZE 256 #else - #define INVENTORY_BG_SIZE 512 + #define INV_BG_SIZE 512 #endif -#define INVENTORY_HEIGHT 2048.0f +#define INV_HEIGHT 2048.0f #define TITLE_LOADING 64.0f #define LINE_HEIGHT 20.0f +#define INV_EYE_SEPARATION 16.0f +#define INV_EYE_FOCAL_LENGTH 256.0f +#define INV_ZNEAR 32.0f +#define INV_ZFAR 2048.0f +#define INV_FOV 70.0f + static const struct OptionItem *waitForKey = NULL; struct OptionItem { @@ -539,7 +545,7 @@ struct Inventory { anim->setAnim(0, 0, false); } - } *items[INVENTORY_MAX_ITEMS]; + } *items[INV_MAX_ITEMS]; static void loadTitleBG(Stream *stream, void *userData) { Inventory *inv = (Inventory*)userData; @@ -759,7 +765,7 @@ struct Inventory { return; } - ASSERT(itemsCount < INVENTORY_MAX_ITEMS); + ASSERT(itemsCount < INV_MAX_ITEMS); count = min(UNLIMITED_AMMO, count); @@ -1346,14 +1352,14 @@ struct Inventory { } Texture* getBackgroundTarget() { - if (background[0] && (background[0]->origWidth != INVENTORY_BG_SIZE || background[0]->origHeight != INVENTORY_BG_SIZE)) { + if (background[0] && (background[0]->origWidth != INV_BG_SIZE || background[0]->origHeight != INV_BG_SIZE)) { delete background[0]; background[0] = NULL; } for (int i = 0; i < COUNT(background); i++) if (!background[i]) - background[i] = new Texture(INVENTORY_BG_SIZE, INVENTORY_BG_SIZE, 1, FMT_RGBA, OPT_TARGET); + background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGBA, OPT_TARGET); return background[0]; } @@ -1385,14 +1391,14 @@ struct Inventory { // vertical blur Core::setTarget(background[1], NULL, RT_STORE_COLOR); game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false); - Core::active.shader->setParam(uParam, vec4(0, 1.0f / INVENTORY_BG_SIZE, 0, 0)); + Core::active.shader->setParam(uParam, vec4(0, 1.0f / INV_BG_SIZE, 0, 0)); background[0]->bind(sDiffuse); game->getMesh()->renderQuad(); // horizontal blur Core::setTarget(background[0], NULL, RT_STORE_COLOR); game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false); - Core::active.shader->setParam(uParam, vec4(1.0f / INVENTORY_BG_SIZE, 0, 0, 0)); + Core::active.shader->setParam(uParam, vec4(1.0f / INV_BG_SIZE, 0, 0, 0)); background[1]->bind(sDiffuse); game->getMesh()->renderQuad(); @@ -1467,8 +1473,7 @@ struct Inventory { if (item->type == TR::Entity::INV_CONTROLS || item->type == TR::Entity::INV_DETAIL) width += 80; - float eye = UI::width * Core::eye * 0.02f; - float x = ( UI::width - width ) * 0.5f - eye; + float x = ( UI::width - width ) * 0.5f; float y = ( UI::height - height ) * 0.5f + LINE_HEIGHT; // background @@ -1534,15 +1539,15 @@ struct Inventory { return def; } - void renderItemText(float eye, Item *item) { + void renderItemText(Item *item) { if (item->type == TR::Entity::INV_PASSPORT && phaseChoose == 1.0f) { // } else { StringID str = getItemName(item->desc.str, game->getLevel()->id, item->type); - UI::textOut(vec2(-eye, 480 - 32), str, UI::aCenter, UI::width); + UI::textOut(vec2(0, 480 - 32), str, UI::aCenter, UI::width); } - renderItemCount(item, vec2(UI::width / 2 - 160 - eye, 480 - 96), 320); + renderItemCount(item, vec2(UI::width / 2 - 160, 480 - 96), 320); // show health bar in inventory when selector is over medikit if (item->type == TR::Entity::INV_MEDIKIT_BIG || item->type == TR::Entity::INV_MEDIKIT_SMALL) { @@ -1553,12 +1558,12 @@ struct Inventory { vec2 size = vec2(180, 10); vec2 pos; if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) { - pos = vec2((UI::width - size.x) * 0.5f - eye * 4.0f, 96); + pos = vec2((UI::width - size.x) * 0.5f, 96); } else { if (game->getLara(1) && playerIndex == 0) { - pos = vec2(32 - eye, 32); + pos = vec2(32, 32); } else { - pos = vec2(UI::width - 32 - size.x - eye, 32); + pos = vec2(UI::width - 32 - size.x, 32); } } @@ -1579,7 +1584,7 @@ struct Inventory { case TR::Entity::INV_GAMMA : case TR::Entity::INV_STOPWATCH : case TR::Entity::INV_MAP : - UI::textOut(vec2(-eye, 240), STR_EMPTY, UI::aCenter, UI::width); + UI::textOut(vec2(0, 240), STR_EMPTY, UI::aCenter, UI::width); break; default : ; } @@ -1598,9 +1603,9 @@ struct Inventory { vec2 cpos(1286, 256 + 1280 * (1.0f - phaseRing)); float ringTilt = cpos.angle(); - float radius = phaseRing * INVENTORY_MAX_RADIUS * phase; + float radius = phaseRing * INV_MAX_RADIUS * phase; float collapseAngle = phaseRing * phase * PI - PI; - float ringHeight = lerp(float(this->page), float(targetPage), quintic(phasePage)) * INVENTORY_HEIGHT; + float ringHeight = lerp(float(this->page), float(targetPage), quintic(phasePage)) * INV_HEIGHT; float angle = getAngle(pageItemIndex[page], count); if (phaseSelect < 1.0f) @@ -1626,7 +1631,7 @@ struct Inventory { rd += 296 * phaseChoose; } - 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)); + Basis b = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item->desc.page * INV_HEIGHT - rh, 0)); if (item->type == TR::Entity::INV_COMPASS) { b.rotate(quat(vec3(1.0f, 0.0f, 0.0f), -phaseChoose * PI * 0.1f)); @@ -1833,7 +1838,7 @@ struct Inventory { pos.z -= 256.0f; if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS || Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) - pos.x += Core::eye * 8.0f; + pos.x += Core::eye * INV_EYE_SEPARATION; Core::mViewInv = mat4(pos, pos + vec3(0, 0, 1), vec3(0, -1, 0)); @@ -1844,10 +1849,12 @@ struct Inventory { } else head.e00 = INF; - if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) + if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) { Core::mProj = Input::hmd.proj[Core::eye == -1.0f ? 0 : 1]; - else - Core::mProj = GAPI::perspective(70.0f, aspect, 32.0f, 2048.0f); + } else { + float eyeSep = Core::eye * INV_EYE_SEPARATION * INV_ZNEAR / INV_EYE_FOCAL_LENGTH; + Core::mProj = GAPI::perspective(INV_FOV, aspect, INV_ZNEAR, INV_ZFAR, eyeSep); + } Core::mView = Core::mViewInv.inverseOrtho(); Core::viewPos = Core::mViewInv.getPos(); @@ -1935,47 +1942,44 @@ struct Inventory { static const StringID pageTitle[PAGE_MAX] = { STR_OPTION, STR_INVENTORY, STR_ITEMS, STR_SAVEGAME, STR_LEVEL_STATS }; - 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 (page == PAGE_SAVEGAME) { - UI::renderBar(CTEX_OPTION, vec2(-eye + UI::width / 2 - 120, 240 - 14), vec2(240, LINE_HEIGHT - 6), 1.0f, 0x802288FF, 0, 0, 0); - UI::textOut(vec2(-eye, 240), pageTitle[page], UI::aCenter, UI::width); - UI::renderBar(CTEX_OPTION, vec2(-eye - 48 * slot + UI::width / 2, 240 + 24 - 16), vec2(48, 18), 1.0f, 0xFFD8377C, 0); - UI::textOut(vec2(-eye - 48 + UI::width / 2, 240 + 24), STR_YES, UI::aCenter, 48); - UI::textOut(vec2(-eye + UI::width / 2, 240 + 24), STR_NO, UI::aCenter, 48); + UI::renderBar(CTEX_OPTION, vec2(UI::width / 2 - 120, 240 - 14), vec2(240, LINE_HEIGHT - 6), 1.0f, 0x802288FF, 0, 0, 0); + UI::textOut(vec2(0, 240), pageTitle[page], UI::aCenter, UI::width); + UI::renderBar(CTEX_OPTION, vec2(slot + UI::width / 2 - 48, 240 + 24 - 16), vec2(48, 18), 1.0f, 0xFFD8377C, 0); + UI::textOut(vec2(UI::width / 2 - 48, 240 + 24), STR_YES, UI::aCenter, 48); + UI::textOut(vec2(UI::width / 2, 240 + 24), STR_NO, UI::aCenter, 48); return; } if (page == PAGE_LEVEL_STATS) { - showLevelStats(vec2(-eye, 180)); + showLevelStats(vec2(0, 180)); return; } if (!game->getLevel()->isTitle()) - UI::textOut(vec2(-eye, 32), pageTitle[page], UI::aCenter, UI::width); + UI::textOut(vec2(0, 32), pageTitle[page], UI::aCenter, UI::width); if (canFlipPage(-1)) { - UI::textOut(vec2(16 - eye, 32), "[", UI::aLeft, UI::width); - UI::textOut(vec2(-eye, 32), "[", UI::aRight, UI::width - 20); + UI::textOut(vec2(16, 32), "[", UI::aLeft, UI::width); + UI::textOut(vec2( 0, 32), "[", UI::aRight, UI::width - 20); } if (canFlipPage(1)) { - UI::textOut(vec2(16 - eye, 480 - 16), "]", UI::aLeft, UI::width); - UI::textOut(vec2(-eye, 480 - 16), "]", UI::aRight, UI::width - 20); + UI::textOut(vec2(16, 480 - 16), "]", UI::aLeft, UI::width); + UI::textOut(vec2( 0, 480 - 16), "]", UI::aRight, UI::width - 20); } if (index == targetIndex && page == targetPage) - renderItemText(eye, items[getGlobalIndex(page, index)]); + renderItemText(items[getGlobalIndex(page, index)]); // inventory controls help if (page == targetPage && Input::touchTimerVis <= 0.0f) { - float dx = 32.0f - eye; + float dx = 32.0f; char buf[64]; const char *bSelect = STR[STR_KEY_FIRST + ikEnter]; const char *bBack = STR[STR_KEY_FIRST + Core::settings.controls[playerIndex].keys[cInventory].key]; diff --git a/src/lang/es.h b/src/lang/es.h index 5d76cb0..31f98f3 100644 --- a/src/lang/es.h +++ b/src/lang/es.h @@ -22,7 +22,7 @@ const char *STR_ES[] = { "" , "S)i" , "No" , "Side-By-Side" - , "Anaglyph" + , "Anaglifo" , "Pantalla dividida" , "VR" , "Bajo" diff --git a/src/lang/fr.h b/src/lang/fr.h index 452dc91..3e6302f 100644 --- a/src/lang/fr.h +++ b/src/lang/fr.h @@ -22,7 +22,7 @@ const char *STR_FR[] = { "" , "Marche" , "Arret" , "Side-By-Side" - , "Anaglyph" + , "Anaglyphe" , ")Ecran Divis)e" , "VR" , "Bas" diff --git a/src/lang/it.h b/src/lang/it.h index eab29f5..6a62b49 100644 --- a/src/lang/it.h +++ b/src/lang/it.h @@ -22,7 +22,7 @@ const char *STR_IT[] = { "" , "On" , "Off" , "Side-By-Side" - , "Anaglyph" + , "Anaglifo" , "Schermo diviso" , "VR" , "Basso" diff --git a/src/lang/pl.h b/src/lang/pl.h index 2f6b260..955f326 100644 --- a/src/lang/pl.h +++ b/src/lang/pl.h @@ -22,7 +22,7 @@ const char *STR_PL[] = { "" , "W}l" , "Wy}l" , "Side-By-Side" - , "Anaglyph" + , "Anaglif" , "Podzielony ekran" , "VR" , "Niska" diff --git a/src/lang/pt.h b/src/lang/pt.h index 01d470c..a49e443 100644 --- a/src/lang/pt.h +++ b/src/lang/pt.h @@ -22,7 +22,7 @@ const char *STR_PT[] = { "" , "Ligado" , "Desligado" , "Side-By-Side" - , "Anaglyph" + , "An)aglifo" , "Tela Separada" , "VR" , "Baixo" diff --git a/src/level.h b/src/level.h index 2a8d491..893c8c9 100644 --- a/src/level.h +++ b/src/level.h @@ -590,7 +590,7 @@ struct Level : IGame { Core::whiteTex->bind(sReflect); Core::whiteCube->bind(sEnvironment); - Texture *shadowMap = shadow[player->camera->cameraIndex]; + Texture *shadowMap = shadow[player ? player->camera->cameraIndex : 0]; if (shadowMap) shadowMap->bind(sShadow); Core::basis.identity(); @@ -2512,7 +2512,7 @@ struct Level : IGame { Core::mViewInv = mat4(pos, pos + dir, up); Core::mView = Core::mViewInv.inverseOrtho(); - Core::mProj = GAPI::perspective(90, 1.0f, camera->znear, camera->zfar); + Core::mProj = GAPI::perspective(90, 1.0f, camera->znear, camera->zfar, 0.0f); Core::mViewProj = Core::mProj * Core::mView; Core::viewPos = Core::mViewInv.offset().xyz(); @@ -2527,7 +2527,7 @@ struct Level : IGame { Core::mViewInv = mat4(player->mainLightPos, pos, vec3(0, -1, 0)); Core::mView = Core::mViewInv.inverseOrtho(); - Core::mProj = GAPI::perspective(90.0f, 1.0f, znear, zfar); + Core::mProj = GAPI::perspective(90.0f, 1.0f, znear, zfar, 0.0f); Core::mLightProj = Core::mProj * Core::mView; @@ -2913,34 +2913,12 @@ struct Level : IGame { } else vp = Viewport(vX, vY, vW, vH); - - Core::eye = float(eye); - - #ifdef _OS_3DS - Core::eye *= osGet3DSliderState() / 3.0f; - - if (eye <= 0) { - GAPI::curTarget = GAPI::defTarget[0]; - } else { - GAPI::curTarget = GAPI::defTarget[1]; - } - - C3D_FrameDrawOn(GAPI::curTarget); - #else - if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH || Core::settings.detail.stereo == Core::Settings::STEREO_VR) { - if (eye <= 0) { - Core::defaultTarget = Core::eyeTex[0]; - } else { - Core::defaultTarget = Core::eyeTex[1]; - } - Core::setTarget(Core::defaultTarget, NULL, 0); - } else { + if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS) { switch (eye) { case -1 : vp = Viewport(vX + vp.x - vp.x / 2, vY + vp.y, vp.width / 2, vp.height); break; case +1 : vp = Viewport(vX + vW / 2 + vp.x / 2, vY + vp.y, vp.width / 2, vp.height); break; } } - #endif Core::setViewport(vp.x, vp.y, vp.width, vp.height); @@ -3015,35 +2993,67 @@ struct Level : IGame { Viewport oldViewport = Core::viewportDef; GAPI::Texture *oldTarget = Core::defaultTarget; - int viewsCount = players[1] ? 2 : 1; - for (int view = 0; view < viewsCount; view++) { - player = players[view]; - camera = player->camera; + Core::eye = float(eye); - setClipParams(1.0f, NO_CLIP_PLANE); - params->waterHeight = params->clipHeight; + #ifdef _OS_3DS + Core::eye *= osGet3DSliderState() / 3.0f; - Core::pass = Core::passCompose; - - setViewport(view, eye, false); - setup(); - renderView(camera->getRoomIndex(), true, showUI); + if (eye <= 0) { + GAPI::curTarget = GAPI::defTarget[0]; + } else { + GAPI::curTarget = GAPI::defTarget[1]; } - Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR); + C3D_FrameDrawOn(GAPI::curTarget); + #else + if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH || Core::settings.detail.stereo == Core::Settings::STEREO_VR) { + if (eye <= 0) { + Core::defaultTarget = Core::eyeTex[0]; + } else { + Core::defaultTarget = Core::eyeTex[1]; + } + } + #endif + if (Core::lightColor[1].x > 0.5f) { + LOG("hello"); + } + + if (needRenderGame) { + int viewsCount = players[1] ? 2 : 1; + for (int view = 0; view < viewsCount; view++) { + player = players[view]; + camera = player->camera; + + setClipParams(1.0f, NO_CLIP_PLANE); + params->waterHeight = params->clipHeight; + + Core::pass = Core::passCompose; + + setViewport(view, eye, false); + setup(); + renderView(camera->getRoomIndex(), true, showUI); + } + } else { + Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR); + } + + Core::pushLights(); Core::resetLights(); if (!(level.isTitle() || inventory->titleTimer > 0.0f)) inventory->renderBackground(); renderInventoryEye(eye); + Core::popLights(); Core::defaultTarget = oldTarget; Core::viewportDef = oldViewport; Core::eye = oldEye; player = players[0]; - camera = player->camera; + if (player) { + camera = player->camera; + } } void renderGame(bool showUI) { @@ -3067,6 +3077,8 @@ struct Level : IGame { void renderUI() { if (inventory->titleTimer > 1.0f || level.isTitle()) return; + Core::pushLights(); + UI::begin(); UI::updateAspect(camera->aspect); @@ -3089,13 +3101,11 @@ struct Level : IGame { if (oxygen <= 0.2f) oxygen = 0.0f; } - 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); + pos = vec2((UI::width - size.x) * 0.5f, 96); else - pos = vec2(UI::width - 32 - size.x - eye, 32); + pos = vec2(UI::width - 32 - size.x, 32); if (!player->dozy && (player->stand == Lara::STAND_ONWATER || player->stand == Character::STAND_UNDERWATER)) { UI::renderBar(CTEX_OXYGEN, pos, size, oxygen); @@ -3119,22 +3129,24 @@ struct Level : IGame { UI::renderSubs(); UI::end(); + + Core::popLights(); } void renderInventoryEye(int eye) { float aspect = float(Core::width) / float(Core::height); - if (Core::settings.detail.stereo != Core::Settings::STEREO_VR) + if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS) { 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; - - Core::eye = float(eye); + if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) { + Core::setViewport(Core::x, Core::y, Core::width, Core::height); + } if (level.isTitle() || inventory->titleTimer > 0.0f) inventory->renderBackground(); @@ -3150,25 +3162,6 @@ struct Level : IGame { UI::end(); } - void renderInventory() { - Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR); - Core::resetLights(); - - if (!(level.isTitle() || inventory->titleTimer > 0.0f)) - inventory->renderBackground(); - - float oldEye = Core::eye; - - if ((Core::settings.detail.stereo == Core::Settings::STEREO_SBS) || (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) || (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT && players[1])) { - renderInventoryEye(-1); - renderInventoryEye(+1); - } else - renderInventoryEye(int(Core::eye)); - - Core::setViewport(Core::x, Core::y, Core::width, Core::height); - Core::eye = oldEye; - } - void render() { if (inventory->video) return; @@ -3192,10 +3185,7 @@ struct Level : IGame { inventory->prepareBackground(); } - if (needRenderGame) - renderGame(true); - - renderInventory(); + renderGame(true); } }; diff --git a/src/ui.h b/src/ui.h index 50d793a..3d565ee 100644 --- a/src/ui.h +++ b/src/ui.h @@ -643,7 +643,7 @@ namespace UI { delete item.animation; pickups.remove(i); } else { - vec2 target = vec2(w - 48.0f - Core::eye * 16.0f - (i % 4) * 96.0f, UI::height - 48.0f - (i / 4) * 96.0f); + vec2 target = vec2(w - 48.0f - (i % 4) * 96.0f, UI::height - 48.0f - (i / 4) * 96.0f); item.pos = item.pos.lerp(target, Core::deltaTime * 5.0f); i++; } @@ -710,18 +710,16 @@ namespace UI { #ifdef _NAPI_SOCKET textOut(vec2(16, height - 32), command, aLeft, width - 32, 255, UI::SHADE_GRAY); #endif - float eye = UI::width * Core::eye * 0.02f; - if (hintTime > 0.0f) { - textOut(vec2(16 - eye, 32), hintStr, aLeft, width - 32, 255, UI::SHADE_GRAY); + textOut(vec2(16, 32), hintStr, aLeft, width - 32, 255, UI::SHADE_GRAY); } #if defined(_OS_WEB) || defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_MAC) || defined(_OS_RPI) if (showHelp) { - textOut(vec2(32 - eye, 32), STR_HELP_TEXT, aLeft, width - 32, 255, UI::SHADE_GRAY); + textOut(vec2(32, 32), STR_HELP_TEXT, aLeft, width - 32, 255, UI::SHADE_GRAY); } else { if (helpTipTime > 0.0f) { - textOut(vec2(0 - eye, height - 16), STR_HELP_PRESS, aCenter, width, 255, UI::SHADE_ORANGE); + textOut(vec2(0, height - 16), STR_HELP_PRESS, aCenter, width, 255, UI::SHADE_ORANGE); } } #endif @@ -736,12 +734,10 @@ namespace UI { void renderSubs() { if (!Core::settings.audio.subtitles) return; - float eye = UI::width * Core::eye * 0.02f; - if (subsTime > 0.0f) { const char *subs = STR[subsStr] + subsPos; - textOut(vec2(16 - eye, height - 48) + vec2(1, 1), subs, aCenterV, width - 32, 255, UI::SHADE_GRAY, true); - textOut(vec2(16 - eye, height - 48), subs, aCenterV, width - 32, 255, UI::SHADE_GRAY); + textOut(vec2(16, height - 48) + vec2(1, 1), subs, aCenterV, width - 32, 255, UI::SHADE_GRAY, true); + textOut(vec2(16, height - 48), subs, aCenterV, width - 32, 255, UI::SHADE_GRAY); } } @@ -762,7 +758,7 @@ namespace UI { void setupInventoryShading(vec3 offset) { Core::mView.identity(); - Core::mProj = GAPI::perspective(1.0f, 1.0f, 1.0f, 2.0f); + Core::mProj = GAPI::perspective(1.0f, 1.0f, 1.0f, 2.0f, 0.0f); Core::mLightProj = Core::mProj * Core::mView; game->setShader(Core::passCompose, Shader::ENTITY, false, false); @@ -797,6 +793,7 @@ namespace UI { mat4 mView = Core::mView; Core::mView.scale(vec3(0.5f)); + Core::mView.translate(vec3(-Core::eye * CAM_EYE_SEPARATION, 0.0f, 0.0f)); Core::setViewProj(Core::mView, Core::mProj); vec3 lightOffset = vec3(UI::width - 64.0f, UI::height - 64.0f, 2048.0f); diff --git a/src/utils.h b/src/utils.h index daae02c..38d6b77 100644 --- a/src/utils.h +++ b/src/utils.h @@ -646,13 +646,15 @@ struct mat4 { e33 = 1.0f; } - mat4(ProjRange range, float l, float r, float b, float t, float znear, float zfar) { + void ortho(ProjRange range, float l, float r, float b, float t, float znear, float zfar) { identity(); + e00 = 2.0f / (r - l); e11 = 2.0f / (t - b); e22 = 2.0f / (znear - zfar); e03 = (l + r) / (l - r); e13 = (t + b) / (b - t); + switch (range) { case PROJ_NEG_POS : e23 = (zfar + znear) / (znear - zfar); @@ -663,18 +665,16 @@ struct mat4 { } } - mat4(ProjRange range, float fov, float aspect, float znear, float zfar) { - float k = 1.0f / tanf(fov * 0.5f * DEG2RAD); + void frustum(ProjRange range, float l, float r, float b, float t, float znear, float zfar) { identity(); - if (aspect >= 1.0f) { - e00 = k / aspect; - e11 = k; - } else { - e00 = k; - e11 = k * aspect; - } - e33 = 0.0f; + + e00 = 2.0f * znear / (r - l); + e11 = 2.0f * znear / (t - b); + e02 = (r + l) / (r - l); + e12 = (t + b) / (t - b); e32 = -1.0f; + e33 = 0.0f; + switch (range) { case PROJ_NEG_POS : e22 = (znear + zfar) / (znear - zfar); @@ -687,6 +687,20 @@ struct mat4 { } } + void perspective(ProjRange range, float fov, float aspect, float znear, float zfar, float eye = 0.0f) { + float y = tanf(fov * 0.5f * DEG2RAD) * znear; + float x = y; + + if (aspect >= 1.0f) { + x = y * aspect; + } else { + x = y; + y /= aspect; + } + + frustum(range, -x - eye, x - eye, -y, y, znear, zfar); + } + mat4(const vec3 &from, const vec3 &at, const vec3 &up) { vec3 r, u, d; d = (from - at).normal();