mirror of
https://github.com/celisej567/mcpe.git
synced 2026-01-04 14:09:47 +03:00
* WIP Android Port Android port. Still needs touch controls and mouse turning (if that's even possible on android) and file saving and SoundSystemSL You control the camera and movement with your controller for now. You can navigate the gui using touch. Options.cpp,LocalPlayer.cpp,Minecraft.cpp is configured to use controller. Blocked out some code in ControllerTurnInput.cpp,Controller.cpp that didn't make sense. * Fix glClear glClear is supossed to use GL_DEPTH_BUFFER_BIT (thx TheBrokenRail) * * Fix build. * * Ignore assets. * * More stuff * * Fix more build errors. * * It finally built What I needed to do is rebuild the debug keystore because apparently android studio created it with sha1 digest alg which isn't supported by ant * * Clean up filters. * * Add cramped mode to the pause screen. * * Fix a bug with the hotbar * * In NinecraftApp::handleBack, pause the game if there is no screen. * * AppPlatform_android: Add placeholder SoundSystem instance till we get SoundSystemSL working * * Add properly working touch code. * * Oh, remove some testing things * * Fix state resetting when going in background and back in foreground * Fix bug where the sky isn't being regenerated on graphics reset * Fix bug where the m_currBoundTex isn't reset in Textures::clear potentially leaving a texture with that ID unassigned and corrupted * Fix bug in CThread where the thread is detached and then also joined. * Don't log anything if the program isn't in debug mode. * * Add virtual keyboard support. The screen instance slides so that the focused text box is kept visible. * Rename from com.minecraftcpp to com.reminecraftpe --------- Co-authored-by: iProgramInCpp <iprogramincpp@gmail.com>
1004 lines
24 KiB
C++
1004 lines
24 KiB
C++
/********************************************************************
|
|
Minecraft: Pocket Edition - Decompilation Project
|
|
Copyright (C) 2023 iProgramInCpp
|
|
|
|
The following code is licensed under the BSD 1 clause license.
|
|
SPDX-License-Identifier: BSD-1-Clause
|
|
********************************************************************/
|
|
|
|
#include "thirdparty/GL/GL.hpp"
|
|
#include "GameRenderer.hpp"
|
|
#include "client/app/Minecraft.hpp"
|
|
#include "client/player/input/Multitouch.hpp"
|
|
#include "Frustum.hpp"
|
|
#include "renderer/GL/GL.hpp"
|
|
|
|
static int t_keepHitResult; // that is its address in v0.1.1j
|
|
int t_keepPic;
|
|
|
|
void GameRenderer::_init()
|
|
{
|
|
//ItemInHandRenderer* m_pItemInHandRenderer = nullptr;
|
|
|
|
field_8 = 0.0f;
|
|
field_C = 0;
|
|
field_10 = nullptr;
|
|
field_14 = 0.0f;
|
|
field_18 = 0.0f;
|
|
field_1C = 0.0f;
|
|
field_20 = 0.0f;
|
|
field_24 = 0.0f;
|
|
field_28 = 0.0f;
|
|
field_2C = 4.0f;
|
|
field_30 = 4.0f;
|
|
field_34 = 0.0f;
|
|
field_38 = 0.0f;
|
|
field_3C = 0.0f;
|
|
field_40 = 0.0f;
|
|
field_44 = 1.0f;
|
|
field_48 = 0.0f;
|
|
field_4C = 0.0f;
|
|
field_50 = 0.0f;
|
|
field_54 = 0.0f;
|
|
field_58 = 0.0f;
|
|
field_5C = 0.0f;
|
|
field_60 = 0.0f;
|
|
field_64 = 0.0f;
|
|
field_68 = 0.0f;
|
|
field_6C = 0.0f;
|
|
field_70 = 0.0f;
|
|
field_74 = 0.0f;
|
|
field_78 = 0.0f;
|
|
field_7C = 0.0f;
|
|
field_80 = 0.0f;
|
|
field_84 = 0.0f;
|
|
m_lastUpdatedMS = 0;
|
|
m_shownFPS = 0;
|
|
m_shownChunkUpdates = 0;
|
|
}
|
|
|
|
GameRenderer::GameRenderer(Minecraft* pMinecraft) :
|
|
m_pMinecraft(pMinecraft)
|
|
{
|
|
_init();
|
|
|
|
saveMatrices();
|
|
|
|
m_pItemInHandRenderer = new ItemInHandRenderer(pMinecraft);
|
|
EntityRenderDispatcher::getInstance()->m_pItemInHandRenderer = m_pItemInHandRenderer;
|
|
}
|
|
|
|
GameRenderer::~GameRenderer()
|
|
{
|
|
delete m_pItemInHandRenderer;
|
|
}
|
|
|
|
void GameRenderer::zoomRegion(float a, float b, float c)
|
|
{
|
|
field_44 = a;
|
|
field_48 = b;
|
|
field_4C = c;
|
|
}
|
|
|
|
void GameRenderer::unZoomRegion()
|
|
{
|
|
field_44 = 1.0f;
|
|
}
|
|
|
|
void GameRenderer::setupCamera(float f, int i)
|
|
{
|
|
field_8 = float(256 >> m_pMinecraft->getOptions()->m_iViewDistance);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
|
|
if (m_pMinecraft->getOptions()->m_bAnaglyphs)
|
|
{
|
|
glTranslatef(float(1 - 2 * i) * 0.07f, 0.0f, 0.0f);
|
|
}
|
|
|
|
if (field_44 != 1.0)
|
|
{
|
|
glTranslatef(field_48, -field_4C, 0.0);
|
|
glScalef(field_44, field_44, 1.0);
|
|
}
|
|
|
|
float fov = getFov(f);
|
|
gluPerspective(fov, float(Minecraft::width) / float(Minecraft::height), 0.05f, field_8);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
if (m_pMinecraft->getOptions()->m_bAnaglyphs)
|
|
{
|
|
glTranslatef(float(2 * i - 1) * 0.1f, 0.0f, 0.0f);
|
|
}
|
|
|
|
bobHurt(f);
|
|
if (m_pMinecraft->getOptions()->m_bViewBobbing)
|
|
bobView(f);
|
|
|
|
moveCameraToPlayer(f);
|
|
}
|
|
|
|
void GameRenderer::moveCameraToPlayer(float f)
|
|
{
|
|
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
|
|
|
float headHeightDiff = pMob->field_84 - 1.62f;
|
|
|
|
float posX = Lerp(pMob->field_3C.x, pMob->m_pos.x, f);
|
|
float posY = Lerp(pMob->field_3C.y, pMob->m_pos.y, f);
|
|
float posZ = Lerp(pMob->field_3C.z, pMob->m_pos.z, f);
|
|
|
|
glRotatef(field_5C + f * (field_58 - field_5C), 0.0f, 0.0f, 1.0f);
|
|
|
|
if (m_pMinecraft->getOptions()->m_bThirdPerson)
|
|
{
|
|
float v11 = field_30 + (field_2C - field_30) * f;
|
|
if (m_pMinecraft->getOptions()->field_241)
|
|
{
|
|
glTranslatef(0.0f, 0.0f, -v11);
|
|
glRotatef(field_38 + (field_34 - field_38) * f, 1.0f, 0.0f, 0.0f);
|
|
glRotatef(field_40 + (field_3C - field_40) * f, 0.0f, 1.0f, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
float mob_yaw = pMob->m_yaw;
|
|
float mob_pitch = pMob->m_pitch;
|
|
|
|
float pitchRad = mob_pitch / 180.0f * float(M_PI);
|
|
|
|
float aX = posX - (-(Mth::sin(mob_yaw / 180.0f * float(M_PI)) * Mth::cos(pitchRad)) * v11);
|
|
float aY = posY + (Mth::sin(pitchRad) * v11);
|
|
float aZ = posZ - ((Mth::cos(mob_yaw / 180.0f * float(M_PI)) * Mth::cos(pitchRad)) * v11);
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
float offsX = (2 * (i & 1) - 1) * 0.1f;
|
|
float offsY = ((i & 2) - 1) * 0.1f;
|
|
float offsZ = (2 * ((i >> 2) & 1) - 1) * 0.1f;
|
|
|
|
HitResult hr = m_pMinecraft->m_pLevel->clip(
|
|
Vec3(posX + offsX, posY + offsY, posZ + offsZ),
|
|
Vec3(aX + offsX + offsZ, aY + offsY, aZ + offsZ) // @NOTE: Not sure why it adds offsZ to offsX.
|
|
);
|
|
|
|
if (hr.m_hitType != HitResult::NONE)
|
|
{
|
|
float dX = posX - hr.m_hitPos.x;
|
|
float dY = posY - hr.m_hitPos.y;
|
|
float dZ = posZ - hr.m_hitPos.z;
|
|
float dist = sqrtf(dX * dX + dY * dY + dZ * dZ);
|
|
if (v11 > dist)
|
|
v11 = dist;
|
|
}
|
|
}
|
|
|
|
// @HUH: Why the hell is it rotating by 0
|
|
glRotatef(pMob->m_pitch - mob_pitch, 1.0f, 0.0f, 0.0f);
|
|
glRotatef(pMob->m_yaw - mob_yaw, 0.0f, 1.0f, 0.0f);
|
|
glTranslatef(0.0, 0.0, -v11);
|
|
glRotatef(mob_yaw - pMob->m_yaw, 0.0f, 1.0f, 0.0f);
|
|
glRotatef(mob_pitch - pMob->m_pitch, 1.0f, 0.0f, 0.0f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
glTranslatef(0.0f, 0.0f, -0.1f);
|
|
}
|
|
|
|
if (!m_pMinecraft->getOptions()->field_241)
|
|
{
|
|
glRotatef(pMob->field_60 + f * (pMob->m_pitch - pMob->field_60), 1.0f, 0.0f, 0.0f);
|
|
glRotatef(pMob->field_5C + f * (pMob->m_yaw - pMob->field_5C) + 180.0f, 0.0f, 1.0f, 0.0f);
|
|
}
|
|
|
|
glTranslatef(0.0f, headHeightDiff, 0.0f);
|
|
}
|
|
|
|
void GameRenderer::saveMatrices()
|
|
{
|
|
glGetFloatv(GL_PROJECTION_MATRIX, m_matrix_projection);
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, m_matrix_model_view);
|
|
}
|
|
|
|
void GameRenderer::setupGuiScreen()
|
|
{
|
|
float x = Gui::InvGuiScale * Minecraft::width;
|
|
float y = Gui::InvGuiScale * Minecraft::height;
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
xglOrthof(0, x, y, 0, 2000.0f, 3000.0f);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
glTranslatef(0.0f, 0.0f, -2000.0f);
|
|
}
|
|
|
|
void GameRenderer::bobHurt(float f)
|
|
{
|
|
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
|
|
|
if (pMob->m_health <= 0)
|
|
glRotatef(-8000.0f / (float(pMob->field_110) + f + 200.0f) + 40.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
if (pMob->field_104 > 0)
|
|
{
|
|
float val = (pMob->field_104 - f) / pMob->field_108;
|
|
|
|
glRotatef(-pMob->field_10C, 0.0f, 1.0f, 0.0f);
|
|
glRotatef(Mth::sin(val * val * val * val * 3.1416f) * -14.0f, 0.0f, 0.0f, 1.0f);
|
|
glRotatef(pMob->field_10C, 0.0f, 1.0f, 0.0f);
|
|
}
|
|
}
|
|
|
|
void GameRenderer::bobView(float f)
|
|
{
|
|
if (!m_pMinecraft->m_pMobPersp->isPlayer())
|
|
return;
|
|
|
|
Player* player = (Player*)m_pMinecraft->m_pMobPersp;
|
|
float f1 = Lerp(player->field_B9C, player->field_BA0, f);
|
|
float f2 = Lerp(player->field_118, player->field_11C, f);
|
|
// @NOTE: Multiplying by M_PI inside of the paren makes it stuttery for some reason? Anyways it works now :)
|
|
float f3 = -(player->field_94 + (player->field_94 - player->field_90) * f) * float(M_PI);
|
|
float f4 = Mth::sin(f3);
|
|
float f5 = Mth::cos(f3);
|
|
glTranslatef((f4 * f1) * 0.5f, -fabsf(f5 * f1), 0.0f);
|
|
float f6 = Mth::sin(f3);
|
|
glRotatef((f6 * f1) * 3.0f, 0.0f, 0.0f, 1.0f);
|
|
float f7 = Mth::cos(f3 - 0.2f);
|
|
glRotatef(fabsf(f7 * f1) * 5.0f, 1.0f, 0.0f, 0.0f);
|
|
glRotatef(f2, 1.0f, 0.0f, 0.0f);
|
|
}
|
|
|
|
void GameRenderer::setupClearColor(float f)
|
|
{
|
|
Minecraft* pMC = m_pMinecraft;
|
|
Level* pLevel = pMC->m_pLevel;
|
|
Mob* pMob = pMC->m_pMobPersp;
|
|
|
|
float x1 = 1.0f - powf(1.0f / float(4 - pMC->getOptions()->m_iViewDistance), 0.25f);
|
|
|
|
Vec3 skyColor = pLevel->getSkyColor(pMob, f), fogColor = pLevel->getFogColor(f);
|
|
|
|
//@BUG: double set to these?
|
|
field_60 = fogColor.x;
|
|
field_64 = fogColor.y;
|
|
|
|
field_60 = fogColor.x + (skyColor.x - fogColor.x) * x1;
|
|
field_64 = fogColor.y + (skyColor.y - fogColor.y) * x1;
|
|
field_68 = fogColor.z + (skyColor.z - fogColor.z) * x1;
|
|
|
|
if (pMob->isUnderLiquid(Material::water))
|
|
{
|
|
field_60 = 0.02f;
|
|
field_64 = 0.02f;
|
|
field_68 = 0.2f;
|
|
}
|
|
else if (pMob->isUnderLiquid(Material::lava))
|
|
{
|
|
field_60 = 0.6f;
|
|
field_64 = 0.1f;
|
|
field_68 = 0.0f;
|
|
}
|
|
|
|
float x2 = field_6C + (field_70 - field_6C) * f;
|
|
|
|
field_60 *= x2;
|
|
field_64 *= x2;
|
|
field_68 *= x2;
|
|
|
|
if (pMC->getOptions()->m_bAnaglyphs)
|
|
{
|
|
float r = (field_60 * 30.0f + field_64 * 59.0f + field_68 * 11.0f) / 100.0f;
|
|
float g = (field_60 * 30.0f + field_64 * 70.0f) / 100.0f;
|
|
float b = (field_60 * 30.0f + field_68 * 70.0f) / 100.0f;
|
|
|
|
field_60 = r;
|
|
field_64 = g;
|
|
field_68 = b;
|
|
}
|
|
|
|
glClearColor(field_60, field_64, field_68, 1.0f);
|
|
}
|
|
|
|
#ifndef ORIGINAL_CODE
|
|
void GameRenderer::renderNoCamera()
|
|
{
|
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
#endif
|
|
|
|
void GameRenderer::setupFog(int i)
|
|
{
|
|
float fog_color[4];
|
|
fog_color[0] = field_60;
|
|
fog_color[1] = field_64;
|
|
fog_color[2] = field_68;
|
|
fog_color[3] = 1.0f;
|
|
|
|
glFogfv(GL_FOG_COLOR, fog_color);
|
|
glNormal3f(0.0f, -1.0f, 0.0f);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
if (m_pMinecraft->m_pMobPersp->isUnderLiquid(Material::water))
|
|
{
|
|
#if defined(ORIGINAL_CODE) || defined(__ANDROID__)
|
|
glFogx(GL_FOG_MODE, GL_EXP);
|
|
#else
|
|
glFogi(GL_FOG_MODE, GL_EXP);
|
|
#endif
|
|
|
|
glFogf(GL_FOG_DENSITY, 0.1f);
|
|
}
|
|
else if (m_pMinecraft->m_pMobPersp->isUnderLiquid(Material::lava))
|
|
{
|
|
#if defined(ORIGINAL_CODE) || defined(__ANDROID__)
|
|
glFogx(GL_FOG_MODE, GL_EXP);
|
|
#else
|
|
glFogi(GL_FOG_MODE, GL_EXP);
|
|
#endif
|
|
|
|
glFogf(GL_FOG_DENSITY, 2.0f);
|
|
}
|
|
else
|
|
{
|
|
#if defined(ORIGINAL_CODE) || defined(__ANDROID__)
|
|
glFogx(GL_FOG_MODE, GL_LINEAR);
|
|
#else
|
|
glFogi(GL_FOG_MODE, GL_LINEAR);
|
|
#endif
|
|
|
|
glFogf(GL_FOG_START, field_8 * 0.25f);
|
|
glFogf(GL_FOG_END, field_8);
|
|
if (i < 0)
|
|
{
|
|
glFogf(GL_FOG_START, 0.0f);
|
|
glFogf(GL_FOG_END, field_8 * 0.8f);
|
|
}
|
|
|
|
if (m_pMinecraft->m_pLevel->m_pDimension->field_C)
|
|
{
|
|
glFogf(GL_FOG_START, 0.0f);
|
|
}
|
|
|
|
}
|
|
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
}
|
|
|
|
float GameRenderer::getFov(float f)
|
|
{
|
|
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
|
|
|
float x1 = 70.0f;
|
|
|
|
if (pMob->isUnderLiquid(Material::water))
|
|
x1 = 60.0f;
|
|
|
|
if (pMob->m_health <= 0)
|
|
{
|
|
float x2 = 1.0f + (-500.0f / ((pMob->field_110 + f) + 500.0f));
|
|
x1 /= (1.0f + 2.0f * x2);
|
|
}
|
|
|
|
return field_54 + x1 + f * (field_50 - field_54);
|
|
}
|
|
|
|
void GameRenderer::renderLevel(float f)
|
|
{
|
|
if (!m_pMinecraft->m_pMobPersp)
|
|
{
|
|
m_pMinecraft->m_pMobPersp = m_pMinecraft->m_pLocalPlayer;
|
|
|
|
if (!m_pMinecraft->m_pMobPersp)
|
|
{
|
|
#ifndef ORIGINAL_CODE
|
|
renderNoCamera();
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
|
|
pick(f);
|
|
|
|
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
|
Vec3 fCamPos;
|
|
|
|
fCamPos.x = pMob->field_98.x + (pMob->m_pos.x - pMob->field_98.x) * f;
|
|
fCamPos.y = pMob->field_98.y + (pMob->m_pos.y - pMob->field_98.y) * f;
|
|
fCamPos.z = pMob->field_98.z + (pMob->m_pos.z - pMob->field_98.z) * f;
|
|
|
|
bool bAnaglyph = m_pMinecraft->getOptions()->m_bAnaglyphs;
|
|
|
|
LevelRenderer* pLR = m_pMinecraft->m_pLevelRenderer;
|
|
ParticleEngine* pPE = m_pMinecraft->m_pParticleEngine;
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
if (bAnaglyph)
|
|
{
|
|
if (i > 0)
|
|
glColorMask(true, false, false, false);
|
|
else
|
|
glColorMask(false, true, true, false);
|
|
}
|
|
|
|
glViewport(0, 0, Minecraft::width, Minecraft::height);
|
|
setupClearColor(f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
setupCamera(f, i);
|
|
saveMatrices();
|
|
|
|
/*
|
|
if (m_pMinecraft->getOptions()->m_iViewDistance <= 1)
|
|
{
|
|
#ifndef ORIGINAL_CODE
|
|
// @NOTE: For whatever reason, Minecraft doesn't enable GL_FOG right away.
|
|
// It appears to work in bluestacks for whatever reason though...
|
|
glEnable(GL_FOG);
|
|
#endif
|
|
setupFog(-1);
|
|
pLR->renderSky(f);
|
|
}
|
|
*/
|
|
|
|
glEnable(GL_FOG);
|
|
setupFog(1);
|
|
|
|
if (m_pMinecraft->getOptions()->m_bAmbientOcclusion)
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
Frustum& frust = Frustum::frustum;
|
|
Frustum::doOurJobInGameRenderer();
|
|
|
|
FrustumCuller frustumCuller;
|
|
frustumCuller.m_frustumData.x = frust;
|
|
frustumCuller.prepare(fCamPos.x, fCamPos.y, fCamPos.z);
|
|
|
|
pLR->cull(&frustumCuller, f);
|
|
pLR->updateDirtyChunks(pMob, false);
|
|
|
|
// TODO[v0.6.1]: what is (this+4)+63 (byte)?
|
|
prepareAndRenderClouds(pLR, f);
|
|
|
|
setupFog(0);
|
|
glEnable(GL_FOG);
|
|
|
|
m_pMinecraft->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME);
|
|
// render the opaque layer
|
|
pLR->render(pMob, 0, f);
|
|
|
|
glShadeModel(GL_FLAT);
|
|
pLR->renderEntities(pMob->getPos(f), &frustumCuller, f);
|
|
pPE->render(pMob, f);
|
|
|
|
glEnable(GL_ALPHA);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
setupFog(0);
|
|
|
|
#ifndef ORIGINAL_CODE
|
|
glShadeModel(GL_SMOOTH);
|
|
#endif
|
|
|
|
glEnable(GL_BLEND);
|
|
glDisable(GL_CULL_FACE);
|
|
// glDepthMask(false); -- added in 0.1.1j. Introduces more issues than fixes
|
|
|
|
// render the alpha layer
|
|
m_pMinecraft->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME);
|
|
pLR->render(pMob, 1, f);
|
|
|
|
glDepthMask(true);
|
|
|
|
#ifndef ORIGINAL_CODE
|
|
glShadeModel(GL_FLAT);
|
|
#endif
|
|
glEnable(GL_CULL_FACE);
|
|
glDisable(GL_BLEND);
|
|
|
|
if (field_44 == 1.0f && pMob->isPlayer() && m_pMinecraft->m_hitResult.m_hitType != HitResult::NONE && !pMob->isUnderLiquid(Material::water))
|
|
{
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
if (m_pMinecraft->getOptions()->m_bBlockOutlines)
|
|
pLR->renderHitOutline((Player*)pMob, m_pMinecraft->m_hitResult, 0, nullptr, f);
|
|
else
|
|
pLR->renderHitSelect((Player*)pMob, m_pMinecraft->m_hitResult, 0, nullptr, f);
|
|
|
|
// added by iProgramInCpp - renders the cracks
|
|
pLR->renderHit((Player*)pMob, m_pMinecraft->m_hitResult, 0, nullptr, f);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
}
|
|
|
|
// @BUG?
|
|
glDisable(GL_FOG);
|
|
|
|
if (field_44 == 1.0f)
|
|
{
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
renderItemInHand(f, i);
|
|
}
|
|
|
|
if (!bAnaglyph)
|
|
break;
|
|
}
|
|
|
|
if (bAnaglyph)
|
|
glColorMask(true, true, true, false);
|
|
}
|
|
|
|
void GameRenderer::render(float f)
|
|
{
|
|
if (m_pMinecraft->m_pLocalPlayer && m_pMinecraft->m_bGrabbedMouse)
|
|
{
|
|
Minecraft *pMC = m_pMinecraft;
|
|
pMC->m_mouseHandler.poll();
|
|
|
|
float multPitch, diff_field_84;
|
|
if (pMC->m_mouseHandler.smoothTurning())
|
|
{
|
|
multPitch = -1.0f;
|
|
float mult1 = 2.0f * (0.2f + pMC->getOptions()->field_8 * 0.6f);
|
|
mult1 = mult1 * mult1 * mult1;
|
|
|
|
float xd = 4.0f * mult1 * pMC->m_mouseHandler.m_delta.x;
|
|
float yd = 4.0f * mult1 * pMC->m_mouseHandler.m_delta.y;
|
|
|
|
float old_field_84 = field_84;
|
|
field_84 = float(field_C) + f;
|
|
diff_field_84 = field_84 - old_field_84;
|
|
field_74 += xd;
|
|
field_78 += yd;
|
|
|
|
if (diff_field_84 > 3.0f)
|
|
diff_field_84 = 3.0f;
|
|
|
|
if (pMC->getOptions()->m_bInvertMouse)
|
|
multPitch = 1.0f;
|
|
|
|
if (!pMC->getOptions()->field_240)
|
|
{
|
|
// @TODO: untangle this code
|
|
float v17 = xd + field_14;
|
|
float v18 = field_18;
|
|
float v19 = field_1C;
|
|
field_14 = v17;
|
|
float v20 = mult1 * 0.25f * (v17 - v18);
|
|
float v21 = v19 + (v20 - v19) * 0.5f;
|
|
field_1C = v21;
|
|
if ((v20 <= 0.0 || v20 <= v21) && (v20 >= 0.0 || v20 >= v21))
|
|
v21 = mult1 * 0.25f * (v17 - v18);
|
|
float v22 = yd + field_20;
|
|
field_18 = v18 + v21;
|
|
float v23 = field_24;
|
|
field_20 = v22;
|
|
float v24 = mult1 * 0.15f * (v22 - v23);
|
|
float v25 = field_28 + (v24 - field_28) * 0.5f;
|
|
field_28 = v25;
|
|
if ((v24 <= 0.0 || v24 <= v25) && (v24 >= 0.0 || v24 >= v25))
|
|
v25 = v24;
|
|
field_24 = v23 + v25;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
multPitch = -1.0f;
|
|
if (pMC->getOptions()->m_bInvertMouse)
|
|
multPitch = 1.0f;
|
|
|
|
diff_field_84 = 1.0f;
|
|
field_7C = pMC->m_mouseHandler.m_delta.x;
|
|
field_80 = pMC->m_mouseHandler.m_delta.y;
|
|
}
|
|
|
|
pMC->m_pLocalPlayer->turn(diff_field_84 * field_7C, diff_field_84 * multPitch * field_80);
|
|
}
|
|
|
|
int mouseX = int(Mouse::getX() * Gui::InvGuiScale);
|
|
int mouseY = int(Mouse::getY() * Gui::InvGuiScale);
|
|
|
|
if (m_pMinecraft->isTouchscreen())
|
|
{
|
|
int pointerId = Multitouch::getFirstActivePointerIdExThisUpdate();
|
|
if (pointerId < 0)
|
|
{
|
|
mouseX = -9999;
|
|
mouseY = -9999;
|
|
}
|
|
else
|
|
{
|
|
mouseX = int(float(Multitouch::getX(pointerId)) * Gui::InvGuiScale);
|
|
mouseY = int(float(Multitouch::getY(pointerId)) * Gui::InvGuiScale);
|
|
}
|
|
}
|
|
|
|
if (m_pMinecraft->isLevelGenerated())
|
|
{
|
|
if (t_keepPic < 0)
|
|
{
|
|
renderLevel(f);
|
|
if (m_pMinecraft->getOptions()->m_bDontRenderGui)
|
|
{
|
|
if (!m_pMinecraft->m_pScreen)
|
|
return;
|
|
}
|
|
|
|
m_pMinecraft->m_gui.render(f, m_pMinecraft->m_pScreen != nullptr, mouseX, mouseY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
glViewport(0, 0, Minecraft::width, Minecraft::height);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
setupGuiScreen();
|
|
}
|
|
|
|
if (m_pMinecraft->m_pLocalPlayer &&
|
|
m_pMinecraft->m_pLocalPlayer->m_pMoveInput)
|
|
m_pMinecraft->m_pLocalPlayer->m_pMoveInput->render(f);
|
|
|
|
if (m_pMinecraft->m_pScreen)
|
|
{
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
m_pMinecraft->m_pScreen->onRender(mouseX, mouseY, f);
|
|
|
|
if (m_pMinecraft->m_pScreen && !m_pMinecraft->m_pScreen->isInGameScreen())
|
|
{
|
|
#ifdef ORIGINAL_CODE
|
|
// force some lag for some reason. I guess it's to make it spend more time actually generating the world?
|
|
sleepMs(15);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
std::stringstream debugText;
|
|
debugText << "ReMinecraftPE " << m_pMinecraft->getVersionString();
|
|
debugText << "\n" << m_shownFPS << " fps, " << m_shownChunkUpdates << " chunk updates";
|
|
|
|
if (m_pMinecraft->getOptions()->m_bDebugText)
|
|
{
|
|
if (m_pMinecraft->m_pLocalPlayer)
|
|
{
|
|
char posStr[96];
|
|
Vec3 pos = m_pMinecraft->m_pLocalPlayer->getPos(f);
|
|
sprintf(posStr, "%.2f, %.2f, %.2f", pos.x, pos.y, pos.z);
|
|
|
|
debugText << "\npos: " << posStr;
|
|
debugText << "\nentities: " << m_pMinecraft->m_pLevel->m_entities.size();
|
|
debugText << "\n" << m_pMinecraft->m_pLevelRenderer->gatherStats1();
|
|
}
|
|
|
|
m_pMinecraft->m_pFont->drawShadow(debugText.str(), 2, 2, 0xFFFFFF);
|
|
}
|
|
|
|
int timeMs = getTimeMs();
|
|
if (timeMs - m_lastUpdatedMS >= 1000)
|
|
{
|
|
m_lastUpdatedMS = timeMs;
|
|
m_shownFPS = m_pMinecraft->getFpsIntlCounter();
|
|
m_shownChunkUpdates = Chunk::updates;
|
|
Chunk::updates = 0;
|
|
}
|
|
}
|
|
|
|
void GameRenderer::tick()
|
|
{
|
|
--t_keepPic;
|
|
#ifndef ORIGINAL_CODE
|
|
// @BUG: If the game is left on for approximately 1,242 days, the counter will underflow,
|
|
// causing the screen to appear frozen, and the level to not render.
|
|
if (t_keepPic < -100)
|
|
t_keepPic = -100;
|
|
#endif
|
|
|
|
if (!m_pMinecraft->m_pLocalPlayer)
|
|
return;
|
|
|
|
if (--t_keepHitResult == 0)
|
|
m_pMinecraft->m_hitResult.m_hitType = HitResult::NONE;
|
|
|
|
#ifndef ORIGINAL_CODE
|
|
// Not harmless to let it underflow, but we won't anyway
|
|
if (t_keepHitResult < -100)
|
|
t_keepHitResult = -100;
|
|
#endif
|
|
|
|
float x1 = powf(fabsf(field_74), 1.2f);
|
|
field_7C = x1 * 0.4f;
|
|
if (field_74 < 0.0f)
|
|
field_7C = -field_7C;
|
|
|
|
float x2 = powf(fabsf(field_78), 1.2f);
|
|
field_80 = x2 * 0.4f;
|
|
if (field_78 < 0.0f)
|
|
field_80 = -field_80;
|
|
|
|
field_74 = 0.0f;
|
|
field_78 = 0.0f;
|
|
field_6C = field_70;
|
|
field_30 = field_2C;
|
|
field_38 = field_34;
|
|
field_40 = field_3C;
|
|
field_54 = field_50;
|
|
field_5C = field_58;
|
|
|
|
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
|
if (!pMob)
|
|
{
|
|
pMob = m_pMinecraft->m_pMobPersp = m_pMinecraft->m_pLocalPlayer;
|
|
}
|
|
|
|
float bright = m_pMinecraft->m_pLevel->getBrightness(Mth::floor(pMob->m_pos.x), Mth::floor(pMob->m_pos.y), Mth::floor(pMob->m_pos.z));
|
|
float x3 = float(3 - m_pMinecraft->getOptions()->m_iViewDistance);
|
|
|
|
field_C++;
|
|
|
|
float x4 = x3 / 3.0f;
|
|
float x5 = (x4 + bright * (1.0f - x4) - field_70) * 0.1f;
|
|
|
|
field_70 += x5;
|
|
|
|
m_pItemInHandRenderer->tick();
|
|
}
|
|
|
|
void GameRenderer::renderItemInHand(float f, int i)
|
|
{
|
|
glLoadIdentity();
|
|
|
|
if (m_pMinecraft->getOptions()->m_bAnaglyphs)
|
|
glTranslatef(float(2 * i - 1) * 0.1f, 0.0f, 0.0f);
|
|
|
|
glPushMatrix();
|
|
bobHurt(f);
|
|
|
|
if (m_pMinecraft->getOptions()->m_bViewBobbing)
|
|
bobView(f);
|
|
|
|
if (!m_pMinecraft->getOptions()->m_bThirdPerson && !m_pMinecraft->getOptions()->m_bDontRenderGui)
|
|
m_pItemInHandRenderer->render(f);
|
|
|
|
glPopMatrix();
|
|
|
|
if (!m_pMinecraft->getOptions()->m_bThirdPerson)
|
|
{
|
|
m_pItemInHandRenderer->renderScreenEffect(f);
|
|
bobHurt(f);
|
|
}
|
|
|
|
if (m_pMinecraft->getOptions()->m_bViewBobbing)
|
|
bobView(f);
|
|
}
|
|
|
|
void GameRenderer::prepareAndRenderClouds(LevelRenderer* pLR, float f)
|
|
{
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
gluPerspective(getFov(f), float(Minecraft::width) / float(Minecraft::height), 0.05f, field_8 * 512.0f);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
setupFog(0);
|
|
glDepthMask(false);
|
|
glEnable(GL_FOG);
|
|
glFogf(GL_FOG_START, field_8 * 0.2f);
|
|
glFogf(GL_FOG_END, field_8 * 0.75f);
|
|
pLR->renderSky(f);
|
|
glFogf(GL_FOG_START, field_8 * 4.2f * 0.6f);
|
|
glFogf(GL_FOG_END, field_8 * 4.2f);
|
|
pLR->renderClouds(f);
|
|
glFogf(GL_FOG_START, field_8 * 0.6f);
|
|
glFogf(GL_FOG_END, field_8);
|
|
glDisable(GL_FOG);
|
|
glDepthMask(true);
|
|
setupFog(1);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
void GameRenderer::onGraphicsReset()
|
|
{
|
|
|
|
}
|
|
|
|
void GameRenderer::pick(float f)
|
|
{
|
|
if (!m_pMinecraft->m_pMobPersp || !m_pMinecraft->m_pLevel)
|
|
return;
|
|
|
|
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
|
HitResult& mchr = m_pMinecraft->m_hitResult;
|
|
float dist = m_pMinecraft->m_pGameMode->getPickRange();
|
|
bool isFirstPerson = !m_pMinecraft->getOptions()->m_bThirdPerson;
|
|
|
|
if (m_pMinecraft->isTouchscreen())
|
|
{
|
|
Vec3 mobPos = pMob->getPos(f);
|
|
Vec3 foundPosNear, foundPosFar;
|
|
bool flag = true;
|
|
float offset = isFirstPerson ? 6.0f : 12.0f;
|
|
|
|
if (m_pMinecraft->m_pInputHolder->allowPicking())
|
|
{
|
|
int viewport[4] = { 0 };
|
|
viewport[2] = Minecraft::width;
|
|
viewport[3] = Minecraft::height;
|
|
float obj_coord[3] = { 0 };
|
|
|
|
if (glhUnProjectf(m_pMinecraft->m_pInputHolder->m_feedbackX,
|
|
Minecraft::height - m_pMinecraft->m_pInputHolder->m_feedbackY,
|
|
1.0f,
|
|
m_matrix_model_view,
|
|
m_matrix_projection,
|
|
viewport,
|
|
obj_coord))
|
|
{
|
|
foundPosFar = mobPos + Vec3(obj_coord[0], obj_coord[1], obj_coord[2]);
|
|
|
|
glhUnProjectf(m_pMinecraft->m_pInputHolder->m_feedbackX,
|
|
Minecraft::height - m_pMinecraft->m_pInputHolder->m_feedbackY,
|
|
0.0f,
|
|
m_matrix_model_view,
|
|
m_matrix_projection,
|
|
viewport,
|
|
obj_coord);
|
|
|
|
foundPosNear = mobPos + Vec3(obj_coord[0], obj_coord[1], obj_coord[2]);
|
|
|
|
Vec3 diff = foundPosFar - foundPosNear;
|
|
Vec3 normDiff = diff.normalize();
|
|
Vec3 normScaledDiff = normDiff.scale(offset);
|
|
|
|
mobPos = foundPosNear + normScaledDiff;
|
|
|
|
foundPosFar = mobPos;
|
|
}
|
|
|
|
// keep the hit result forever
|
|
t_keepHitResult = -1;
|
|
}
|
|
else
|
|
{
|
|
t_keepHitResult = 1; // keep the tick result for exactly one frame
|
|
flag = false;
|
|
}
|
|
|
|
if (flag)
|
|
{
|
|
if (isFirstPerson)
|
|
{
|
|
mchr = m_pMinecraft->m_pLevel->clip(foundPosNear, foundPosFar, false);
|
|
}
|
|
else
|
|
{
|
|
HitResult hr = m_pMinecraft->m_pLevel->clip(foundPosNear, foundPosFar, false);
|
|
|
|
float diffX = float(hr.m_tileX) - m_pMinecraft->m_pMobPersp->m_pos.x;
|
|
float diffY = float(hr.m_tileY) - m_pMinecraft->m_pMobPersp->m_pos.y;
|
|
float diffZ = float(hr.m_tileZ) - m_pMinecraft->m_pMobPersp->m_pos.z;
|
|
|
|
if (hr.m_hitType == HitResult::NONE || diffX * diffX + diffY * diffY + diffZ * diffZ > offset * offset)
|
|
mchr.m_hitType = HitResult::NONE;
|
|
else
|
|
mchr = hr;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// easy case: pick from the middle of the screen
|
|
HitResult hrMob = pMob->pick(dist, f);
|
|
mchr = hrMob;
|
|
}
|
|
|
|
Vec3 mobPos = pMob->getPos(f);
|
|
|
|
if (m_pMinecraft->m_hitResult.m_hitType != HitResult::NONE)
|
|
dist = mchr.m_hitPos.distanceTo(mobPos);
|
|
|
|
if (m_pMinecraft->m_pGameMode->isCreativeType())
|
|
dist = 32.0f;
|
|
else if (dist > 3.0f)
|
|
dist = 3.0f;
|
|
|
|
Vec3 view = pMob->getViewVector(f);
|
|
Vec3 exp = view * dist;
|
|
Vec3 limit = mobPos + view * dist;
|
|
|
|
field_10 = nullptr;
|
|
|
|
AABB scanAABB = pMob->m_hitbox;
|
|
|
|
if (exp.x < 0) scanAABB.min.x += exp.x;
|
|
if (exp.x > 0) scanAABB.max.x += exp.x;
|
|
if (exp.y < 0) scanAABB.min.y += exp.y;
|
|
if (exp.y > 0) scanAABB.max.y += exp.y;
|
|
if (exp.z < 0) scanAABB.min.z += exp.z;
|
|
if (exp.z > 0) scanAABB.max.z += exp.z;
|
|
|
|
scanAABB.grow(1, 1, 1);
|
|
|
|
EntityVector* pEnts = m_pMinecraft->m_pLevel->getEntities(pMob, scanAABB);
|
|
|
|
float fDist = 0.0f;
|
|
for (int i = 0; i < int(pEnts->size()); i++)
|
|
{
|
|
Entity *pEnt = (*pEnts)[i];
|
|
if (!pEnt->isPickable())
|
|
continue;
|
|
|
|
AABB checkAABB = pEnt->m_hitbox;
|
|
checkAABB.grow(pEnt->getPickRadius());
|
|
|
|
HitResult hrMobChk = checkAABB.clip(mobPos, limit);
|
|
|
|
if (checkAABB.contains(mobPos))
|
|
{
|
|
if (fDist >= 0.0f)
|
|
{
|
|
//this is it brother
|
|
field_10 = pEnt;
|
|
fDist = 0.0f;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (hrMobChk.m_hitType != HitResult::NONE)
|
|
{
|
|
float dX = hrMobChk.m_hitPos.x - mobPos.x;
|
|
float dY = hrMobChk.m_hitPos.y - mobPos.y;
|
|
float dZ = hrMobChk.m_hitPos.z - mobPos.z;
|
|
float fNewDist = sqrtf(dX * dX + dY * dY + dZ * dZ);
|
|
|
|
if (fDist > fNewDist || fDist == 0.0f)
|
|
{
|
|
field_10 = pEnt;
|
|
fDist = fNewDist;
|
|
}
|
|
}
|
|
}
|
|
|
|
// picked entities take priority over tiles (?!)
|
|
if (field_10)
|
|
{
|
|
m_pMinecraft->m_hitResult = HitResult(field_10);
|
|
return;
|
|
}
|
|
|
|
if (m_pMinecraft->m_hitResult.m_hitType != HitResult::NONE || view.y >= -0.7f)
|
|
return;
|
|
|
|
mobPos = pMob->getPos(f);
|
|
Vec3 checkVec = mobPos;
|
|
checkVec.translate(0, -2, 0);
|
|
|
|
HitResult hrLevelChk = m_pMinecraft->m_pLevel->clip(mobPos, checkVec);
|
|
|
|
if (hrLevelChk.m_hitType == HitResult::NONE)
|
|
return;
|
|
|
|
mchr = hrLevelChk;
|
|
mchr.m_bUnk24 = true;
|
|
|
|
if (fabsf(view.x) <= fabsf(view.z))
|
|
{
|
|
m_pMinecraft->m_hitResult.m_hitSide = view.z >= 0.0f ? HitResult::MAXZ : HitResult::MINZ;
|
|
}
|
|
else
|
|
{
|
|
m_pMinecraft->m_hitResult.m_hitSide = view.x >= 0.0f ? HitResult::MAXX : HitResult::MINX;
|
|
}
|
|
}
|
|
|