aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/GameRenderer.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/GameRenderer.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/GameRenderer.cpp')
-rw-r--r--Minecraft.Client/GameRenderer.cpp2169
1 files changed, 2169 insertions, 0 deletions
diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp
new file mode 100644
index 00000000..508b3a1a
--- /dev/null
+++ b/Minecraft.Client/GameRenderer.cpp
@@ -0,0 +1,2169 @@
+#include "stdafx.h"
+#include "GameRenderer.h"
+#include "ItemInHandRenderer.h"
+#include "LevelRenderer.h"
+#include "Frustum.h"
+#include "FrustumCuller.h"
+#include "Textures.h"
+#include "Tesselator.h"
+#include "ParticleEngine.h"
+#include "SmokeParticle.h"
+#include "WaterDropParticle.h"
+#include "GameMode.h"
+#include "CreativeMode.h"
+#include "Lighting.h"
+#include "Options.h"
+#include "MultiplayerLocalPlayer.h"
+#include "GuiParticles.h"
+#include "MultiPlayerLevel.h"
+#include "Chunk.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.h"
+#include "..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.player.h"
+#include "..\Minecraft.World\net.minecraft.world.phys.h"
+#include "..\Minecraft.World\net.minecraft.world.level.material.h"
+#include "..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "..\Minecraft.World\net.minecraft.world.level.chunk.h"
+#include "..\Minecraft.World\net.minecraft.world.level.biome.h"
+#include "..\Minecraft.World\net.minecraft.world.level.dimension.h"
+#include "..\Minecraft.World\System.h"
+#include "..\Minecraft.World\FloatBuffer.h"
+#include "..\Minecraft.World\ThreadName.h"
+#include "..\Minecraft.World\SparseLightStorage.h"
+#include "..\Minecraft.World\CompressedTileStorage.h"
+#include "..\Minecraft.World\SparseDataStorage.h"
+#include "..\Minecraft.World\JavaMath.h"
+#include "..\Minecraft.World\Facing.h"
+#include "..\Minecraft.World\MobEffect.h"
+#include "..\Minecraft.World\IntCache.h"
+#include "..\Minecraft.World\SmoothFloat.h"
+#include "..\Minecraft.World\MobEffectInstance.h"
+#include "..\Minecraft.World\Item.h"
+#include "Camera.h"
+#include "..\Minecraft.World\SoundTypes.h"
+#include "HumanoidModel.h"
+#include "..\Minecraft.World\Item.h"
+#include "..\Minecraft.World\compression.h"
+#include "PS3\PS3Extras\ShutdownManager.h"
+
+#include "TexturePackRepository.h"
+#include "TexturePack.h"
+
+bool GameRenderer::anaglyph3d = false;
+int GameRenderer::anaglyphPass = 0;
+
+#ifdef MULTITHREAD_ENABLE
+C4JThread* GameRenderer::m_updateThread;
+C4JThread::EventArray* GameRenderer::m_updateEvents;
+bool GameRenderer::nearThingsToDo = false;
+bool GameRenderer::updateRunning = false;
+vector<byte *> GameRenderer::m_deleteStackByte;
+vector<SparseLightStorage *> GameRenderer::m_deleteStackSparseLightStorage;
+vector<CompressedTileStorage *> GameRenderer::m_deleteStackCompressedTileStorage;
+vector<SparseDataStorage *> GameRenderer::m_deleteStackSparseDataStorage;
+#endif
+CRITICAL_SECTION GameRenderer::m_csDeleteStack;
+
+GameRenderer::GameRenderer(Minecraft *mc)
+{
+ // 4J - added this block of initialisers
+ renderDistance = 0;
+ _tick = 0;
+ hovered = nullptr;
+ thirdDistance = 4;
+ thirdDistanceO = 4;
+ thirdRotation = 0;
+ thirdRotationO = 0;
+ thirdTilt = 0;
+ thirdTiltO = 0;
+
+ accumulatedSmoothXO = 0;
+ accumulatedSmoothYO = 0;
+ tickSmoothXO = 0;
+ tickSmoothYO = 0;
+ lastTickA = 0;
+
+ cameraPos = Vec3::newPermanent(0.0f,0.0f,0.0f);
+
+ fovOffset = 0;
+ fovOffsetO = 0;
+ cameraRoll = 0;
+ cameraRollO = 0;
+ for( int i = 0; i < 4; i++ )
+ {
+ fov[i] = 0.0f;
+ oFov[i] = 0.0f;
+ tFov[i] = 0.0f;
+ }
+ isInClouds = false;
+ zoom = 1;
+ zoom_x = 0;
+ zoom_y = 0;
+ rainXa = NULL;
+ rainZa = NULL;
+ lastActiveTime = Minecraft::currentTimeMillis();
+ lastNsTime = 0;
+ random = new Random();
+ rainSoundTime = 0;
+ xMod = 0;
+ yMod = 0;
+ lb = MemoryTracker::createFloatBuffer(16);
+ fr = 0.0f;
+ fg = 0.0f;
+ fb = 0.0f;
+ fogBrO = 0.0f;
+ fogBr = 0.0f;
+ cameraFlip = 0;
+ _updateLightTexture = false;
+ blr = 0.0f;
+ blrt = 0.0f;
+ blg = 0.0f;
+ blgt = 0.0f;
+
+
+ m_fov=70.0f;
+
+ // 4J Stu - Init these so they are setup before the tick
+ for( int i = 0; i < 4; i++ )
+ {
+ fov[i] = oFov[i] = 1.0f;
+ }
+
+ this->mc = mc;
+ itemInHandRenderer = NULL;
+
+ // 4J-PB - set up the local players iteminhand renderers here - needs to be done with lighting enabled so that the render geometry gets compiled correctly
+ glEnable(GL_LIGHTING);
+ mc->localitemInHandRenderers[0] = new ItemInHandRenderer(mc);//itemInHandRenderer;
+ mc->localitemInHandRenderers[1] = new ItemInHandRenderer(mc);
+ mc->localitemInHandRenderers[2] = new ItemInHandRenderer(mc);
+ mc->localitemInHandRenderers[3] = new ItemInHandRenderer(mc);
+ glDisable(GL_LIGHTING);
+
+ // 4J - changes brought forward from 1.8.2
+ BufferedImage *img = new BufferedImage(16, 16, BufferedImage::TYPE_INT_RGB);
+ for( int i = 0; i < NUM_LIGHT_TEXTURES; i++ )
+ {
+ lightTexture[i] = mc->textures->getTexture(img); // 4J - changed to one light texture per level to support split screen
+ }
+ delete img;
+#ifdef __PS3__
+ // we're using the RSX now to upload textures to vram, so we need the main ram textures allocated from io space
+ for(int i=0;i<NUM_LIGHT_TEXTURES;i++)
+ lightPixels[i] = intArray((int*)RenderManager.allocIOMem(16*16*sizeof(int)), 16*16);
+#else
+ for(int i=0;i<NUM_LIGHT_TEXTURES;i++)
+ lightPixels[i] = intArray(16*16);
+#endif
+
+#ifdef MULTITHREAD_ENABLE
+ m_updateEvents = new C4JThread::EventArray(eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear);
+ m_updateEvents->Set(eUpdateEventIsFinished);
+
+ InitializeCriticalSection(&m_csDeleteStack);
+ m_updateThread = new C4JThread(runUpdate, NULL, "Chunk update");
+#ifdef __PS3__
+ m_updateThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
+#endif// __PS3__
+ m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE);
+ m_updateThread->Run();
+#endif
+}
+
+// 4J Stu Added to go with 1.8.2 change
+GameRenderer::~GameRenderer()
+{
+ if(rainXa != NULL) delete [] rainXa;
+ if(rainZa != NULL) delete [] rainZa;
+}
+
+void GameRenderer::tick(bool first) // 4J - add bFirst
+{
+ tickFov();
+ tickLightTexture(); // 4J - change brought forward from 1.8.2
+ fogBrO = fogBr;
+ thirdDistanceO = thirdDistance;
+ thirdRotationO = thirdRotation;
+ thirdTiltO = thirdTilt;
+ fovOffsetO = fovOffset;
+ cameraRollO = cameraRoll;
+
+ if (ClientConstants::DEADMAU5_CAMERA_CHEATS)
+ {
+ if (mc->screen == NULL)
+ {
+ float distanceDelta = 0;
+ float rotationDelta = 0;
+ float tiltDelta = 0;
+ float rollDelta = 0;
+
+ if (Keyboard::isKeyDown(Keyboard::KEY_U))
+ {
+ distanceDelta -= .3f * mc->options->cameraSpeed;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_O))
+ {
+ distanceDelta += .3f * mc->options->cameraSpeed;
+ }
+ if (Keyboard::isKeyDown(Keyboard::KEY_J))
+ {
+ rotationDelta += 8.0f * mc->options->cameraSpeed;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_L))
+ {
+ rotationDelta -= 8.0f * mc->options->cameraSpeed;
+ }
+ if (Keyboard::isKeyDown(Keyboard::KEY_I))
+ {
+ tiltDelta += 6.0f * mc->options->cameraSpeed;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_K))
+ {
+ tiltDelta -= 6.0f * mc->options->cameraSpeed;
+ }
+ if (Keyboard::isKeyDown(Keyboard::KEY_Y) && Keyboard::isKeyDown(Keyboard::KEY_H))
+ {
+ fovOffset = 0;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_Y))
+ {
+ fovOffset -= 3.0f;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_H))
+ {
+ fovOffset += 3.0f;
+ }
+ if (Keyboard::isKeyDown(Keyboard::KEY_N) && Keyboard::isKeyDown(Keyboard::KEY_M))
+ {
+ cameraRoll = 0;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_N))
+ {
+ rollDelta -= 8.0f * mc->options->cameraSpeed;
+ }
+ else if (Keyboard::isKeyDown(Keyboard::KEY_M))
+ {
+ rollDelta += 8.0f * mc->options->cameraSpeed;
+ }
+
+ if (mc->options->smoothCamera)
+ {
+ distanceDelta = smoothDistance.getNewDeltaValue(distanceDelta, .5f * mc->options->sensitivity);
+ rotationDelta = smoothRotation.getNewDeltaValue(rotationDelta, .5f * mc->options->sensitivity);
+ tiltDelta = smoothTilt.getNewDeltaValue(tiltDelta, .5f * mc->options->sensitivity);
+ rollDelta = smoothRoll.getNewDeltaValue(rollDelta, .5f * mc->options->sensitivity);
+ }
+ thirdDistance += distanceDelta;
+ thirdRotation += rotationDelta;
+ thirdTilt += tiltDelta;
+ cameraRoll += rollDelta;
+ }
+ }
+
+ if (mc->options->smoothCamera)
+ {
+ // update player view in tick() instead of render() to maintain
+// camera movement regardless of FPS
+ float ss = mc->options->sensitivity * 0.6f + 0.2f;
+ float sens = (ss * ss * ss) * 8;
+ tickSmoothXO = smoothTurnX.getNewDeltaValue(accumulatedSmoothXO, 0.05f * sens);
+ tickSmoothYO = smoothTurnY.getNewDeltaValue(accumulatedSmoothYO, 0.05f * sens);
+ lastTickA = 0;
+
+ accumulatedSmoothXO = 0;
+ accumulatedSmoothYO = 0;
+ }
+
+ if (mc->cameraTargetPlayer == NULL)
+ {
+ mc->cameraTargetPlayer = dynamic_pointer_cast<Mob>(mc->player);
+ }
+
+ 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;
+
+ itemInHandRenderer->tick();
+
+ PIXBeginNamedEvent(0,"Rain tick");
+ tickRain();
+ PIXEndNamedEvent();
+
+ if( mc->player != mc->localplayers[ProfileManager.GetPrimaryPad()] ) return; // 4J added for split screen - only do rest of processing for once per frame
+
+ _tick++;
+}
+
+void GameRenderer::pick(float a)
+{
+ if (mc->cameraTargetPlayer == NULL) return;
+ if (mc->level == NULL) return;
+
+ double range = mc->gameMode->getPickRange();
+ delete mc->hitResult;
+ MemSect(31);
+ mc->hitResult = mc->cameraTargetPlayer->pick(range, a);
+ MemSect(0);
+
+ // 4J - added - stop blocks right at the edge of the world from being pickable so we shouldn't be able to directly destroy or create anything there
+ if( mc->hitResult )
+ {
+ int maxxz = ( ( mc->level->chunkSource->m_XZSize / 2 ) * 16 ) - 2;
+ int minxz = ( -( mc->level->chunkSource->m_XZSize / 2 ) * 16 ) + 1;
+
+ // Don't select the tops of the very edge blocks, or the sides of the next blocks in
+ // 4J Stu - Only block the sides that are facing an outside block
+ int hitx = mc->hitResult->x;
+ int hitz = mc->hitResult->z;
+ int face = mc->hitResult->f;
+ if( face == Facing::WEST && hitx < 0 ) hitx -= 1;
+ if( face == Facing::EAST && hitx > 0 ) hitx += 1;
+ if( face == Facing::NORTH && hitz < 0 ) hitz -= 1;
+ if( face == Facing::SOUTH && hitz > 0 ) hitz += 1;
+
+ if( ( hitx < minxz ) || ( hitx > maxxz) ||
+ ( hitz < minxz ) || ( hitz > maxxz) )
+ {
+ delete mc->hitResult;
+ mc->hitResult = NULL;
+ }
+ }
+
+ double dist = range;
+ Vec3 *from = mc->cameraTargetPlayer->getPos(a);
+
+ if (mc->gameMode->hasFarPickRange())
+ {
+ dist = range = 6;
+ }
+ else
+ {
+ if (dist > 3) dist = 3;
+ range = dist;
+ }
+
+ if (mc->hitResult != NULL)
+ {
+ dist = mc->hitResult->pos->distanceTo(from);
+ }
+
+ Vec3 *b = mc->cameraTargetPlayer->getViewVector(a);
+ Vec3 *to = from->add(b->x * range, b->y * range, b->z * range);
+ hovered = nullptr;
+ float overlap = 1;
+ vector<shared_ptr<Entity> > *objects = mc->level->getEntities(mc->cameraTargetPlayer, mc->cameraTargetPlayer->bb->expand(b->x * (range), b->y * (range), b->z * (range))->grow(overlap, overlap, overlap));
+ double nearest = dist;
+
+ AUTO_VAR(itEnd, objects->end());
+ for (AUTO_VAR(it, objects->begin()); it != itEnd; it++)
+ {
+ shared_ptr<Entity> e = *it; //objects->at(i);
+ if (!e->isPickable()) continue;
+
+ float rr = e->getPickRadius();
+ AABB *bb = e->bb->grow(rr, rr, rr);
+ HitResult *p = bb->clip(from, to);
+ if (bb->contains(from))
+ {
+ if (0 < nearest || nearest == 0)
+ {
+ hovered = e;
+ nearest = 0;
+ }
+ }
+ else if (p != NULL)
+ {
+ double dd = from->distanceTo(p->pos);
+ if (dd < nearest || nearest == 0)
+ {
+ hovered = e;
+ nearest = dd;
+ }
+ }
+ delete p;
+ }
+
+ if (hovered != NULL)
+ {
+ if (nearest < dist || (mc->hitResult == NULL))
+ {
+ if( mc->hitResult != NULL )
+ delete mc->hitResult;
+ mc->hitResult = new HitResult(hovered);
+ }
+ }
+}
+
+void GameRenderer::SetFovVal(float fov)
+{
+ m_fov=fov;
+}
+
+float GameRenderer::GetFovVal()
+{
+ return m_fov;
+}
+
+void GameRenderer::tickFov()
+{
+ shared_ptr<LocalPlayer>player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
+
+ int playerIdx = player ? player->GetXboxPad() : 0;
+ tFov[playerIdx] = player->getFieldOfViewModifier();
+
+ oFov[playerIdx] = fov[playerIdx];
+ fov[playerIdx] += (tFov[playerIdx] - fov[playerIdx]) * 0.5f;
+}
+
+float GameRenderer::getFov(float a, bool applyEffects)
+{
+ if (cameraFlip > 0 ) return 90;
+
+ shared_ptr<LocalPlayer> player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
+ int playerIdx = player ? player->GetXboxPad() : 0;
+ float fov = m_fov;//70;
+ if (applyEffects)
+ {
+ fov += mc->options->fov * 40;
+ fov *= this->oFov[playerIdx] + (this->fov[playerIdx] - this->oFov[playerIdx]) * a;
+ }
+ if (player->getHealth() <= 0)
+ {
+ float duration = player->deathTime + a;
+
+ fov /= ((1 - 500 / (duration + 500)) * 2.0f + 1);
+ }
+
+ int t = Camera::getBlockAt(mc->level, player, a);
+ if (t != 0 && Tile::tiles[t]->material == Material::water) fov = fov * 60 / 70;
+
+ return fov + fovOffsetO + (fovOffset - fovOffsetO) * a;
+
+}
+
+void GameRenderer::bobHurt(float a)
+{
+ shared_ptr<Mob> player = mc->cameraTargetPlayer;
+
+ float hurt = player->hurtTime - a;
+
+ if (player->getHealth() <= 0)
+ {
+ float duration = player->deathTime + a;
+
+ glRotatef(40 - (40 * 200) / (duration + 200), 0, 0, 1);
+ }
+
+ if (hurt < 0) return;
+ hurt /= player->hurtDuration;
+ hurt = (float) Mth::sin(hurt * hurt * hurt * hurt * PI);
+
+ float rr = player->hurtDir;
+
+
+ glRotatef(-rr, 0, 1, 0);
+ glRotatef(-hurt * 14, 0, 0, 1);
+ glRotatef(+rr, 0, 1, 0);
+
+}
+
+void GameRenderer::bobView(float a)
+{
+ shared_ptr<Player> player = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer);
+ if(player==NULL)
+ {
+ return;
+ }
+ //shared_ptr<Player> player = dynamic_pointer_cast<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;
+ glTranslatef((float) Mth::sin(b * PI) * bob * 0.5f, -(float) abs(Mth::cos(b * PI) * bob), 0);
+ glRotatef((float) Mth::sin(b * PI) * bob * 3, 0, 0, 1);
+ glRotatef((float) abs(Mth::cos(b * PI - 0.2f) * bob) * 5, 1, 0, 0);
+ glRotatef((float) tilt, 1, 0, 0);
+}
+
+void GameRenderer::moveCameraToPlayer(float a)
+{
+ shared_ptr<Mob> player = mc->cameraTargetPlayer;
+ shared_ptr<LocalPlayer> localplayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
+ float heightOffset = player->heightOffset - 1.62f;
+
+ double x = player->xo + (player->x - player->xo) * a;
+ double y = player->yo + (player->y - player->yo) * a - heightOffset;
+ double z = player->zo + (player->z - player->zo) * a;
+
+
+ glRotatef(cameraRollO + (cameraRoll - cameraRollO) * a, 0, 0, 1);
+
+ if (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.0f, 1.0f, 0.0f);
+ }
+ glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, -1, 0);
+ glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, -1, 0, 0);
+ }
+ }
+ // 4J-PB - changing this to be per player
+ //else if (mc->options->thirdPersonView)
+ else if (localplayer->ThirdPersonView())
+ {
+ double cameraDist = thirdDistanceO + (thirdDistance - thirdDistanceO) * a;
+
+ if (mc->options->fixedCamera)
+ {
+
+ float rotationY = thirdRotationO + (thirdRotation - thirdRotationO) * a;
+ float xRot = thirdTiltO + (thirdTilt - thirdTiltO) * a;
+
+ glTranslatef(0, 0, (float) -cameraDist);
+ glRotatef(xRot, 1, 0, 0);
+ glRotatef(rotationY, 0, 1, 0);
+ }
+ else
+ {
+ // 4J - corrected bug where this used to just take player->xRot & yRot directly and so wasn't taking into account interpolation, allowing camera to go through walls
+ float yRot = player->yRotO + (player->yRot - player->yRotO) * a;
+ float xRot = player->xRotO + (player->xRot - player->xRotO) * a;
+
+ // Thirdperson view values are now 0 for disabled, 1 for original mode, 2 for reversed.
+ if( localplayer->ThirdPersonView() == 2 )
+ {
+ // Reverse y rotation - note that this is only used in doing collision to calculate our view
+ // distance, the actual rotation itself is just below this else {} block
+ yRot += 180.0f;
+ }
+
+ double xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
+ double zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
+ double yd = -Mth::sin(xRot / 180 * 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;
+
+ // 4J - corrected bug here where zo was also added to x component
+ HitResult *hr = mc->level->clip(Vec3::newTemp(x + xo, y + yo, z + zo), Vec3::newTemp(x - xd + xo, y - yd + yo, z - zd + zo));
+ if (hr != NULL)
+ {
+ double dist = hr->pos->distanceTo(Vec3::newTemp(x, y, z));
+ if (dist < cameraDist) cameraDist = dist;
+ delete hr;
+ }
+ }
+
+ // 4J - removed extra rotations here that aren't needed because our xRot/yRot don't ever
+ // deviate from the player's view direction
+// glRotatef(player->xRot - xRot, 1, 0, 0);
+// glRotatef(player->yRot - yRot, 0, 1, 0);
+ glTranslatef(0, 0, (float) -cameraDist);
+// glRotatef(yRot - player->yRot, 0, 1, 0);
+// glRotatef(xRot - player->xRot, 1, 0, 0);
+ }
+ }
+ else
+ {
+ glTranslatef(0, 0, -0.1f);
+ }
+
+ if (!mc->options->fixedCamera)
+ {
+ glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0);
+ if( localplayer->ThirdPersonView() == 2 )
+ {
+ // Third person view is now 0 for disabled, 1 for original, 2 for flipped
+ glRotatef(player->yRotO + (player->yRot - player->yRotO) * a, 0, 1, 0);
+ }
+ else
+ {
+ glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0);
+ }
+ }
+
+ glTranslatef(0, heightOffset, 0);
+
+ x = player->xo + (player->x - player->xo) * a;
+ y = player->yo + (player->y - player->yo) * a - heightOffset;
+ z = player->zo + (player->z - player->zo) * a;
+
+ isInClouds = mc->levelRenderer->isInCloud(x, y, z, a);
+
+}
+
+
+void GameRenderer::zoomRegion(double zoom, double xa, double ya)
+{
+ this->zoom = zoom;
+ this->zoom_x = xa;
+ this->zoom_y = ya;
+}
+
+void GameRenderer::unZoomRegion()
+{
+ zoom = 1;
+}
+
+// 4J added as we have more complex adjustments to make for fov & aspect on account of viewports
+void GameRenderer::getFovAndAspect(float& fov, float& aspect, float a, bool applyEffects)
+{
+ // 4J - split out aspect ratio and fov here so we can adjust for viewports - we might need to revisit these as
+ // they are maybe be too generous for performance.
+ aspect = mc->width / (float) mc->height;
+ fov = getFov(a, applyEffects);
+
+ if( ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_TOP ) ||
+ ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM ) )
+ {
+ aspect *= 2.0f;
+ fov *= 0.7f; // Reduce FOV to make things less fish-eye, at the expense of reducing vertical FOV from single player mode
+ }
+ else if( ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT ) ||
+ ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT) )
+ {
+ // Ideally I'd like to make the fov bigger here, but if I do then you an see that the arm isn't very long...
+ aspect *= 0.5f;
+ }
+}
+
+void GameRenderer::setupCamera(float a, int eye)
+{
+ renderDistance = (float)(16 * 16 >> (mc->options->viewDistance));
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ float stereoScale = 0.07f;
+ if (mc->options->anaglyph3d) glTranslatef(-(eye * 2 - 1) * stereoScale, 0, 0);
+
+ // 4J - have split out fov & aspect calculation so we can take into account viewports
+ float aspect, fov;
+ getFovAndAspect(fov, aspect, a, true);
+
+ if (zoom != 1)
+ {
+ glTranslatef((float) zoom_x, (float) -zoom_y, 0);
+ glScaled(zoom, zoom, 1);
+ }
+ gluPerspective(fov, aspect, 0.05f, renderDistance * 2);
+
+ if (mc->gameMode->isCutScene())
+ {
+ float s = 1 / 1.5f;
+ glScalef(1, s, 1);
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ if (mc->options->anaglyph3d) glTranslatef((eye * 2 - 1) * 0.10f, 0, 0);
+
+ bobHurt(a);
+
+ // 4J-PB - this is a per-player option
+ //if (mc->options->bobView) bobView(a);
+
+ bool bNoLegAnim =(mc->player->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_NoLegAnim))!=0;
+ bool bNoBobbingAnim =(mc->player->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_NoBobbing))!=0;
+
+ if(app.GetGameSettings(mc->player->GetXboxPad(),eGameSetting_ViewBob) && !mc->player->abilities.flying && !bNoLegAnim && !bNoBobbingAnim) bobView(a);
+
+ float pt = mc->player->oPortalTime + (mc->player->portalTime - mc->player->oPortalTime) * a;
+ if (pt > 0)
+ {
+ int multiplier = 20;
+ if (mc->player->hasEffect(MobEffect::confusion))
+ {
+ multiplier = 7;
+ }
+
+ float skew = 5 / (pt * pt + 5) - pt * 0.04f;
+ skew *= skew;
+ glRotatef((_tick + a) * multiplier, 0, 1, 1);
+ glScalef(1 / skew, 1, 1);
+ glRotatef(-(_tick + a) * multiplier, 0, 1, 1);
+ }
+
+
+ moveCameraToPlayer(a);
+
+ if (cameraFlip > 0)
+ {
+ int i = cameraFlip - 1;
+ if (i == 1) glRotatef(90, 0, 1, 0);
+ if (i == 2) glRotatef(180, 0, 1, 0);
+ if (i == 3) glRotatef(-90, 0, 1, 0);
+ if (i == 4) glRotatef(90, 1, 0, 0);
+ if (i == 5) glRotatef(-90, 1, 0, 0);
+ }
+}
+
+void GameRenderer::renderItemInHand(float a, int eye)
+{
+ if (cameraFlip > 0) return;
+
+ shared_ptr<LocalPlayer> localplayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
+
+ // 4J-PB - to turn off the hand for screenshots, but not when the item held is a map
+ if ( localplayer!=NULL)
+ {
+ shared_ptr<ItemInstance> item = localplayer->inventory->getSelected();
+ if(!(item && item->getItem()->id==Item::map_Id) && app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_DisplayHand)==0 ) return;
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+
+ float stereoScale = 0.07f;
+ if (mc->options->anaglyph3d) glTranslatef(-(eye * 2 - 1) * stereoScale, 0, 0);
+
+ // 4J - have split out fov & aspect calculation so we can take into account viewports
+ float fov, aspect;
+ getFovAndAspect(fov, aspect, a, false);
+
+ if (zoom != 1)
+ {
+ glTranslatef((float) zoom_x, (float) -zoom_y, 0);
+ glScaled(zoom, zoom, 1);
+ }
+ gluPerspective(fov, aspect, 0.05f, renderDistance * 2);
+
+ if (mc->gameMode->isCutScene())
+ {
+ float s = 1 / 1.5f;
+ glScalef(1, s, 1);
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+
+
+ glLoadIdentity();
+ if (mc->options->anaglyph3d) glTranslatef((eye * 2 - 1) * 0.10f, 0, 0);
+
+ glPushMatrix();
+ bobHurt(a);
+
+ // 4J-PB - changing this to be per player
+ //if (mc->options->bobView) bobView(a);
+ bool bNoLegAnim =(localplayer->getAnimOverrideBitmask()&( (1<<HumanoidModel::eAnim_NoLegAnim) | (1<<HumanoidModel::eAnim_NoBobbing) ))!=0;
+ if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a);
+
+ // 4J-PB - changing this to be per player
+ //if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping())
+ if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping())
+ {
+ if (!mc->options->hideGui && !mc->gameMode->isCutScene())
+ {
+ turnOnLightLayer(a);
+ PIXBeginNamedEvent(0,"Item in hand render");
+ itemInHandRenderer->render(a);
+ PIXEndNamedEvent();
+ turnOffLightLayer(a);
+ }
+ }
+ glPopMatrix();
+ // 4J-PB - changing this to be per player
+ //if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping())
+ if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping())
+ {
+ itemInHandRenderer->renderScreenEffect(a);
+ bobHurt(a);
+ }
+ // 4J-PB - changing this to be per player
+ //if (mc->options->bobView) bobView(a);
+ if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a);
+}
+
+// 4J - change brought forward from 1.8.2
+void GameRenderer::turnOffLightLayer(double alpha)
+{ // 4J - TODO
+#if 0
+ if (SharedConstants::TEXTURE_LIGHTING)
+ {
+ glClientActiveTexture(GL_TEXTURE1);
+ glActiveTexture(GL_TEXTURE1);
+ glDisable(GL_TEXTURE_2D);
+ glClientActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0);
+ }
+#endif
+ RenderManager.TextureBindVertex(-1);
+}
+
+// 4J - change brought forward from 1.8.2
+void GameRenderer::turnOnLightLayer(double alpha)
+{ // 4J - TODO
+#if 0
+ if (SharedConstants::TEXTURE_LIGHTING)
+ {
+ glClientActiveTexture(GL_TEXTURE1);
+ glActiveTexture(GL_TEXTURE1);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+// float s = 1 / 16f / 15.0f*16/14.0f;
+ float s = 1 / 16.0f / 15.0f * 15 / 16;
+ glScalef(s, s, s);
+ glTranslatef(8f, 8f, 8f);
+ glMatrixMode(GL_MODELVIEW);
+
+ mc->textures->bind(lightTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_TEXTURE_2D);
+ glClientActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0);
+ }
+#endif
+ RenderManager.TextureBindVertex(getLightTexture(mc->player->GetXboxPad(), mc->level));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+}
+
+// 4J - change brought forward from 1.8.2
+void GameRenderer::tickLightTexture()
+{
+ blrt += (float)((Math::random() - Math::random()) * Math::random() * Math::random());
+ blgt += (float)((Math::random() - Math::random()) * Math::random() * Math::random());
+ blrt *= 0.9;
+ blgt *= 0.9;
+ blr += (blrt - blr) * 1;
+ blg += (blgt - blg) * 1;
+ _updateLightTexture = true;
+}
+
+void GameRenderer::updateLightTexture(float a)
+{
+ // 4J-JEV: Now doing light textures on PER PLAYER basis.
+ // 4J - we *had* added separate light textures for all dimensions, and this loop to update them all here
+ for(int j = 0; j < XUSER_MAX_COUNT; j++ )
+ {
+ // Loop over all the players
+ shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j];
+ if (player == NULL) continue;
+
+ Level *level = player->level; // 4J - was mc->level when it was just to update the one light texture
+
+ float skyDarken1 = level->getSkyDarken((float) 1);
+ for (int i = 0; i < 256; i++)
+ {
+ float darken = skyDarken1 * 0.95f + 0.05f;
+ float sky = level->dimension->brightnessRamp[i / 16] * darken;
+ float block = level->dimension->brightnessRamp[i % 16] * (blr * 0.1f + 1.5f);
+
+ if (level->lightningBoltTime > 0)
+ {
+ sky = level->dimension->brightnessRamp[i / 16];
+ }
+
+ float rs = sky * (skyDarken1 * 0.65f + 0.35f);
+ float gs = sky * (skyDarken1 * 0.65f + 0.35f);
+ float bs = sky;
+
+ float rb = block;
+ float gb = block * ((block * 0.6f + 0.4f) * 0.6f + 0.4f);
+ float bb = block * ((block * block) * 0.6f + 0.4f);
+
+ float _r = (rs + rb);
+ float _g = (gs + gb);
+ float _b = (bs + bb);
+
+ _r = _r * 0.96f + 0.03f;
+ _g = _g * 0.96f + 0.03f;
+ _b = _b * 0.96f + 0.03f;
+
+ if (level->dimension->id == 1)
+ {
+ _r = (0.22f + rb * 0.75f);
+ _g = (0.28f + gb * 0.75f);
+ _b = (0.25f + bb * 0.75f);
+ }
+
+ if (player->hasEffect(MobEffect::nightVision))
+ {
+ float scale = getNightVisionScale(player, a);
+ {
+ float dist = 1.0f / _r;
+ if (dist > (1.0f / _g))
+ {
+ dist = (1.0f / _g);
+ }
+ if (dist > (1.0f / _b))
+ {
+ dist = (1.0f / _b);
+ }
+ _r = _r * (1.0f - scale) + (_r * dist) * scale;
+ _g = _g * (1.0f - scale) + (_g * dist) * scale;
+ _b = _b * (1.0f - scale) + (_b * dist) * scale;
+ }
+ }
+
+ float brightness = 0.0f; // 4J - TODO - was mc->options->gamma;
+ if (_r > 1) _r = 1;
+ if (_g > 1) _g = 1;
+ if (_b > 1) _b = 1;
+
+ float ir = 1 - _r;
+ float ig = 1 - _g;
+ float ib = 1 - _b;
+ ir = 1 - (ir * ir * ir * ir);
+ ig = 1 - (ig * ig * ig * ig);
+ ib = 1 - (ib * ib * ib * ib);
+ _r = _r * (1 - brightness) + ir * brightness;
+ _g = _g * (1 - brightness) + ig * brightness;
+ _b = _b * (1 - brightness) + ib * brightness;
+
+
+ _r = _r * 0.96f + 0.03f;
+ _g = _g * 0.96f + 0.03f;
+ _b = _b * 0.96f + 0.03f;
+
+
+ if (_r > 1) _r = 1;
+ if (_g > 1) _g = 1;
+ if (_b > 1) _b = 1;
+ if (_r < 0) _r = 0;
+ if (_g < 0) _g = 0;
+ if (_b < 0) _b = 0;
+
+ int a = 255;
+ int r = (int) (_r * 255);
+ int g = (int) (_g * 255);
+ int b = (int) (_b * 255);
+
+#if ( defined _DURANGO || defined _WIN64 || __PSVITA__ )
+ lightPixels[j][i] = a << 24 | b << 16 | g << 8 | r;
+#elif ( defined _XBOX || defined __ORBIS__ )
+ lightPixels[j][i] = a << 24 | r << 16 | g << 8 | b;
+#else
+ lightPixels[j][i] = r << 24 | g << 16 | b << 8 | a;
+#endif
+ }
+
+ mc->textures->replaceTextureDirect( lightPixels[j], 16, 16, getLightTexture(j,level) );
+ }
+}
+
+float GameRenderer::getNightVisionScale(shared_ptr<Player> player, float a)
+{
+ int duration = player->getEffect(MobEffect::nightVision)->getDuration();
+ if (duration > (SharedConstants::TICKS_PER_SECOND * 10))
+ {
+ return 1.0f;
+ }
+ else
+ {
+ float flash = max(0.0f, (float)duration - a);
+ return .7f + Mth::sin(flash * PI * .05f) * .3f; // was: .7 + sin(flash*pi*0.2) * .3
+ }
+}
+
+// 4J added, so we can have a light texture for each player to support split screen
+int GameRenderer::getLightTexture(int iPad, Level *level)
+{
+ // Turn the current dimenions id into an index from 0 to 2
+ // int idx = level->dimension->id;
+ // if( idx == -1 ) idx = 2;
+
+ return lightTexture[iPad]; // 4J-JEV: Changing to Per Player lighting textures.
+}
+
+void GameRenderer::render(float a, bool bFirst)
+{
+ if( _updateLightTexture && bFirst) updateLightTexture(a);
+ if (Display::isActive())
+ {
+ lastActiveTime = System::currentTimeMillis();
+ }
+ else
+ {
+ if (System::currentTimeMillis() - lastActiveTime > 500)
+ {
+ mc->pauseGame();
+ }
+ }
+
+#if 0 // 4J - TODO
+ if (mc->mouseGrabbed) {
+ mc->mouseHandler.poll();
+
+ float ss = mc->options->sensitivity * 0.6f + 0.2f;
+ float sens = (ss * ss * ss) * 8;
+ float xo = mc->mouseHandler.xd * sens;
+ float yo = mc->mouseHandler.yd * sens;
+
+ int yAxis = 1;
+ if (mc->options->invertYMouse) yAxis = -1;
+
+ if (Minecraft.DEADMAU5_CAMERA_CHEATS) {
+ if (!mc->options->fixedCamera) {
+ if (Keyboard.isKeyDown(Keyboard.KEY_J)) {
+ xo = -12f * mc->options->sensitivity;
+ } else if (Keyboard.isKeyDown(Keyboard.KEY_L)) {
+ xo = 12f * mc->options->sensitivity;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_I)) {
+ yo = 12f * mc->options->sensitivity;
+ } else if (Keyboard.isKeyDown(Keyboard.KEY_K)) {
+ yo = -12f * mc->options->sensitivity;
+ }
+ }
+ }
+
+ if (mc->options->smoothCamera) {
+
+ xo = smoothTurnX.getNewDeltaValue(xo, .05f * sens);
+ yo = smoothTurnY.getNewDeltaValue(yo, .05f * sens);
+
+ }
+
+ mc->player.turn(xo, yo * yAxis);
+ }
+#endif
+
+ if (mc->noRender) return;
+ GameRenderer::anaglyph3d = mc->options->anaglyph3d;
+
+ glViewport(0, 0, mc->width, mc->height); // 4J - added
+ ScreenSizeCalculator ssc(mc->options, mc->width, mc->height);
+ int screenWidth = ssc.getWidth();
+ int screenHeight = ssc.getHeight();
+ int xMouse = Mouse::getX() * screenWidth / mc->width;
+ int yMouse = screenHeight - Mouse::getY() * screenHeight / mc->height - 1;
+
+ int maxFps = getFpsCap(mc->options->framerateLimit);
+
+ if (mc->level != NULL)
+ {
+ if (mc->options->framerateLimit == 0)
+ {
+ renderLevel(a, 0);
+ }
+ else
+ {
+ renderLevel(a, lastNsTime + 1000000000 / maxFps);
+ }
+
+ lastNsTime = System::nanoTime();
+
+
+ if (!mc->options->hideGui || mc->screen != NULL)
+ {
+ mc->gui->render(a, mc->screen != NULL, xMouse, yMouse);
+ }
+ }
+ else
+ {
+ glViewport(0, 0, mc->width, mc->height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ setupGuiScreen();
+
+ lastNsTime = System::nanoTime();
+ }
+
+
+ if (mc->screen != NULL)
+ {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ mc->screen->render(xMouse, yMouse, a);
+ if (mc->screen != NULL && mc->screen->particles != NULL) mc->screen->particles->render(a);
+ }
+
+}
+
+void GameRenderer::renderLevel(float a)
+{
+ renderLevel(a, 0);
+}
+
+#ifdef MULTITHREAD_ENABLE
+// Request that an item be deleted, when it is safe to do so
+void GameRenderer::AddForDelete(byte *deleteThis)
+{
+ EnterCriticalSection(&m_csDeleteStack);
+ m_deleteStackByte.push_back(deleteThis);
+}
+
+void GameRenderer::AddForDelete(SparseLightStorage *deleteThis)
+{
+ EnterCriticalSection(&m_csDeleteStack);
+ m_deleteStackSparseLightStorage.push_back(deleteThis);
+}
+
+void GameRenderer::AddForDelete(CompressedTileStorage *deleteThis)
+{
+ EnterCriticalSection(&m_csDeleteStack);
+ m_deleteStackCompressedTileStorage.push_back(deleteThis);
+}
+
+void GameRenderer::AddForDelete(SparseDataStorage *deleteThis)
+{
+ EnterCriticalSection(&m_csDeleteStack);
+ m_deleteStackSparseDataStorage.push_back(deleteThis);
+}
+
+void GameRenderer::FinishedReassigning()
+{
+ LeaveCriticalSection(&m_csDeleteStack);
+}
+
+int GameRenderer::runUpdate(LPVOID lpParam)
+{
+ Minecraft *minecraft = Minecraft::GetInstance();
+ Vec3::CreateNewThreadStorage();
+ AABB::CreateNewThreadStorage();
+ IntCache::CreateNewThreadStorage();
+ Tesselator::CreateNewThreadStorage(1024*1024);
+ Compression::UseDefaultThreadStorage();
+ RenderManager.InitialiseContext();
+#ifdef _LARGE_WORLDS
+ Chunk::CreateNewThreadStorage();
+#endif
+ Tile::CreateNewThreadStorage();
+
+ ShutdownManager::HasStarted(ShutdownManager::eRenderChunkUpdateThread,m_updateEvents);
+ while(ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread))
+ {
+ //m_updateEvents->Clear(eUpdateEventIsFinished);
+ //m_updateEvents->WaitForSingle(eUpdateCanRun,INFINITE);
+ // 4J Stu - We Need to have this happen atomically to avoid deadlocks
+ m_updateEvents->WaitForAll(INFINITE);
+
+ if( !ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread) )
+ {
+ break;
+ }
+
+ m_updateEvents->Set(eUpdateCanRun);
+
+// PIXBeginNamedEvent(0,"Updating dirty chunks %d",(count++)&7);
+
+ // Update chunks atomically until there aren't any very near ones left - they will be deferred for rendering
+ // until the call to CBuffDeferredModeEnd if we have anything near to render here
+ // Now limiting maximum number of updates that can be deferred as have noticed that with redstone clock circuits, it is possible to create
+ // things that need constant updating, so if you stand near them, the render data Never gets updated and the game just keeps going until it runs out of render memory...
+ int count = 0;
+ static const int MAX_DEFERRED_UPDATES = 10;
+ bool shouldContinue = false;
+ do
+ {
+ shouldContinue = minecraft->levelRenderer->updateDirtyChunks();
+ count++;
+ } while ( shouldContinue && count < MAX_DEFERRED_UPDATES );
+
+// while( minecraft->levelRenderer->updateDirtyChunks() )
+// ;
+ RenderManager.CBuffDeferredModeEnd();
+
+ // If any renderable tile entities were flagged in this last block of chunk(s) that were udpated, then change their
+ // flags to say that this deferred chunk is over and they are actually safe to be removed now
+ minecraft->levelRenderer->fullyFlagRenderableTileEntitiesToBeRemoved();
+
+ // We've got stacks for things that can only safely be deleted whilst this thread isn't updating things - delete those things now
+ EnterCriticalSection(&m_csDeleteStack);
+ for(unsigned int i = 0; i < m_deleteStackByte.size(); i++ )
+ {
+ delete m_deleteStackByte[i];
+ }
+ m_deleteStackByte.clear();
+ for(unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); i++ )
+ {
+ delete m_deleteStackSparseLightStorage[i];
+ }
+ m_deleteStackSparseLightStorage.clear();
+ for(unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size(); i++ )
+ {
+ delete m_deleteStackCompressedTileStorage[i];
+ }
+ m_deleteStackCompressedTileStorage.clear();
+ for(unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++ )
+ {
+ delete m_deleteStackSparseDataStorage[i];
+ }
+ m_deleteStackSparseDataStorage.clear();
+ LeaveCriticalSection(&m_csDeleteStack);
+
+// PIXEndNamedEvent();
+
+ AABB::resetPool();
+ Vec3::resetPool();
+ IntCache::Reset();
+ m_updateEvents->Set(eUpdateEventIsFinished);
+ }
+
+ ShutdownManager::HasFinished(ShutdownManager::eRenderChunkUpdateThread);
+ return 0;
+}
+#endif
+
+void GameRenderer::EnableUpdateThread()
+{
+// #ifdef __PS3__ // MGH - disable the update on PS3 for now
+// return;
+// #endif
+#ifdef MULTITHREAD_ENABLE
+ if( updateRunning) return;
+ app.DebugPrintf("------------------EnableUpdateThread--------------------\n");
+ updateRunning = true;
+ m_updateEvents->Set(eUpdateCanRun);
+ m_updateEvents->Set(eUpdateEventIsFinished);
+#endif
+}
+
+void GameRenderer::DisableUpdateThread()
+{
+// #ifdef __PS3__ // MGH - disable the update on PS3 for now
+// return;
+// #endif
+#ifdef MULTITHREAD_ENABLE
+ if( !updateRunning) return;
+ app.DebugPrintf("------------------DisableUpdateThread--------------------\n");
+ updateRunning = false;
+ m_updateEvents->Clear(eUpdateCanRun);
+ m_updateEvents->WaitForSingle(eUpdateEventIsFinished,INFINITE);
+#endif
+}
+
+void GameRenderer::renderLevel(float a, __int64 until)
+{
+// if (updateLightTexture) updateLightTexture(); // 4J - TODO - Java 1.0.1 has this line enabled, should check why - don't want to put it in now in case it breaks split-screen
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ // Is this the primary player? Only do the updating of chunks if it is. This controls the creation of render data for each chunk - all of this we are only
+ // going to do for the primary player, and the other players can just view whatever they have loaded in - we're sharing render data between players.
+ bool updateChunks = ( mc->player == mc->localplayers[ProfileManager.GetPrimaryPad()] );
+
+// if (mc->cameraTargetPlayer == NULL) // 4J - removed condition as we want to update this is mc->player changes for different local players
+ {
+ mc->cameraTargetPlayer = mc->player;
+ }
+ pick(a);
+
+ shared_ptr<Mob> cameraEntity = mc->cameraTargetPlayer;
+ LevelRenderer *levelRenderer = mc->levelRenderer;
+ ParticleEngine *particleEngine = mc->particleEngine;
+ double xOff = cameraEntity->xOld + (cameraEntity->x - cameraEntity->xOld) * a;
+ double yOff = cameraEntity->yOld + (cameraEntity->y - cameraEntity->yOld) * a;
+ double zOff = cameraEntity->zOld + (cameraEntity->z - cameraEntity->zOld) * a;
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (mc->options->anaglyph3d)
+ {
+ GameRenderer::anaglyphPass = i;
+ if (GameRenderer::anaglyphPass == 0) glColorMask(false, true, true, false);
+ else glColorMask(true, false, false, false);
+ }
+
+
+ glViewport(0, 0, mc->width, mc->height);
+ setupClearColor(a);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_CULL_FACE);
+
+ setupCamera(a, i);
+ Camera::prepare(mc->player, mc->player->ThirdPersonView() == 2);
+
+ Frustum::getFrustum();
+ if (mc->options->viewDistance < 2)
+ {
+ setupFog(-1, a);
+ levelRenderer->renderSky(a);
+ if(mc->skins->getSelected()->getId() == 1026 ) levelRenderer->renderHaloRing(a);
+ }
+ glEnable(GL_FOG);
+ setupFog(1, a);
+
+ if (mc->options->ambientOcclusion)
+ {
+ GL11::glShadeModel(GL11::GL_SMOOTH);
+ }
+
+ PIXBeginNamedEvent(0,"Culling");
+ MemSect(31);
+// Culler *frustum = new FrustumCuller();
+ FrustumCuller frustObj;
+ Culler *frustum = &frustObj;
+ MemSect(0);
+ frustum->prepare(xOff, yOff, zOff);
+
+ mc->levelRenderer->cull(frustum, a);
+ PIXEndNamedEvent();
+
+#ifndef MULTITHREAD_ENABLE
+ if ( (i == 0) && updateChunks ) // 4J - added updateChunks condition
+ {
+ int PIXPass = 0;
+ PIXBeginNamedEvent(0,"Updating dirty chunks");
+ do
+ {
+ PIXBeginNamedEvent(0,"Updating dirty chunks pass %d",PIXPass++);
+ bool retval = mc->levelRenderer->updateDirtyChunks(cameraEntity, false);
+ PIXEndNamedEvent();
+ if( retval ) break;
+
+
+ if (until == 0) break;
+
+ __int64 diff = until - System::nanoTime();
+ if (diff < 0) break;
+ if (diff > 1000000000) break;
+ } while (true);
+ PIXEndNamedEvent();
+ }
+#endif
+ setupFog(0, a);
+ glEnable(GL_FOG);
+ MemSect(31);
+ mc->textures->bindTexture(TN_TERRAIN); // 4J was L"/terrain.png"
+ MemSect(0);
+ Lighting::turnOff();
+ PIXBeginNamedEvent(0,"Level render");
+ levelRenderer->render(cameraEntity, 0, a, updateChunks);
+ PIXEndNamedEvent();
+
+ GL11::glShadeModel(GL11::GL_FLAT);
+
+ if (cameraFlip == 0 )
+ {
+ Lighting::turnOn();
+ PIXBeginNamedEvent(0,"Entity render");
+ // 4J - for entities, don't include the "a" factor that interpolates from the old to new position, as the AABBs for the entities are already fully at the new position
+ // This fixes flickering minecarts, and pigs that you are riding on
+ frustum->prepare(cameraEntity->x,cameraEntity->y,cameraEntity->z);
+ // 4J Stu - When rendering entities, in the end if the dragon is hurt or we have a lot of entities we can end up wrapping
+ // our index into the temp Vec3 cache and overwrite the one that was storing the camera position
+ // Fix for #77745 - TU9: Content: Gameplay: Items and mobs not belonging to end world are disappearing when Enderdragon is damaged.
+ Vec3 *cameraPosTemp = cameraEntity->getPos(a);
+ cameraPos->x = cameraPosTemp->x;
+ cameraPos->y = cameraPosTemp->y;
+ cameraPos->z = cameraPosTemp->z;
+ levelRenderer->renderEntities(cameraPos, frustum, a);
+#ifdef __PSVITA__
+ // AP - make sure we're using the Alpha cut out effect for particles
+ glEnable(GL_ALPHA_TEST);
+#endif
+ PIXEndNamedEvent();
+ PIXBeginNamedEvent(0,"Particle render");
+ turnOnLightLayer(a); // 4J - brought forward from 1.8.2
+ particleEngine->renderLit(cameraEntity, a);
+ Lighting::turnOff();
+ setupFog(0, a);
+ particleEngine->render(cameraEntity, a);
+ PIXEndNamedEvent();
+ turnOffLightLayer(a); // 4J - brought forward from 1.8.2
+
+ shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity);
+ if (mc->hitResult != NULL && cameraEntity->isUnderLiquid(Material::water) && player!=NULL) //&& !mc->options.hideGui)
+ {
+ //shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity);
+ glDisable(GL_ALPHA_TEST);
+ levelRenderer->renderHit(player, mc->hitResult, 0, player->inventory->getSelected(), a);
+ levelRenderer->renderHitOutline(player, mc->hitResult, 0, player->inventory->getSelected(), a);
+ glEnable(GL_ALPHA_TEST);
+ }
+ }
+
+ glDisable(GL_BLEND);
+ glEnable(GL_CULL_FACE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(true);
+ setupFog(0, a);
+ glEnable(GL_BLEND);
+ glDisable(GL_CULL_FACE);
+ MemSect(31);
+ mc->textures->bindTexture(TN_TERRAIN); // 4J was L"/terrain.png"
+ MemSect(0);
+ // 4J - have changed this fancy rendering option to work with our command buffers. The original used to use frame buffer flags to disable
+ // writing to colour when doing the z-only pass, but that value gets obliterated by our command buffers. Using alpha blend function instead
+ // to achieve the same effect.
+ if (true) // (mc->options->fancyGraphics)
+ {
+ if (mc->options->ambientOcclusion)
+ {
+ GL11::glShadeModel(GL11::GL_SMOOTH);
+ }
+
+ glBlendFunc(GL_ZERO, GL_ONE);
+ PIXBeginNamedEvent(0,"Fancy second pass - writing z");
+ int visibleWaterChunks = levelRenderer->render(cameraEntity, 1, a, updateChunks);
+ PIXEndNamedEvent();
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if (visibleWaterChunks > 0)
+ {
+ PIXBeginNamedEvent(0,"Fancy second pass - actual rendering");
+ levelRenderer->render(cameraEntity, 1, a, updateChunks); // 4J - chanaged, used to be renderSameAsLast but we don't support that anymore
+ PIXEndNamedEvent();
+ }
+
+ GL11::glShadeModel(GL11::GL_FLAT);
+ }
+ else
+ {
+ PIXBeginNamedEvent(0,"Second pass level render");
+ levelRenderer->render(cameraEntity, 1, a, updateChunks);
+ PIXEndNamedEvent();
+ }
+
+
+ glDepthMask(true);
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+
+ if (zoom == 1 && (dynamic_pointer_cast<Player>(cameraEntity)!=NULL)) //&& !mc->options.hideGui)
+ {
+ if (mc->hitResult != NULL && !cameraEntity->isUnderLiquid(Material::water))
+ {
+ shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity);
+ glDisable(GL_ALPHA_TEST);
+ levelRenderer->renderHit(player, mc->hitResult, 0, player->inventory->getSelected(), a);
+ levelRenderer->renderHitOutline(player, mc->hitResult, 0, player->inventory->getSelected(), a);
+ glEnable(GL_ALPHA_TEST);
+ }
+ }
+
+ /* 4J - moved rain rendering to after clouds so that it alpha blends onto them properly
+ PIXBeginNamedEvent(0,"Rendering snow and rain");
+ renderSnowAndRain(a);
+ PIXEndNamedEvent();
+ glDisable(GL_FOG);
+ */
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ levelRenderer->renderDestroyAnimation(Tesselator::getInstance(), dynamic_pointer_cast<Player>(cameraEntity), a);
+ glDisable(GL_BLEND);
+
+ if (mc->options->isCloudsOn())
+ {
+ glPushMatrix();
+ setupFog(0, a);
+ glEnable(GL_FOG);
+ PIXBeginNamedEvent(0,"Rendering clouds");
+ levelRenderer->renderClouds(a);
+ PIXEndNamedEvent();
+ glDisable(GL_FOG);
+ setupFog(1, a);
+ glPopMatrix();
+ }
+
+ // 4J - rain rendering moved here so that it renders after clouds & can blend properly onto them
+ setupFog(0, a);
+ glEnable(GL_FOG);
+ PIXBeginNamedEvent(0,"Rendering snow and rain");
+ renderSnowAndRain(a);
+ PIXEndNamedEvent();
+ glDisable(GL_FOG);
+
+
+ if (zoom == 1)
+ {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ renderItemInHand(a, i);
+ }
+
+
+ if (!mc->options->anaglyph3d)
+ {
+ return;
+ }
+ }
+ glColorMask(true, true, true, false);
+}
+
+void GameRenderer::tickRain()
+{
+ float rainLevel = mc->level->getRainLevel(1);
+
+ if (!mc->options->fancyGraphics) rainLevel /= 2;
+ if (rainLevel == 0) return;
+
+ rainLevel /= ( mc->levelRenderer->activePlayers() + 1 );
+
+ random->setSeed(_tick * 312987231l);
+ shared_ptr<Mob> player = mc->cameraTargetPlayer;
+ Level *level = mc->level;
+
+ int x0 = Mth::floor(player->x);
+ int y0 = Mth::floor(player->y);
+ int z0 = Mth::floor(player->z);
+
+ int r = 10;
+
+ double rainPosX = 0;
+ double rainPosY = 0;
+ double rainPosZ = 0;
+ int rainPosSamples = 0;
+
+ int rainCount = (int) (100 * rainLevel * rainLevel);
+ if (mc->options->particles == 1)
+ {
+ rainCount >>= 1;
+ } else if (mc->options->particles == 2)
+ {
+ rainCount = 0;
+ }
+ for (int i = 0; i < rainCount; i++)
+ {
+ int x = x0 + random->nextInt(r) - random->nextInt(r);
+ int z = z0 + random->nextInt(r) - random->nextInt(r);
+ int y = level->getTopRainBlock(x, z);
+ int t = level->getTile(x, y - 1, z);
+ Biome *biome = level->getBiome(x,z);
+ if (y <= y0 + r && y >= y0 - r && biome->hasRain() && biome->getTemperature() >= 0.2f)
+ {
+ float xa = random->nextFloat();
+ float za = random->nextFloat();
+ if (t > 0)
+ {
+ if (Tile::tiles[t]->material == Material::lava)
+ {
+ mc->particleEngine->add( shared_ptr<SmokeParticle>( new SmokeParticle(level, x + xa, y + 0.1f - Tile::tiles[t]->getShapeY0(), z + za, 0, 0, 0) ) );
+ }
+ else
+ {
+ if (random->nextInt(++rainPosSamples) == 0)
+ {
+ rainPosX = x + xa;
+ rainPosY = y + 0.1f - Tile::tiles[t]->getShapeY0();
+ rainPosZ = z + za;
+ }
+ mc->particleEngine->add( shared_ptr<WaterDropParticle>( new WaterDropParticle(level, x + xa, y + 0.1f - Tile::tiles[t]->getShapeY0(), z + za) ) );
+ }
+ }
+ }
+ }
+
+
+ if (rainPosSamples > 0 && random->nextInt(3) < rainSoundTime++)
+ {
+ rainSoundTime = 0;
+ MemSect(24);
+ if (rainPosY > player->y + 1 && level->getTopRainBlock(Mth::floor(player->x), Mth::floor(player->z)) > Mth::floor(player->y))
+ {
+ mc->level->playLocalSound(rainPosX, rainPosY, rainPosZ, eSoundType_AMBIENT_WEATHER_RAIN, 0.1f, 0.5f);
+ }
+ else
+ {
+ mc->level->playLocalSound(rainPosX, rainPosY, rainPosZ, eSoundType_AMBIENT_WEATHER_RAIN, 0.2f, 1.0f);
+ }
+ MemSect(0);
+ }
+
+}
+
+// 4J - this whole function updated from 1.8.2
+void GameRenderer::renderSnowAndRain(float a)
+{
+ float rainLevel = mc->level->getRainLevel(a);
+ if (rainLevel <= 0) return;
+
+ // 4J - rain is relatively low poly, but high fill-rate - better to clip it
+ RenderManager.StateSetEnableViewportClipPlanes(true);
+
+ this->turnOnLightLayer(a);
+
+ if (rainXa == NULL)
+ {
+ rainXa = new float[32 * 32];
+ rainZa = new float[32 * 32];
+
+ for (int z = 0; z < 32; z++)
+ {
+ for (int x = 0; x < 32; x++)
+ {
+ float xa = x - 16;
+ float za = z - 16;
+ float d = Mth::sqrt(xa * xa + za * za);
+ rainXa[z << 5 | x] = -za / d;
+ rainZa[z << 5 | x] = xa / d;
+ }
+ }
+ }
+
+ shared_ptr<Mob> player = mc->cameraTargetPlayer;
+ Level *level = mc->level;
+
+ int x0 = Mth::floor(player->x);
+ int y0 = Mth::floor(player->y);
+ int z0 = Mth::floor(player->z);
+
+ Tesselator *t = Tesselator::getInstance();
+ glDisable(GL_CULL_FACE);
+ glNormal3f(0, 1, 0);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glAlphaFunc(GL_GREATER, 0.01f);
+
+ MemSect(31);
+ mc->textures->bindTexture(TN_ENVIRONMENT_SNOW); // 4J was L"/environment/snow.png"
+ MemSect(0);
+
+ double xo = player->xOld + (player->x - player->xOld) * a;
+ double yo = player->yOld + (player->y - player->yOld) * a;
+ double zo = player->zOld + (player->z - player->zOld) * a;
+
+ int yMin = Mth::floor(yo);
+
+
+ int r = 5;
+ // 4J - was if(mc.options.fancyGraphics) r = 10;
+ switch( mc->levelRenderer->activePlayers() )
+ {
+ case 1:
+ default:
+ r = 9;
+ break;
+ case 2:
+ r = 7;
+ break;
+ case 3:
+ r = 5;
+ break;
+ case 4:
+ r = 5;
+ break;
+ }
+
+ // 4J - some changes made here to access biome through new interface that caches results in levelchunk flags, as an optimisation
+
+ int mode = -1;
+ float time = _tick + a;
+
+ glColor4f(1, 1, 1, 1);
+
+ for (int x = x0 - r; x <= x0 + r; x++)
+ for (int z = z0 - r; z <= z0 + r; z++)
+ {
+ int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16);
+ float xa = rainXa[rainSlot] * 0.5f;
+ float za = rainZa[rainSlot] * 0.5f;
+
+ // 4J - changes here brought forward from 1.8.2
+ Biome *b = level->getBiome(x, z);
+ if (!b->hasRain() && !b->hasSnow()) continue;
+
+ int floor = level->getTopRainBlock(x, z);
+
+ int yy0 = y0 - r;
+ int yy1 = y0 + r;
+
+ if (yy0 < floor) yy0 = floor;
+ if (yy1 < floor) yy1 = floor;
+ float s = 1;
+
+ int yl = floor;
+ if (yl < yMin) yl = yMin;
+
+ if (yy0 != yy1)
+ {
+ random->setSeed((x * x * 3121 + x * 45238971) ^ (z * z * 418711 + z * 13761));
+
+ // 4J - changes here brought forward from 1.8.2
+ float temp = b->getTemperature();
+ if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f)
+ {
+ if (mode != 0)
+ {
+ if (mode >= 0) t->end();
+ mode = 0;
+ mc->textures->bindTexture(TN_ENVIRONMENT_RAIN);
+ t->begin();
+ }
+
+ float ra = (((_tick + x * x * 3121 + x * 45238971 + z * z * 418711 + z * 13761) & 31) + a) / 32.0f * (3 + random->nextFloat());
+
+ double xd = (x + 0.5f) - player->x;
+ double zd = (z + 0.5f) - player->z;
+ float dd = (float) Mth::sqrt(xd * xd + zd * zd) / r;
+
+ float br = 1;
+ t->offset(-xo * 1, -yo * 1, -zo * 1);
+#ifdef __PSVITA__
+ // AP - this will set up the 4 vertices in half the time
+ float Alpha = ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel;
+ int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
+ t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s,
+ x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s,
+ x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s,
+ x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s,
+ br, br, br, Alpha, br, br, br, 0, tex2);
+#else
+ t->tex2(level->getLightColor(x, yl, z, 0));
+ t->color(br, br, br, ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel);
+ t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s);
+ t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s);
+ t->color(br, br, br, 0.0f); // 4J - added to soften the top visible edge of the rain
+ t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s);
+ t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s);
+#endif
+ t->offset(0, 0, 0);
+ t->end();
+ }
+ else
+ {
+ if (mode != 1)
+ {
+ if (mode >= 0) t->end();
+ mode = 1;
+ mc->textures->bindTexture(TN_ENVIRONMENT_SNOW);
+ t->begin();
+ }
+ float ra = (((_tick) & 511) + a) / 512.0f;
+ float uo = random->nextFloat() + time * 0.01f * (float) random->nextGaussian();
+ float vo = random->nextFloat() + time * (float) random->nextGaussian() * 0.001f;
+ double xd = (x + 0.5f) - player->x;
+ double zd = (z + 0.5f) - player->z;
+ float dd = (float) sqrt(xd * xd + zd * zd) / r;
+ float br = 1;
+ t->offset(-xo * 1, -yo * 1, -zo * 1);
+#ifdef __PSVITA__
+ // AP - this will set up the 4 vertices in half the time
+ float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel;
+ int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
+ t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo,
+ x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo,
+ x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo,
+ x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo,
+ br, br, br, Alpha, br, br, br, Alpha, tex2);
+#else
+ t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4);
+ t->color(br, br, br, ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel);
+ t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo);
+ t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo);
+ t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo);
+ t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo);
+#endif
+ t->offset(0, 0, 0);
+ }
+ }
+ }
+
+ if( mode >= 0 ) t->end();
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glAlphaFunc(GL_GREATER, 0.1f);
+ this->turnOffLightLayer(a);
+
+ RenderManager.StateSetEnableViewportClipPlanes(false);
+}
+
+// 4J - added forceScale parameter
+void GameRenderer::setupGuiScreen(int forceScale /*=-1*/)
+{
+ ScreenSizeCalculator ssc(mc->options, mc->width, mc->height, forceScale);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, (float)ssc.rawWidth, (float)ssc.rawHeight, 0, 1000, 3000);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0, 0, -2000);
+}
+
+void GameRenderer::setupClearColor(float a)
+{
+ Level *level = mc->level;
+ shared_ptr<Mob> player = mc->cameraTargetPlayer;
+
+ float whiteness = 1.0f / (4 - mc->options->viewDistance);
+ whiteness = 1 - (float) pow((double)whiteness, 0.25);
+
+ 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;
+
+ if (mc->options->viewDistance < 2)
+ {
+ Vec3 *sunAngle = Mth::sin(level->getSunAngle(a)) > 0 ? Vec3::newTemp(-1, 0, 0) : Vec3::newTemp(1, 0, 0);
+ float d = (float) player->getViewVector(a)->dot(sunAngle);
+ if (d < 0) d = 0;
+ if (d > 0)
+ {
+ float *c = level->dimension->getSunriseColor(level->getTimeOfDay(a), a);
+ if (c != NULL)
+ {
+ d *= c[3];
+ fr = fr * (1 - d) + c[0] * d;
+ fg = fg * (1 - d) + c[1] * d;
+ fb = fb * (1 - d) + c[2] * d;
+ }
+ }
+ }
+
+ fr += (sr - fr) * whiteness;
+ fg += (sg - fg) * whiteness;
+ fb += (sb - fb) * whiteness;
+
+ float rainLevel = level->getRainLevel(a);
+ if (rainLevel > 0)
+ {
+ float ba = 1 - rainLevel * 0.5f;
+ float bb = 1 - rainLevel * 0.4f;
+ fr *= ba;
+ fg *= ba;
+ fb *= bb;
+ }
+ float thunderLevel = level->getThunderLevel(a);
+ if (thunderLevel > 0)
+ {
+ float ba = 1 - thunderLevel * 0.5f;
+ fr *= ba;
+ fg *= ba;
+ fb *= ba;
+ }
+
+ int t = Camera::getBlockAt(mc->level, player, a);
+ if (isInClouds)
+ {
+ Vec3 *cc = level->getCloudColor(a);
+ fr = (float) cc->x;
+ fg = (float) cc->y;
+ fb = (float) cc->z;
+ }
+ else if (t != 0 && Tile::tiles[t]->material == Material::water)
+ {
+
+ unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Water_Clear_Colour );
+ byte redComponent = ((colour>>16)&0xFF);
+ byte greenComponent = ((colour>>8)&0xFF);
+ byte blueComponent = ((colour)&0xFF);
+
+ fr = (float)redComponent/256;//0.02f;
+ fg = (float)greenComponent/256;//0.02f;
+ fb = (float)blueComponent/256;//0.2f;
+ }
+ else if (t != 0 && Tile::tiles[t]->material == Material::lava)
+ {
+
+ unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Lava_Clear_Colour );
+ byte redComponent = ((colour>>16)&0xFF);
+ byte greenComponent = ((colour>>8)&0xFF);
+ byte blueComponent = ((colour)&0xFF);
+
+ fr = (float)redComponent/256;//0.6f;
+ fg = (float)greenComponent/256;//0.1f;
+ fb = (float)blueComponent/256;//0.00f;
+ }
+
+ float brr = fogBrO + (fogBr - fogBrO) * a;
+ fr *= brr;
+ fg *= brr;
+ fb *= brr;
+
+ double yy = (player->yOld + (player->y - player->yOld) * a) * level->dimension->getClearColorScale(); // 4J - getClearColorScale brought forward from 1.2.3
+
+ if (player->hasEffect(MobEffect::blindness))
+ {
+ int duration = player->getEffect(MobEffect::blindness)->getDuration();
+ if (duration < 20)
+ {
+ yy = yy * (1.0f - (float) duration / 20.0f);
+ }
+ else
+ {
+ yy = 0;
+ }
+ }
+
+ if (yy < 1)
+ {
+ if (yy < 0) yy = 0;
+ yy = yy * yy;
+ fr *= yy;
+ fg *= yy;
+ fb *= yy;
+ }
+
+ if (player->hasEffect(MobEffect::nightVision))
+ {
+ float scale = getNightVisionScale(mc->player, a);
+ {
+ float dist = FLT_MAX; // MGH - changed this to avoid divide by zero
+ if ( (fr > 0) && (dist > (1.0f / fr)) )
+ {
+ dist = (1.0f / fr);
+ }
+ if ( (fg > 0) && (dist > (1.0f / fg)) )
+ {
+ dist = (1.0f / fg);
+ }
+ if ( (fb > 0) && (dist > (1.0f / fb)) )
+ {
+ dist = (1.0f / fb);
+ }
+ fr = fr * (1.0f - scale) + (fr * dist) * scale;
+ fg = fg * (1.0f - scale) + (fg * dist) * scale;
+ fb = fb * (1.0f - scale) + (fb * dist) * scale;
+ }
+ }
+
+ 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, 0.0f);
+
+}
+
+void GameRenderer::setupFog(int i, float alpha)
+{
+ shared_ptr<Mob> player = mc->cameraTargetPlayer;
+
+ // 4J - check for creative mode brought forward from 1.2.3
+ bool creative = false;
+ if (dynamic_pointer_cast<Player>(player) )
+ {
+ creative = (dynamic_pointer_cast<Player>(player))->abilities.instabuild;
+ }
+
+ if (i == 999)
+ {
+ __debugbreak();
+ // 4J TODO
+ /*
+ glFog(GL_FOG_COLOR, getBuffer(0, 0, 0, 1));
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ glFogf(GL_FOG_START, 0);
+ glFogf(GL_FOG_END, 8);
+
+ if (GLContext.getCapabilities().GL_NV_fog_distance) {
+ glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
+ }
+
+ glFogf(GL_FOG_START, 0);
+ */
+ return;
+ }
+
+ glFog(GL_FOG_COLOR, getBuffer(fr, fg, fb, 1));
+ glNormal3f(0, -1, 0);
+ glColor4f(1, 1, 1, 1);
+
+ int t = Camera::getBlockAt(mc->level, player, alpha);
+
+ if (player->hasEffect(MobEffect::blindness))
+ {
+ float distance = 5.0f;
+ int duration = player->getEffect(MobEffect::blindness)->getDuration();
+ if (duration < 20)
+ {
+ distance = 5.0f + (renderDistance - 5.0f) * (1.0f - (float) duration / 20.0f);
+ }
+
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ if (i < 0)
+ {
+ glFogf(GL_FOG_START, 0);
+ glFogf(GL_FOG_END, distance * 0.8f);
+ }
+ else
+ {
+ glFogf(GL_FOG_START, distance * 0.25f);
+ glFogf(GL_FOG_END, distance);
+ }
+ // 4J - TODO investigate implementing this
+// if (GLContext.getCapabilities().GL_NV_fog_distance)
+// {
+// glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
+// }
+ }
+ else if (isInClouds)
+ {
+ glFogi(GL_FOG_MODE, GL_EXP);
+ glFogf(GL_FOG_DENSITY, 0.1f); // was 0.06
+
+ unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_In_Cloud_Fog_Colour );
+ byte redComponent = ((colour>>16)&0xFF);
+ byte greenComponent = ((colour>>8)&0xFF);
+ byte blueComponent = ((colour)&0xFF);
+
+ float rr = (float)redComponent/256;//1.0f;
+ float gg = (float)greenComponent/256;//1.0f;
+ float bb = (float)blueComponent/256;//1.0f;
+
+ 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 (t > 0 && Tile::tiles[t]->material == Material::water)
+ {
+ glFogi(GL_FOG_MODE, GL_EXP);
+ if (player->hasEffect(MobEffect::waterBreathing))
+ {
+ glFogf(GL_FOG_DENSITY, 0.05f); // was 0.06
+ }
+ else
+ {
+ glFogf(GL_FOG_DENSITY, 0.1f); // was 0.06
+ }
+
+ unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Water_Fog_Colour );
+ byte redComponent = ((colour>>16)&0xFF);
+ byte greenComponent = ((colour>>8)&0xFF);
+ byte blueComponent = ((colour)&0xFF);
+
+ float rr = (float)redComponent/256;//0.4f;
+ float gg = (float)greenComponent/256;//0.4f;
+ float bb = (float)blueComponent/256;//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 (t > 0 && Tile::tiles[t]->material == Material::lava)
+ {
+ glFogi(GL_FOG_MODE, GL_EXP);
+ glFogf(GL_FOG_DENSITY, 2.0f); // was 0.06
+
+ unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Lava_Fog_Colour );
+ byte redComponent = ((colour>>16)&0xFF);
+ byte greenComponent = ((colour>>8)&0xFF);
+ byte blueComponent = ((colour)&0xFF);
+
+ float rr = (float)redComponent/256;//0.4f;
+ float gg = (float)greenComponent/256;//0.3f;
+ float bb = (float)blueComponent/256;//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
+ {
+ float distance = renderDistance;
+ if (!mc->level->dimension->hasCeiling)
+ {
+ // 4J - test for doing bedrockfog brought forward from 1.2.3
+ if (mc->level->dimension->hasBedrockFog() && !creative)
+ {
+ double yy = ((player->getLightColor(alpha) & 0xf00000) >> 20) / 16.0 + (player->yOld + (player->y - player->yOld) * alpha + 4) / 32;
+ if (yy < 1)
+ {
+ if (yy < 0) yy = 0;
+ yy = yy * yy;
+ float dist = 100 * (float) yy;
+ if (dist < 5) dist = 5;
+ if (distance > dist) distance = dist;
+ }
+ }
+ }
+
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ glFogf(GL_FOG_START, distance * 0.25f);
+ glFogf(GL_FOG_END, distance);
+ if (i < 0)
+ {
+ glFogf(GL_FOG_START, 0);
+ glFogf(GL_FOG_END, distance * 0.8f);
+ }
+ else
+ {
+ glFogf(GL_FOG_START, distance * 0.25f);
+ glFogf(GL_FOG_END, distance);
+ }
+ /* 4J - removed - TODO investigate
+ if (GLContext.getCapabilities().GL_NV_fog_distance)
+ {
+ glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
+ }
+ */
+
+ if (mc->level->dimension->isFoggyAt((int) player->x, (int) player->z))
+ {
+ glFogf(GL_FOG_START, distance * 0.05f);
+ glFogf(GL_FOG_END, min(distance, 16 * 16 * .75f) * .5f);
+ }
+ }
+
+ glEnable(GL_COLOR_MATERIAL);
+ glColorMaterial(GL_FRONT, GL_AMBIENT);
+
+}
+
+FloatBuffer *GameRenderer::getBuffer(float a, float b, float c, float d)
+{
+ lb->clear();
+ lb->put(a)->put(b)->put(c)->put(d);
+ lb->flip();
+ return lb;
+}
+
+int GameRenderer::getFpsCap(int option)
+{
+ int maxFps = 200;
+ if (option == 1) maxFps = 120;
+ if (option == 2) maxFps = 35;
+ return maxFps;
+}
+
+void GameRenderer::updateAllChunks()
+{
+// mc->levelRenderer->updateDirtyChunks(mc->cameraTargetPlayer, true);
+}