the whole game

This commit is contained in:
Kolyah35
2026-03-02 22:04:18 +03:00
parent 816e9060b4
commit f0617a5d22
2069 changed files with 581500 additions and 0 deletions

View File

@@ -0,0 +1,952 @@
#include "GameRenderer.h"
#include "gles.h"
#include "../../util/PerfTimer.h"
#include "LevelRenderer.h"
#include "ItemInHandRenderer.h"
#include "culling/AllowAllCuller.h"
#include "culling/FrustumCuller.h"
#include "entity/EntityRenderDispatcher.h"
#include "../Minecraft.h"
#include "../gamemode/GameMode.h"
#include "../particle/ParticleEngine.h"
#include "../player/LocalPlayer.h"
#include "../gui/Screen.h"
#include "../../world/level/Level.h"
#include "../../world/entity/Mob.h"
#include "../../world/level/chunk/ChunkCache.h"
#include "../../world/level/material/Material.h"
#include "../../world/Facing.h"
#include "../../platform/input/Controller.h"
#include "../../platform/input/Mouse.h"
#include "../../platform/input/Multitouch.h"
#include "../../NinecraftApp.h"
#include "../../world/level/tile/Tile.h"
#include "../player/input/IInputHolder.h"
#include "Textures.h"
#include "../gui/components/ImageButton.h"
#include "Tesselator.h"
static int _shTicks = -1;
GameRenderer::GameRenderer( Minecraft* mc )
: mc(mc),
renderDistance(0),
_tick(0),
_lastTickT(0),
fovOffset(0),
fovOffsetO(0),
fov(1), oFov(1),
_setupCameraFov(0),
zoom(1), zoom_x(0), zoom_y(0),
cameraRoll(0), cameraRollO(0),
pickDirection(1, 0, 0),
thirdDistance(4), thirdDistanceO(4),
thirdRotation(0), thirdRotationO(0),
thirdTilt(0), thirdTiltO(0),
fogBr(0), fogBrO(0),
fr(0), fg(0), fb(0),
_rotX(0), _rotY(0),
_rotXlast(0), _rotYlast(0),
useScreenScissor(false)
{
saveMatrices();
itemInHandRenderer = new ItemInHandRenderer(mc);
EntityRenderDispatcher* e = EntityRenderDispatcher::getInstance();
e->itemInHandRenderer = itemInHandRenderer;
e->textures = mc->textures;
}
GameRenderer::~GameRenderer() {
delete itemInHandRenderer;
}
void renderCursor(float x, float y, Minecraft* minecraft) {
Tesselator& t = Tesselator::instance;
minecraft->textures->loadAndBindTexture("gui/cursor.png");
glEnable(GL_BLEND);
const float s = 32;
const float width = 16;
const float height = 16;
t.begin();
t.color(0xffffffff);
t.vertexUV(x, y + (float)height, 0, 0, 1);
t.vertexUV(x + (float)width, y + (float)height, 0, 1, 1);
t.vertexUV(x + (float)width, y, 0, 1, 0);
t.vertexUV(x, y, 0, 0, 0);
t.draw();
glDisable(GL_BLEND);
}
/*private*/
void GameRenderer::setupCamera(float a, int eye) {
renderDistance = (float) (16 * 16 >> (mc->options.viewDistance));
#if defined(ANDROID)
if (mc->isPowerVR() && mc->options.viewDistance <= 2)
renderDistance *= 0.8f;
#endif
glMatrixMode(GL_PROJECTION);
glLoadIdentity2();
float stereoScale = 0.07f;
if (mc->options.anaglyph3d) glTranslatef2(-(eye * 2 - 1) * stereoScale, 0, 0);
if (zoom != 1) {
glTranslatef2((float) zoom_x, (float) -zoom_y, 0);
glScalef2(zoom, zoom, 1);
gluPerspective(_setupCameraFov = getFov(a, true), mc->width / (float) mc->height, 0.05f, renderDistance);
} else {
gluPerspective(_setupCameraFov = getFov(a, true), mc->width / (float) mc->height, 0.05f, renderDistance);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity2();
if (mc->options.anaglyph3d) glTranslatef2((eye * 2 - 1) * 0.10f, 0, 0);
bobHurt(a);
if (mc->options.bobView) bobView(a);
moveCameraToPlayer(a);
}
extern int _t_keepPic;
/*public*/
void GameRenderer::render(float a) {
TIMER_PUSH("mouse");
if (mc->player && mc->mouseGrabbed) {
mc->mouseHandler.poll();
//printf("Controller.x,y : %f,%f\n", Controller::getX(0), Controller::getY(0));
float ss = mc->options.sensitivity * 0.6f + 0.2f;
float sens = (ss * ss * ss) * 8;
float xo = mc->mouseHandler.xd * sens * 4.f;
float yo = mc->mouseHandler.yd * sens * 4.f;
const float now = _tick + a;
float deltaT = now - _lastTickT;
if (deltaT > 3.0f) deltaT = 3.0f;
_lastTickT = now;
_rotX += xo;
_rotY += yo;
int yAxis = -1;
if (mc->options.invertYMouse) yAxis = 1;
bool screenCovering = mc->screen && !mc->screen->passEvents;
if (!screenCovering)
{
mc->player->turn(deltaT * _rotXlast, deltaT * _rotYlast * yAxis);
}
}
int xMouse = (int)(Mouse::getX() * Gui::InvGuiScale);
int yMouse = (int)(Mouse::getY() * Gui::InvGuiScale);
if (mc->useTouchscreen()) {
const int pid = Multitouch::getFirstActivePointerIdExThisUpdate();
if (pid >= 0) {
xMouse = (int)(Multitouch::getX(pid) * Gui::InvGuiScale);
yMouse = (int)(Multitouch::getY(pid) * Gui::InvGuiScale);
} else {
xMouse = -9999;
yMouse = -9999;
}
}
TIMER_POP();
bool hasClearedColorBuffer = false;
bool hasSetupGuiScreen = false;
useScreenScissor = false;
if (mc->isLevelGenerated()) {
TIMER_PUSH("level");
if (_t_keepPic < 0) {
if (!(mc->screen && !mc->screen->renderGameBehind())) {
if (mc->screen && mc->screen->hasClippingArea(screenScissorArea))
useScreenScissor = true;
renderLevel(a);
hasClearedColorBuffer = true;
if (!mc->options.hideGui) {
TIMER_POP_PUSH("gui");
setupGuiScreen(false);
hasSetupGuiScreen = true;
mc->gui.render(a, mc->screen != NULL, xMouse, yMouse);
}
}}
TIMER_POP();
} else {
glViewport(0, 0, mc->width, mc->height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity2();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity2();
setupGuiScreen(true);
hasSetupGuiScreen = true;
hasClearedColorBuffer = true;
}
//@todo
if (!hasSetupGuiScreen)
setupGuiScreen(!hasClearedColorBuffer);
if (mc->player && mc->screen == NULL) {
if (mc->inputHolder) mc->inputHolder->render(a);
if (mc->player->input) mc->player->input->render(a);
}
if (mc->screen != NULL) {
if (useScreenScissor)
glDisable2(GL_SCISSOR_TEST);
mc->screen->render(xMouse, yMouse, a);
#ifdef RPI
renderCursor(xMouse, yMouse, mc);
#endif
// Screen might have been removed, so check it again
if (mc->screen && !mc->screen->isInGameScreen())
sleepMs(15);
}
}
/*public*/
void GameRenderer::renderLevel(float a) {
if (mc->cameraTargetPlayer == NULL) {
if (mc->player)
{
mc->cameraTargetPlayer = mc->player;
}
else
{
return;
}
}
TIMER_PUSH("pick");
pick(a);
Mob* cameraEntity = mc->cameraTargetPlayer;
LevelRenderer* levelRenderer = mc->levelRenderer;
ParticleEngine* particleEngine = mc->particleEngine;
float xOff = cameraEntity->xOld + (cameraEntity->x - cameraEntity->xOld) * a;
float yOff = cameraEntity->yOld + (cameraEntity->y - cameraEntity->yOld) * a;
float zOff = cameraEntity->zOld + (cameraEntity->z - cameraEntity->zOld) * a;
for (int i = 0; i < 2; i++) {
if (mc->options.anaglyph3d) {
if (i == 0) glColorMask(false, true, true, false);
else glColorMask(true, false, false, false);
}
TIMER_POP_PUSH("clear");
glViewport(0, 0, mc->width, mc->height);
setupClearColor(a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable2(GL_CULL_FACE);
TIMER_POP_PUSH("camera");
setupCamera(a, i);
saveMatrices();
if (useScreenScissor) {
glEnable2(GL_SCISSOR_TEST);
glScissor( screenScissorArea.x, screenScissorArea.y,
screenScissorArea.w, screenScissorArea.h);
}
// if(mc->options.fancyGraphics) {
// setupFog(-1);
// TIMER_POP_PUSH("sky");
// glFogf(GL_FOG_START, renderDistance * 0.2f);
// glFogf(GL_FOG_END, renderDistance *0.75);
// levelRenderer->renderSky(a);
// glFogf(GL_FOG_START, renderDistance * 0.6f);
// glFogf(GL_FOG_END, renderDistance);
// }
glEnable2(GL_FOG);
setupFog(1);
if (mc->options.ambientOcclusion) {
glShadeModel2(GL_SMOOTH);
}
TIMER_POP_PUSH("frustrum");
FrustumCuller frustum;
frustum.prepare(xOff, yOff, zOff);
TIMER_POP_PUSH("culling");
mc->levelRenderer->cull(&frustum, a);
mc->levelRenderer->updateDirtyChunks(cameraEntity, false);
if(mc->options.fancyGraphics) {
prepareAndRenderClouds(levelRenderer, a);
}
setupFog(0);
glEnable2(GL_FOG);
mc->textures->loadAndBindTexture("terrain.png");
glDisable2(GL_ALPHA_TEST);
glDisable2(GL_BLEND);
glEnable2(GL_CULL_FACE);
TIMER_POP_PUSH("terrain-0");
levelRenderer->render(cameraEntity, 0, a);
TIMER_POP_PUSH("terrain-1");
glEnable2(GL_ALPHA_TEST);
levelRenderer->render(cameraEntity, 1, a);
glShadeModel2(GL_FLAT);
TIMER_POP_PUSH("entities");
mc->levelRenderer->renderEntities(cameraEntity->getPos(a), &frustum, a);
// setupFog(0);
TIMER_POP_PUSH("particles");
particleEngine->render(cameraEntity, a);
glDisable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
setupFog(0);
glEnable2(GL_BLEND);
glDisable2(GL_CULL_FACE);
glDepthMask(GL_FALSE);
glDisable2(GL_ALPHA_TEST);
mc->textures->loadAndBindTexture("terrain.png");
//if (mc->options.fancyGraphics) {
// glColorMask(false, false, false, false);
// int visibleWaterChunks = levelRenderer->render(cameraEntity, 1, a);
// glColorMask(true, true, true, true);
// if (mc->options.anaglyph3d) {
// if (i == 0) glColorMask(false, true, true, false);
// else glColorMask(true, false, false, false);
// }
// if (visibleWaterChunks > 0) {
// levelRenderer->renderSameAsLast(1, a);
// }
//} else
{
//glDepthRangef(0.1f, 1.0f);
//glDepthMask(GL_FALSE);
TIMER_POP_PUSH("terrain-water");
glEnable2(GL_DEPTH_TEST);
levelRenderer->render(cameraEntity, 2, a);
//glDepthRangef(0, 1);
}
glDepthMask(GL_TRUE);
glEnable2(GL_CULL_FACE);
glDisable2(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
if (/*!Minecraft::FLYBY_MODE &&*/ zoom == 1 && cameraEntity->isPlayer()) {
if (mc->hitResult.isHit() && !cameraEntity->isUnderLiquid(Material::water)) {
TIMER_POP_PUSH("select");
Player* player = (Player*) cameraEntity;
if (mc->useTouchscreen()) {
levelRenderer->renderHitSelect(player, mc->hitResult, 0, NULL, a); //player.inventory->getSelected(), a);
}
levelRenderer->renderHit(player, mc->hitResult, 0, NULL, a);//player->inventory.getSelected(), a);
}
}
glDisable2(GL_FOG);
//
// setupFog(0);
// glEnable2(GL_FOG);
//// levelRenderer->renderClouds(a);
// glDisable2(GL_FOG);
setupFog(1);
if (zoom == 1) {
TIMER_POP_PUSH("hand");
glClear(GL_DEPTH_BUFFER_BIT);
renderItemInHand(a, i);
}
if (!mc->options.anaglyph3d) {
TIMER_POP();
return;
}
}
glColorMask(true, true, true, false);
TIMER_POP();
}
void GameRenderer::tickFov() {
if (mc->cameraTargetPlayer != mc->player)
return;
oFov = fov;
fov += (mc->player->getFieldOfViewModifier() - fov) * 0.5f;
}
/*private*/
float GameRenderer::getFov(float a, bool applyEffects) {
Mob* player = mc->cameraTargetPlayer;
float fov = 70;
if (applyEffects)
fov *= this->oFov + (this->fov - this->oFov) * a;
if (player->isUnderLiquid(Material::water)) fov = 60;
if (player->health <= 0) {
float duration = player->deathTime + a;
fov /= ((1 - 500 / (duration + 500)) * 2.0f + 1);
}
return fov + fovOffsetO + (fovOffset - fovOffsetO) * a;
}
/*private*/
void GameRenderer::moveCameraToPlayer(float a) {
Entity* player = mc->cameraTargetPlayer;
float heightOffset = player->heightOffset - 1.62f;
float x = player->xo + (player->x - player->xo) * a;
float y = player->yo + (player->y - player->yo) * a - heightOffset;
//printf("camera y: %f\n", y);
float z = player->zo + (player->z - player->zo) * a;
//printf("rot: %f %f\n", cameraRollO, cameraRoll);
glRotatef2(cameraRollO + (cameraRoll - cameraRollO) * a, 0, 0, 1);
//LOGI("player. alive, removed: %d, %d\n", player->isAlive(), player->removed);
if(player->isPlayer() && ((Player*)player)->isSleeping()) {
heightOffset += 1.0;
glTranslatef(0.0f, 0.3f, 0);
if (!mc->options.fixedCamera) {
int t = mc->level->getTile(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
if (t == Tile::bed->id) {
int data = mc->level->getData(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
int direction = data & 3;
glRotatef(float(direction * 90), 0, 1, 0);
}
glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, -1, 0);
glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, -1, 0, 0);
}
} else if (mc->options.thirdPersonView/* || (player->isPlayer() && !player->isAlive())*/) {
float cameraDist = thirdDistanceO + (thirdDistance - thirdDistanceO) * a;
if (mc->options.fixedCamera) {
float rotationY = thirdRotationO + (thirdRotation - thirdRotationO) * a;
float xRot = thirdTiltO + (thirdTilt - thirdTiltO) * a;
glTranslatef2(0, 0, (float) -cameraDist);
glRotatef2(xRot, 1, 0, 0);
glRotatef2(rotationY, 0, 1, 0);
} else {
float yRot = player->yRot;
float xRot = player->xRot/* + 180.0f*/;
float xd = -Mth::sin(yRot / 180 * Mth::PI) * Mth::cos(xRot / 180 * Mth::PI) * cameraDist;
float zd = Mth::cos(yRot / 180 * Mth::PI) * Mth::cos(xRot / 180 * Mth::PI) * cameraDist;
float yd = -Mth::sin(xRot / 180 * Mth::PI) * cameraDist;
for (int i = 0; i < 8; i++) {
float xo = (float)((i & 1) * 2 - 1);
float yo = (float)(((i >> 1) & 1) * 2 - 1);
float zo = (float)(((i >> 2) & 1) * 2 - 1);
xo *= 0.1f;
yo *= 0.1f;
zo *= 0.1f;
HitResult hr = mc->level->clip(Vec3(x + xo, y + yo, z + zo), Vec3(x - xd + xo + zo, y - yd + yo, z - zd + zo)); // newTemp
if (hr.type != NO_HIT) {
float dist = hr.pos.distanceTo(Vec3(x, y, z)); // newTemp
if (dist < cameraDist) cameraDist = dist;
}
}
//glRotatef2(180, 0, 1, 0);
glRotatef2(player->xRot - xRot, 1, 0, 0);
glRotatef2(player->yRot - yRot, 0, 1, 0);
glTranslatef2(0, 0, (float) -cameraDist);
glRotatef2(yRot - player->yRot, 0, 1, 0);
glRotatef2(xRot - player->xRot, 1, 0, 0);
}
} else {
glTranslatef2(0, 0, -0.1f);
}
if (!mc->options.fixedCamera) {
glRotatef2(player->xRotO + (player->xRot - player->xRotO) * a, 1.0f, 0.0f, 0.0f);
glRotatef2(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0);
//if (_t_keepPic > 0)
}
glTranslatef2(0, heightOffset, 0);
}
/*private*/
void GameRenderer::bobHurt(float a) {
Mob* player = mc->cameraTargetPlayer;
float hurt = player->hurtTime - a;
if (player->health <= 0) {
float duration = player->deathTime + a;
glRotatef2(40 - (40 * 200) / (duration + 200), 0, 0, 1);
}
if (player->hurtTime <= 0) return;
hurt /= player->hurtDuration;
hurt = (float) Mth::sin(hurt * hurt * hurt * hurt * Mth::PI);
float rr = player->hurtDir;
glRotatef2(-rr, 0, 1, 0);
glRotatef2(-hurt * 14, 0, 0, 1);
glRotatef2(+rr, 0, 1, 0);
}
/*private*/
void GameRenderer::bobView(float a) {
//if (mc->options.thirdPersonView) return;
if (!(mc->cameraTargetPlayer->isPlayer())) {
return;
}
Player* player = (Player*) mc->cameraTargetPlayer;
float wda = player->walkDist - player->walkDistO;
float b = -(player->walkDist + wda * a);
float bob = player->oBob + (player->bob - player->oBob) * a;
float tilt = player->oTilt + (player->tilt - player->oTilt) * a;
glTranslatef2((float) Mth::sin(b * Mth::PI) * bob * 0.5f, -(float) std::abs(Mth::cos(b * Mth::PI) * bob), 0);
glRotatef2((float) Mth::sin(b * Mth::PI) * bob * 3, 0, 0, 1);
glRotatef2((float) std::abs(Mth::cos(b * Mth::PI - 0.2f) * bob) * 5, 1, 0, 0);
glRotatef2((float) tilt, 1, 0, 0);
}
/*private*/
void GameRenderer::setupFog(int i) {
Mob* player = mc->cameraTargetPlayer;
float fogBuffer[4] = {fr, fg, fb, 1};
glFogfv(GL_FOG_COLOR, (GLfloat*)fogBuffer);
glColor4f2(1, 1, 1, 1);
if (player->isUnderLiquid(Material::water)) {
glFogx(GL_FOG_MODE, GL_EXP);
glFogf(GL_FOG_DENSITY, 0.1f); // was 0.06
// float rr = 0.4f;
// float gg = 0.4f;
// float bb = 0.9f;
//
// if (mc->options.anaglyph3d) {
// float rrr = (rr * 30 + gg * 59 + bb * 11) / 100;
// float ggg = (rr * 30 + gg * 70) / (100);
// float bbb = (rr * 30 + bb * 70) / (100);
//
// rr = rrr;
// gg = ggg;
// bb = bbb;
// }
} else if (player->isUnderLiquid(Material::lava)) {
glFogx(GL_FOG_MODE, GL_EXP);
glFogf(GL_FOG_DENSITY, 2.f); // was 0.06
// float rr = 0.4f;
// float gg = 0.3f;
// float bb = 0.3f;
//
// if (mc->options.anaglyph3d) {
// float rrr = (rr * 30 + gg * 59 + bb * 11) / 100;
// float ggg = (rr * 30 + gg * 70) / (100);
// float bbb = (rr * 30 + bb * 70) / (100);
//
// rr = rrr;
// gg = ggg;
// bb = bbb;
// }
} else {
glFogx(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, renderDistance * 0.6f);
glFogf(GL_FOG_END, renderDistance);
if (i < 0) {
glFogf(GL_FOG_START, 0);
glFogf(GL_FOG_END, renderDistance * 1.0f);
}
if (mc->level->dimension->foggy) {
glFogf(GL_FOG_START, 0);
}
}
glEnable2(GL_COLOR_MATERIAL);
//glColorMaterial(GL_FRONT, GL_AMBIENT);
}
void GameRenderer::updateAllChunks() {
mc->levelRenderer->updateDirtyChunks(mc->cameraTargetPlayer, true);
}
bool GameRenderer::updateFreeformPickDirection(float a, Vec3& outDir) {
if (!mc->inputHolder->allowPicking()) {
_shTicks = 1;
return false;
}
Vec3 c = mc->cameraTargetPlayer->getPos(a);
bool firstPerson = !mc->options.thirdPersonView;
const float PickingDistance = firstPerson? 6.0f : 12.0f;
_shTicks = -1;
int vp[4] = {0, 0, mc->width, mc->height};
float pt[3];
float x = mc->inputHolder->mousex;
float y = mc->height - mc->inputHolder->mousey;
//sw.start();
if (!glhUnProjectf(x, y, 1, lastModelMatrix, lastProjMatrix, vp, pt)) {
return false;
}
Vec3 p1(pt[0] + c.x, pt[1] + c.y, pt[2] + c.z);
glhUnProjectf(x, y, 0, lastModelMatrix, lastProjMatrix, vp, pt);
Vec3 p0(pt[0] + c.x, pt[1] + c.y, pt[2] + c.z);
outDir = (p1 - p0).normalized();
p1 = p0 + outDir * PickingDistance;
//sw.stop();
//sw.printEvery(30, "unproject ");
const HitResult& hit = mc->hitResult = mc->level->clip(p0, p1, false);
// If in 3rd person view - verify that the hit target is within range
if (!firstPerson && hit.isHit()) {
const float MaxSqrDist = PickingDistance*PickingDistance;
if (mc->cameraTargetPlayer->distanceToSqr((float)hit.x, (float)hit.y, (float)hit.z) > MaxSqrDist)
mc->hitResult.type = NO_HIT;
}
return true;
}
/*public*/
void GameRenderer::pick(float a) {
if (mc->level == NULL) return;
if (mc->cameraTargetPlayer == NULL) return;
if (!mc->cameraTargetPlayer->isAlive()) return;
float range = mc->gameMode->getPickRange();
bool isPicking = true;
bool freeform = mc->useTouchscreen() && !mc->options.isJoyTouchArea;
if (freeform) {
isPicking = updateFreeformPickDirection(a, pickDirection);
} else {
mc->hitResult = mc->cameraTargetPlayer->pick(range, a);
pickDirection = mc->cameraTargetPlayer->getViewVector(a);
}
Vec3 from = mc->cameraTargetPlayer->getPos(a);
float dist = range;
if (mc->hitResult.isHit()) {
dist = mc->hitResult.pos.distanceTo(from);
}
if (mc->gameMode->isCreativeType()) {
/*dist =*/ range = 12;
} else {
if (dist > 3) dist = 3;
range = dist;
}
Vec3 pv = (pickDirection * range);
Vec3 to = from + pv;
mc->cameraTargetPlayer->aimDirection = pickDirection;
Entity* hovered = NULL;
const float g = 1;
AABB aabb = mc->cameraTargetPlayer->bb.expand(pv.x, pv.y, pv.z).grow(g, g, g);
EntityList& objects = mc->level->getEntities(mc->cameraTargetPlayer, aabb);
float nearest = 0;
for (unsigned int i = 0; i < objects.size(); i++) {
Entity* e = objects[i];
if (!e->isPickable()) continue;
float rr = e->getPickRadius();
AABB bb = e->bb.grow(rr, rr, rr);
HitResult p = bb.clip(from, to);
//printf("Clip Hitresult %d (%d)\n", p.type, p.isHit());
if (bb.contains(from)) {
//@todo: hovered = e; break; ?
if (nearest >= 0) {
hovered = e;
nearest = 0;
}
} else if (p.isHit()) {
float dd = from.distanceTo(p.pos);
if (dd < nearest || nearest == 0) {
hovered = e;
nearest = dd;
}
}
}
if (hovered != NULL) {
if(nearest < dist) {
mc->hitResult = HitResult(hovered);
}
}
else if (isPicking && !mc->hitResult.isHit()) {
// if we don't have a hit result, attempt to hit the edge of the block we are standing on
// (this is an pocket edition simplification to help building floors)
//LOGI("hovered : %d (%f)\n", mc->hitResult.type, viewVec.y);
if (pickDirection.y < -.7f) {
// looking down by more than roughly 45 degrees, fetch a hit to the block standing on
Vec3 to = from.add(0, -2.0f, 0);
HitResult downHitResult = mc->level->clip(from, to);
if (downHitResult.isHit()) {
mc->hitResult = downHitResult;
mc->hitResult.indirectHit = true;
// change face (not up)
if (std::abs(pickDirection.x) > std::abs(pickDirection.z)) {
mc->hitResult.f = (pickDirection.x < 0)? 4 : 5;
} else {
mc->hitResult.f = (pickDirection.z < 0)? 2 : 3;
}
}
}
}
}
/*public*/
void GameRenderer::tick(int nTick, int maxTick) {
--_t_keepPic;
if (!mc->player)
{
return;
}
if (--_shTicks == 0)
mc->hitResult.type = NO_HIT;
//_rotXlast = _rotX;
//_rotYlast = _rotY;
//LOGI("x: %f\n", _rotX);
if (nTick == maxTick) {
const float tickMult = 1.0f / (float)(1 + maxTick);
_rotXlast = 0.4f * std::pow(std::abs(_rotX), 1.2f) * tickMult;
if (_rotX < 0) _rotXlast = -_rotXlast;
_rotYlast = 0.4f * std::pow(std::abs(_rotY), 1.2f) * tickMult;
if (_rotY < 0) _rotYlast = -_rotYlast;
_rotX = 0;
_rotY = 0;
}
fogBrO = fogBr;
thirdDistanceO = thirdDistance;
thirdRotationO = thirdRotation;
thirdTiltO = thirdTilt;
fovOffsetO = fovOffset;
cameraRollO = cameraRoll;
if (mc->cameraTargetPlayer == NULL) {
mc->cameraTargetPlayer = mc->player;
}
tickFov();
float brr = mc->level->getBrightness( Mth::floor(mc->cameraTargetPlayer->x),
Mth::floor(mc->cameraTargetPlayer->y),
Mth::floor(mc->cameraTargetPlayer->z));
float whiteness = (3 - mc->options.viewDistance) / 3.0f;
float fogBrT = brr * (1 - whiteness) + whiteness;
fogBr += (fogBrT - fogBr) * 0.1f;
_tick++;
itemInHandRenderer->tick();
// if (mc->isRaining) tickRain();
}
/*private*/
void GameRenderer::setupClearColor(float a) {
Level* level = mc->level;
Mob* player = mc->cameraTargetPlayer;
float whiteness = 1.0f / (4 - mc->options.viewDistance);
whiteness = 1 - (float) pow(whiteness, 0.25f);
Vec3 skyColor = level->getSkyColor(mc->cameraTargetPlayer, a);
float sr = (float) skyColor.x;
float sg = (float) skyColor.y;
float sb = (float) skyColor.z;
Vec3 fogColor = level->getFogColor(a);
fr = (float) fogColor.x;
fg = (float) fogColor.y;
fb = (float) fogColor.z;
fr += (sr - fr) * whiteness;
fg += (sg - fg) * whiteness;
fb += (sb - fb) * whiteness;
if (player->isUnderLiquid(Material::water)) {
fr = 0.02f;
fg = 0.02f;
fb = 0.2f;
} else if (player->isUnderLiquid(Material::lava)) {
fr = 0.6f;
fg = 0.1f;
fb = 0.00f;
}
float brr = fogBrO + (fogBr - fogBrO) * a;
fr *= brr;
fg *= brr;
fb *= brr;
if (mc->options.anaglyph3d) {
float frr = (fr * 30 + fg * 59 + fb * 11) / 100;
float fgg = (fr * 30 + fg * 70) / (100);
float fbb = (fr * 30 + fb * 70) / (100);
fr = frr;
fg = fgg;
fb = fbb;
}
glClearColor(fr, fg, fb, 1.0f);
}
void GameRenderer::zoomRegion( float zoom, float xa, float ya )
{
this->zoom = zoom;
this->zoom_x = xa;
this->zoom_y = ya;
}
void GameRenderer::unZoomRegion()
{
zoom = 1;
}
void GameRenderer::setupGuiScreen( bool clearColorBuffer )
{
int screenWidth = (int)(mc->width * Gui::InvGuiScale);
int screenHeight = (int)(mc->height * Gui::InvGuiScale);
// Setup GUI render mode
GLbitfield clearBits = clearColorBuffer?
GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT
: GL_DEPTH_BUFFER_BIT;
glClear(clearBits);
glMatrixMode(GL_PROJECTION);
glLoadIdentity2();
glOrthof(0, (GLfloat)screenWidth, (GLfloat)screenHeight, 0, 2000, 3000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity2();
glTranslatef2(0, 0, -2000);
}
/*private*/
void GameRenderer::renderItemInHand(float a, int eye) {
glLoadIdentity2();
if (mc->options.anaglyph3d) glTranslatef2((eye * 2 - 1) * 0.10f, 0, 0);
glPushMatrix2();
bobHurt(a);
if (mc->options.bobView) bobView(a);
if (!mc->options.thirdPersonView && (mc->cameraTargetPlayer->isPlayer() && !((Player*)mc->cameraTargetPlayer)->isSleeping())) {
if (!mc->options.hideGui) {
float fov = getFov(a, false);
if (fov != _setupCameraFov) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, mc->width / (float) mc->height, 0.05f, renderDistance);
glMatrixMode(GL_MODELVIEW);
}
itemInHandRenderer->render(a);
}
}
glPopMatrix2();
if (!mc->options.thirdPersonView && (mc->cameraTargetPlayer->isPlayer() && !((Player*)mc->cameraTargetPlayer)->isSleeping())) {
itemInHandRenderer->renderScreenEffect(a);
bobHurt(a);
}
if (mc->options.bobView) bobView(a);
}
void GameRenderer::onGraphicsReset()
{
if (itemInHandRenderer) itemInHandRenderer->onGraphicsReset();
}
void GameRenderer::saveMatrices()
{
#if defined(RPI)
return;
#endif
static bool saved = false;
//if (saved) return;
saved = true;
glGetFloatv(GL_PROJECTION_MATRIX, lastProjMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, lastModelMatrix);
}
void GameRenderer::prepareAndRenderClouds( LevelRenderer* levelRenderer, float a ) {
//if(mc->options.isCloudsOn()) {
TIMER_PUSH("clouds");
glMatrixMode(GL_PROJECTION);
glPushMatrix2();
glLoadIdentity2();
gluPerspective(_setupCameraFov = getFov(a, true), mc->width / (float) mc->height, 2, renderDistance * 512);
glMatrixMode(GL_MODELVIEW);
glPushMatrix2();
setupFog(0);
glDepthMask(false);
glEnable2(GL_FOG);
glFogf(GL_FOG_START, renderDistance * 0.2f);
glFogf(GL_FOG_END, renderDistance * 0.75f);
levelRenderer->renderSky(a);
glFogf(GL_FOG_START, renderDistance * 4.2f * 0.6f);
glFogf(GL_FOG_END, renderDistance * 4.2f);
levelRenderer->renderClouds(a);
glFogf(GL_FOG_START, renderDistance * 0.6f);
glFogf(GL_FOG_END, renderDistance);
glDisable2(GL_FOG);
glDepthMask(true);
setupFog(1);
glPopMatrix2();
glMatrixMode(GL_PROJECTION);
glPopMatrix2();
glMatrixMode(GL_MODELVIEW);
TIMER_POP();
//}
}