the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "GameRenderer.h"
3#include "ItemInHandRenderer.h"
4#include "LevelRenderer.h"
5#include "Frustum.h"
6#include "FrustumCuller.h"
7#include "Textures.h"
8#include "Tesselator.h"
9#include "ParticleEngine.h"
10#include "SmokeParticle.h"
11#include "WaterDropParticle.h"
12#include "GameMode.h"
13#include "CreativeMode.h"
14#include "Lighting.h"
15#include "Options.h"
16#include "MultiplayerLocalPlayer.h"
17#include "GuiParticles.h"
18#include "MultiPlayerLevel.h"
19#include "Chunk.h"
20#include "..\Minecraft.World\net.minecraft.world.entity.h"
21#include "..\Minecraft.World\net.minecraft.world.entity.player.h"
22#include "..\Minecraft.World\net.minecraft.world.item.enchantment.h"
23#include "..\Minecraft.World\net.minecraft.world.level.h"
24#include "..\Minecraft.World\net.minecraft.world.level.material.h"
25#include "..\Minecraft.World\net.minecraft.world.level.tile.h"
26#include "..\Minecraft.World\net.minecraft.world.level.chunk.h"
27#include "..\Minecraft.World\net.minecraft.world.level.biome.h"
28#include "..\Minecraft.World\net.minecraft.world.level.dimension.h"
29#include "..\Minecraft.World\net.minecraft.world.phys.h"
30#include "..\Minecraft.World\System.h"
31#include "..\Minecraft.World\FloatBuffer.h"
32#include "..\Minecraft.World\ThreadName.h"
33#include "..\Minecraft.World\SparseLightStorage.h"
34#include "..\Minecraft.World\CompressedTileStorage.h"
35#include "..\Minecraft.World\SparseDataStorage.h"
36#include "..\Minecraft.World\JavaMath.h"
37#include "..\Minecraft.World\Facing.h"
38#include "..\Minecraft.World\MobEffect.h"
39#include "..\Minecraft.World\IntCache.h"
40#include "..\Minecraft.World\SmoothFloat.h"
41#include "..\Minecraft.World\MobEffectInstance.h"
42#include "..\Minecraft.World\Item.h"
43#include "Camera.h"
44#include "..\Minecraft.World\SoundTypes.h"
45#include "HumanoidModel.h"
46#include "..\Minecraft.World\Item.h"
47#include "..\Minecraft.World\compression.h"
48#include "PS3\PS3Extras\ShutdownManager.h"
49#include "BossMobGuiInfo.h"
50
51#include "TexturePackRepository.h"
52#include "TexturePack.h"
53#include "TextureAtlas.h"
54
55bool GameRenderer::anaglyph3d = false;
56int GameRenderer::anaglyphPass = 0;
57
58#ifdef MULTITHREAD_ENABLE
59C4JThread* GameRenderer::m_updateThread;
60C4JThread::EventArray* GameRenderer::m_updateEvents;
61bool GameRenderer::nearThingsToDo = false;
62bool GameRenderer::updateRunning = false;
63vector<byte *> GameRenderer::m_deleteStackByte;
64vector<SparseLightStorage *> GameRenderer::m_deleteStackSparseLightStorage;
65vector<CompressedTileStorage *> GameRenderer::m_deleteStackCompressedTileStorage;
66vector<SparseDataStorage *> GameRenderer::m_deleteStackSparseDataStorage;
67#endif
68CRITICAL_SECTION GameRenderer::m_csDeleteStack;
69
70ResourceLocation GameRenderer::RAIN_LOCATION = ResourceLocation(TN_ENVIRONMENT_RAIN);
71ResourceLocation GameRenderer::SNOW_LOCATION = ResourceLocation(TN_ENVIRONMENT_SNOW);
72
73GameRenderer::GameRenderer(Minecraft *mc)
74{
75 // 4J - added this block of initialisers
76 renderDistance = 0;
77 _tick = 0;
78 hovered = nullptr;
79 thirdDistance = 4;
80 thirdDistanceO = 4;
81 thirdRotation = 0;
82 thirdRotationO = 0;
83 thirdTilt = 0;
84 thirdTiltO = 0;
85
86 accumulatedSmoothXO = 0;
87 accumulatedSmoothYO = 0;
88 tickSmoothXO = 0;
89 tickSmoothYO = 0;
90 lastTickA = 0;
91
92 cameraPos = Vec3::newPermanent(0.0f,0.0f,0.0f);
93
94 fovOffset = 0;
95 fovOffsetO = 0;
96 cameraRoll = 0;
97 cameraRollO = 0;
98 for( int i = 0; i < 4; i++ )
99 {
100 fov[i] = 0.0f;
101 oFov[i] = 0.0f;
102 tFov[i] = 0.0f;
103 }
104 isInClouds = false;
105 zoom = 1;
106 zoom_x = 0;
107 zoom_y = 0;
108 rainXa = NULL;
109 rainZa = NULL;
110 lastActiveTime = Minecraft::currentTimeMillis();
111 lastNsTime = 0;
112 random = new Random();
113 rainSoundTime = 0;
114 xMod = 0;
115 yMod = 0;
116 lb = MemoryTracker::createFloatBuffer(16);
117 fr = 0.0f;
118 fg = 0.0f;
119 fb = 0.0f;
120 fogBrO = 0.0f;
121 fogBr = 0.0f;
122 cameraFlip = 0;
123 _updateLightTexture = false;
124 blr = 0.0f;
125 blrt = 0.0f;
126 blg = 0.0f;
127 blgt = 0.0f;
128
129 darkenWorldAmount = 0.0f;
130 darkenWorldAmountO = 0.0f;
131
132 m_fov=70.0f;
133
134 // 4J Stu - Init these so they are setup before the tick
135 for( int i = 0; i < 4; i++ )
136 {
137 fov[i] = oFov[i] = 1.0f;
138 }
139
140 this->mc = mc;
141 itemInHandRenderer = NULL;
142
143 // 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
144 glEnable(GL_LIGHTING);
145 mc->localitemInHandRenderers[0] = new ItemInHandRenderer(mc);//itemInHandRenderer;
146 mc->localitemInHandRenderers[1] = new ItemInHandRenderer(mc);
147 mc->localitemInHandRenderers[2] = new ItemInHandRenderer(mc);
148 mc->localitemInHandRenderers[3] = new ItemInHandRenderer(mc);
149 glDisable(GL_LIGHTING);
150
151 // 4J - changes brought forward from 1.8.2
152 BufferedImage *img = new BufferedImage(16, 16, BufferedImage::TYPE_INT_RGB);
153 for( int i = 0; i < NUM_LIGHT_TEXTURES; i++ )
154 {
155 lightTexture[i] = mc->textures->getTexture(img); // 4J - changed to one light texture per level to support split screen
156 }
157 delete img;
158#ifdef __PS3__
159 // we're using the RSX now to upload textures to vram, so we need the main ram textures allocated from io space
160 for(int i=0;i<NUM_LIGHT_TEXTURES;i++)
161 lightPixels[i] = intArray((int*)RenderManager.allocIOMem(16*16*sizeof(int)), 16*16);
162#else
163 for(int i=0;i<NUM_LIGHT_TEXTURES;i++)
164 lightPixels[i] = intArray(16*16);
165#endif
166
167#ifdef MULTITHREAD_ENABLE
168 m_updateEvents = new C4JThread::EventArray(eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear);
169 m_updateEvents->Set(eUpdateEventIsFinished);
170
171 InitializeCriticalSection(&m_csDeleteStack);
172 m_updateThread = new C4JThread(runUpdate, NULL, "Chunk update");
173#ifdef __PS3__
174 m_updateThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
175#endif// __PS3__
176 m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE);
177 m_updateThread->Run();
178#endif
179}
180
181// 4J Stu Added to go with 1.8.2 change
182GameRenderer::~GameRenderer()
183{
184 if(rainXa != NULL) delete [] rainXa;
185 if(rainZa != NULL) delete [] rainZa;
186}
187
188void GameRenderer::tick(bool first) // 4J - add bFirst
189{
190 tickFov();
191 tickLightTexture(); // 4J - change brought forward from 1.8.2
192 fogBrO = fogBr;
193 thirdDistanceO = thirdDistance;
194 thirdRotationO = thirdRotation;
195 thirdTiltO = thirdTilt;
196 fovOffsetO = fovOffset;
197 cameraRollO = cameraRoll;
198
199 if (mc->options->smoothCamera)
200 {
201 // update player view in tick() instead of render() to maintain
202 // camera movement regardless of FPS
203 float ss = mc->options->sensitivity * 0.6f + 0.2f;
204 float sens = (ss * ss * ss) * 8;
205 tickSmoothXO = smoothTurnX.getNewDeltaValue(accumulatedSmoothXO, 0.05f * sens);
206 tickSmoothYO = smoothTurnY.getNewDeltaValue(accumulatedSmoothYO, 0.05f * sens);
207 lastTickA = 0;
208
209 accumulatedSmoothXO = 0;
210 accumulatedSmoothYO = 0;
211 }
212
213 if (mc->cameraTargetPlayer == NULL)
214 {
215 mc->cameraTargetPlayer = dynamic_pointer_cast<Mob>(mc->player);
216 }
217
218 float brr = mc->level->getBrightness(Mth::floor(mc->cameraTargetPlayer->x), Mth::floor(mc->cameraTargetPlayer->y), Mth::floor(mc->cameraTargetPlayer->z));
219 float whiteness = (3 - mc->options->viewDistance) / 3.0f;
220 float fogBrT = brr * (1 - whiteness) + whiteness;
221 fogBr += (fogBrT - fogBr) * 0.1f;
222
223 itemInHandRenderer->tick();
224
225 PIXBeginNamedEvent(0,"Rain tick");
226 tickRain();
227 PIXEndNamedEvent();
228
229 darkenWorldAmountO = darkenWorldAmount;
230 if (BossMobGuiInfo::darkenWorld)
231 {
232 darkenWorldAmount += 1.0f / ((float) SharedConstants::TICKS_PER_SECOND * 1);
233 if (darkenWorldAmount > 1)
234 {
235 darkenWorldAmount = 1;
236 }
237 BossMobGuiInfo::darkenWorld = false;
238 }
239 else if (darkenWorldAmount > 0)
240 {
241 darkenWorldAmount -= 1.0f / ((float) SharedConstants::TICKS_PER_SECOND * 4);
242 }
243
244 if( mc->player != mc->localplayers[ProfileManager.GetPrimaryPad()] ) return; // 4J added for split screen - only do rest of processing for once per frame
245
246 _tick++;
247}
248
249void GameRenderer::pick(float a)
250{
251 if (mc->cameraTargetPlayer == NULL) return;
252 if (mc->level == NULL) return;
253
254 mc->crosshairPickMob = nullptr;
255
256 double range = mc->gameMode->getPickRange();
257 delete mc->hitResult;
258 MemSect(31);
259 mc->hitResult = mc->cameraTargetPlayer->pick(range, a);
260 MemSect(0);
261
262 // 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
263 if( mc->hitResult )
264 {
265 int maxxz = ( ( mc->level->chunkSource->m_XZSize / 2 ) * 16 ) - 2;
266 int minxz = ( -( mc->level->chunkSource->m_XZSize / 2 ) * 16 ) + 1;
267
268 // Don't select the tops of the very edge blocks, or the sides of the next blocks in
269 // 4J Stu - Only block the sides that are facing an outside block
270 int hitx = mc->hitResult->x;
271 int hitz = mc->hitResult->z;
272 int face = mc->hitResult->f;
273 if( face == Facing::WEST && hitx < 0 ) hitx -= 1;
274 if( face == Facing::EAST && hitx > 0 ) hitx += 1;
275 if( face == Facing::NORTH && hitz < 0 ) hitz -= 1;
276 if( face == Facing::SOUTH && hitz > 0 ) hitz += 1;
277
278 if( ( hitx < minxz ) || ( hitx > maxxz) ||
279 ( hitz < minxz ) || ( hitz > maxxz) )
280 {
281 delete mc->hitResult;
282 mc->hitResult = NULL;
283 }
284 }
285
286 double dist = range;
287 Vec3 *from = mc->cameraTargetPlayer->getPos(a);
288
289 if (mc->gameMode->hasFarPickRange())
290 {
291 dist = range = 6;
292 }
293 else
294 {
295 if (dist > 3) dist = 3;
296 range = dist;
297 }
298
299 if (mc->hitResult != NULL)
300 {
301 dist = mc->hitResult->pos->distanceTo(from);
302 }
303
304 Vec3 *b = mc->cameraTargetPlayer->getViewVector(a);
305 Vec3 *to = from->add(b->x * range, b->y * range, b->z * range);
306 hovered = nullptr;
307 float overlap = 1;
308 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));
309 double nearest = dist;
310
311 AUTO_VAR(itEnd, objects->end());
312 for (AUTO_VAR(it, objects->begin()); it != itEnd; it++)
313 {
314 shared_ptr<Entity> e = *it; //objects->at(i);
315 if (!e->isPickable()) continue;
316
317 float rr = e->getPickRadius();
318 AABB *bb = e->bb->grow(rr, rr, rr);
319 HitResult *p = bb->clip(from, to);
320 if (bb->contains(from))
321 {
322 if (0 < nearest || nearest == 0)
323 {
324 hovered = e;
325 nearest = 0;
326 }
327 }
328 else if (p != NULL)
329 {
330 double dd = from->distanceTo(p->pos);
331 if (e == mc->cameraTargetPlayer->riding != NULL)
332 {
333 if (nearest == 0)
334 {
335 hovered = e;
336 }
337 }
338 else
339 {
340 hovered = e;
341 nearest = dd;
342 }
343 }
344 delete p;
345 }
346
347 if (hovered != NULL)
348 {
349 if (nearest < dist || (mc->hitResult == NULL))
350 {
351 if( mc->hitResult != NULL )
352 delete mc->hitResult;
353 mc->hitResult = new HitResult(hovered);
354 if (hovered->instanceof(eTYPE_LIVINGENTITY))
355 {
356 mc->crosshairPickMob = dynamic_pointer_cast<LivingEntity>(hovered);
357 }
358 }
359 }
360}
361
362void GameRenderer::SetFovVal(float fov)
363{
364 m_fov=fov;
365}
366
367float GameRenderer::GetFovVal()
368{
369 return m_fov;
370}
371
372void GameRenderer::tickFov()
373{
374 shared_ptr<LocalPlayer>player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
375
376 int playerIdx = player ? player->GetXboxPad() : 0;
377 tFov[playerIdx] = player->getFieldOfViewModifier();
378
379 oFov[playerIdx] = fov[playerIdx];
380 fov[playerIdx] += (tFov[playerIdx] - fov[playerIdx]) * 0.5f;
381
382 if (fov[playerIdx] > 1.5f) fov[playerIdx] = 1.5f;
383 if (fov[playerIdx] < 0.1f) fov[playerIdx] = 0.1f;
384}
385
386float GameRenderer::getFov(float a, bool applyEffects)
387{
388 if (cameraFlip > 0 ) return 90;
389
390 shared_ptr<LocalPlayer> player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
391 int playerIdx = player ? player->GetXboxPad() : 0;
392 float fov = m_fov;//70;
393 if (applyEffects)
394 {
395 fov += mc->options->fov * 40;
396 fov *= oFov[playerIdx] + (this->fov[playerIdx] - oFov[playerIdx]) * a;
397 }
398 if (player->getHealth() <= 0)
399 {
400 float duration = player->deathTime + a;
401
402 fov /= ((1 - 500 / (duration + 500)) * 2.0f + 1);
403 }
404
405 int t = Camera::getBlockAt(mc->level, player, a);
406 if (t != 0 && Tile::tiles[t]->material == Material::water) fov = fov * 60 / 70;
407
408 return fov + fovOffsetO + (fovOffset - fovOffsetO) * a;
409
410}
411
412void GameRenderer::bobHurt(float a)
413{
414 shared_ptr<LivingEntity> player = mc->cameraTargetPlayer;
415
416 float hurt = player->hurtTime - a;
417
418 if (player->getHealth() <= 0)
419 {
420 float duration = player->deathTime + a;
421
422 glRotatef(40 - (40 * 200) / (duration + 200), 0, 0, 1);
423 }
424
425 if (hurt < 0) return;
426 hurt /= player->hurtDuration;
427 hurt = (float) Mth::sin(hurt * hurt * hurt * hurt * PI);
428
429 float rr = player->hurtDir;
430
431
432 glRotatef(-rr, 0, 1, 0);
433 glRotatef(-hurt * 14, 0, 0, 1);
434 glRotatef(+rr, 0, 1, 0);
435
436}
437
438void GameRenderer::bobView(float a)
439{
440 if (!mc->cameraTargetPlayer->instanceof(eTYPE_LIVINGENTITY)) return;
441
442 shared_ptr<Player> player = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer);
443
444 float wda = player->walkDist - player->walkDistO;
445 float b = -(player->walkDist + wda * a);
446 float bob = player->oBob + (player->bob - player->oBob) * a;
447 float tilt = player->oTilt + (player->tilt - player->oTilt) * a;
448 glTranslatef((float) Mth::sin(b * PI) * bob * 0.5f, -(float) abs(Mth::cos(b * PI) * bob), 0);
449 glRotatef((float) Mth::sin(b * PI) * bob * 3, 0, 0, 1);
450 glRotatef((float) abs(Mth::cos(b * PI - 0.2f) * bob) * 5, 1, 0, 0);
451 glRotatef((float) tilt, 1, 0, 0);
452}
453
454void GameRenderer::moveCameraToPlayer(float a)
455{
456 shared_ptr<LivingEntity> player = mc->cameraTargetPlayer;
457 shared_ptr<LocalPlayer> localplayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
458 float heightOffset = player->heightOffset - 1.62f;
459
460 double x = player->xo + (player->x - player->xo) * a;
461 double y = player->yo + (player->y - player->yo) * a - heightOffset;
462 double z = player->zo + (player->z - player->zo) * a;
463
464
465 glRotatef(cameraRollO + (cameraRoll - cameraRollO) * a, 0, 0, 1);
466
467 if (player->isSleeping())
468 {
469 heightOffset += 1.0;
470 glTranslatef(0.0f, 0.3f, 0);
471 if (!mc->options->fixedCamera)
472 {
473 int t = mc->level->getTile(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
474 if (t == Tile::bed_Id)
475 {
476 int data = mc->level->getData(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
477
478 int direction = data & 3;
479 glRotatef((float)direction * 90,0.0f, 1.0f, 0.0f);
480 }
481 glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, -1, 0);
482 glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, -1, 0, 0);
483 }
484 }
485 // 4J-PB - changing this to be per player
486 //else if (mc->options->thirdPersonView)
487 else if (localplayer->ThirdPersonView())
488 {
489 double cameraDist = thirdDistanceO + (thirdDistance - thirdDistanceO) * a;
490
491 if (mc->options->fixedCamera)
492 {
493
494 float rotationY = thirdRotationO + (thirdRotation - thirdRotationO) * a;
495 float xRot = thirdTiltO + (thirdTilt - thirdTiltO) * a;
496
497 glTranslatef(0, 0, (float) -cameraDist);
498 glRotatef(xRot, 1, 0, 0);
499 glRotatef(rotationY, 0, 1, 0);
500 }
501 else
502 {
503 // 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
504 float playerYRot = player->yRotO + (player->yRot - player->yRotO) * a;
505 float playerXRot = player->xRotO + (player->xRot - player->xRotO) * a;
506 float yRot = playerYRot;
507 float xRot = playerXRot;
508
509 // Thirdperson view values are now 0 for disabled, 1 for original mode, 2 for reversed.
510 if( localplayer->ThirdPersonView() == 2 )
511 {
512 // Reverse x rotation - note that this is only used in doing collision to calculate our view
513 // distance, the actual rotation itself is just below this else {} block
514 xRot += 180.0f;
515 }
516
517 double xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
518 double zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
519 double yd = -Mth::sin(xRot / 180 * PI) * cameraDist;
520
521 for (int i = 0; i < 8; i++)
522 {
523 float xo = (float)((i & 1) * 2 - 1);
524 float yo = (float)(((i >> 1) & 1) * 2 - 1);
525 float zo = (float)(((i >> 2) & 1) * 2 - 1);
526
527 xo *= 0.1f;
528 yo *= 0.1f;
529 zo *= 0.1f;
530
531 // 4J - corrected bug here where zo was also added to x component
532 HitResult *hr = mc->level->clip(Vec3::newTemp(x + xo, y + yo, z + zo), Vec3::newTemp(x - xd + xo, y - yd + yo, z - zd + zo));
533 if (hr != NULL)
534 {
535 double dist = hr->pos->distanceTo(Vec3::newTemp(x, y, z));
536 if (dist < cameraDist) cameraDist = dist;
537 delete hr;
538 }
539 }
540
541 if ( localplayer->ThirdPersonView() == 2)
542 {
543 glRotatef(180, 0, 1, 0);
544 }
545
546 glRotatef(playerXRot - xRot, 1, 0, 0);
547 glRotatef(playerYRot - yRot, 0, 1, 0);
548 glTranslatef(0, 0, (float) -cameraDist);
549 glRotatef(yRot - playerYRot, 0, 1, 0);
550 glRotatef(xRot - playerXRot, 1, 0, 0);
551 }
552 }
553 else
554 {
555 glTranslatef(0, 0, -0.1f);
556 }
557
558 if (!mc->options->fixedCamera)
559 {
560 glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0);
561 glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0);
562 }
563
564 glTranslatef(0, heightOffset, 0);
565
566 x = player->xo + (player->x - player->xo) * a;
567 y = player->yo + (player->y - player->yo) * a - heightOffset;
568 z = player->zo + (player->z - player->zo) * a;
569
570 isInClouds = mc->levelRenderer->isInCloud(x, y, z, a);
571
572}
573
574
575void GameRenderer::zoomRegion(double zoom, double xa, double ya)
576{
577 zoom = zoom;
578 zoom_x = xa;
579 zoom_y = ya;
580}
581
582void GameRenderer::unZoomRegion()
583{
584 zoom = 1;
585}
586
587// 4J added as we have more complex adjustments to make for fov & aspect on account of viewports
588void GameRenderer::getFovAndAspect(float& fov, float& aspect, float a, bool applyEffects)
589{
590 // 4J - split out aspect ratio and fov here so we can adjust for viewports - we might need to revisit these as
591 // they are maybe be too generous for performance.
592 aspect = mc->width / (float) mc->height;
593 fov = getFov(a, applyEffects);
594
595 if( ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_TOP ) ||
596 ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM ) )
597 {
598 aspect *= 2.0f;
599 fov *= 0.7f; // Reduce FOV to make things less fish-eye, at the expense of reducing vertical FOV from single player mode
600 }
601 else if( ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT ) ||
602 ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT) )
603 {
604 // 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...
605 aspect *= 0.5f;
606 }
607}
608
609void GameRenderer::setupCamera(float a, int eye)
610{
611 renderDistance = (float)(16 * 16 >> (mc->options->viewDistance));
612 glMatrixMode(GL_PROJECTION);
613 glLoadIdentity();
614
615 float stereoScale = 0.07f;
616 if (mc->options->anaglyph3d) glTranslatef(-(eye * 2 - 1) * stereoScale, 0, 0);
617
618 // 4J - have split out fov & aspect calculation so we can take into account viewports
619 float aspect, fov;
620 getFovAndAspect(fov, aspect, a, true);
621
622 if (zoom != 1)
623 {
624 glTranslatef((float) zoom_x, (float) -zoom_y, 0);
625 glScaled(zoom, zoom, 1);
626 }
627 gluPerspective(fov, aspect, 0.05f, renderDistance * 2);
628
629 if (mc->gameMode->isCutScene())
630 {
631 float s = 1 / 1.5f;
632 glScalef(1, s, 1);
633 }
634
635 glMatrixMode(GL_MODELVIEW);
636 glLoadIdentity();
637 if (mc->options->anaglyph3d) glTranslatef((eye * 2 - 1) * 0.10f, 0, 0);
638
639 bobHurt(a);
640
641 // 4J-PB - this is a per-player option
642 //if (mc->options->bobView) bobView(a);
643
644 bool bNoLegAnim =(mc->player->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_NoLegAnim))!=0;
645 bool bNoBobbingAnim =(mc->player->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_NoBobbing))!=0;
646
647 if(app.GetGameSettings(mc->player->GetXboxPad(),eGameSetting_ViewBob) && !mc->player->abilities.flying && !bNoLegAnim && !bNoBobbingAnim) bobView(a);
648
649 float pt = mc->player->oPortalTime + (mc->player->portalTime - mc->player->oPortalTime) * a;
650 if (pt > 0)
651 {
652 int multiplier = 20;
653 if (mc->player->hasEffect(MobEffect::confusion))
654 {
655 multiplier = 7;
656 }
657
658 float skew = 5 / (pt * pt + 5) - pt * 0.04f;
659 skew *= skew;
660 glRotatef((_tick + a) * multiplier, 0, 1, 1);
661 glScalef(1 / skew, 1, 1);
662 glRotatef(-(_tick + a) * multiplier, 0, 1, 1);
663 }
664
665
666 moveCameraToPlayer(a);
667
668 if (cameraFlip > 0)
669 {
670 int i = cameraFlip - 1;
671 if (i == 1) glRotatef(90, 0, 1, 0);
672 if (i == 2) glRotatef(180, 0, 1, 0);
673 if (i == 3) glRotatef(-90, 0, 1, 0);
674 if (i == 4) glRotatef(90, 1, 0, 0);
675 if (i == 5) glRotatef(-90, 1, 0, 0);
676 }
677}
678
679void GameRenderer::renderItemInHand(float a, int eye)
680{
681 if (cameraFlip > 0) return;
682
683 // 4J-JEV: I'm fairly confident this method would crash if the cameratarget isnt a local player anyway, but oh well.
684 shared_ptr<LocalPlayer> localplayer = mc->cameraTargetPlayer->instanceof(eTYPE_LOCALPLAYER) ? dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer) : nullptr;
685
686 bool renderHand = true;
687
688 // 4J-PB - to turn off the hand for screenshots, but not when the item held is a map
689 if ( localplayer!=NULL)
690 {
691 shared_ptr<ItemInstance> item = localplayer->inventory->getSelected();
692 if(!(item && item->getItem()->id==Item::map_Id) && app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_DisplayHand)==0 ) renderHand = false;
693 }
694
695 glMatrixMode(GL_PROJECTION);
696 glLoadIdentity();
697
698 float stereoScale = 0.07f;
699 if (mc->options->anaglyph3d) glTranslatef(-(eye * 2 - 1) * stereoScale, 0, 0);
700
701 // 4J - have split out fov & aspect calculation so we can take into account viewports
702 float fov, aspect;
703 getFovAndAspect(fov, aspect, a, false);
704
705 if (zoom != 1)
706 {
707 glTranslatef((float) zoom_x, (float) -zoom_y, 0);
708 glScaled(zoom, zoom, 1);
709 }
710 gluPerspective(fov, aspect, 0.05f, renderDistance * 2);
711
712 if (mc->gameMode->isCutScene())
713 {
714 float s = 1 / 1.5f;
715 glScalef(1, s, 1);
716 }
717
718 glMatrixMode(GL_MODELVIEW);
719
720 glLoadIdentity();
721 if (mc->options->anaglyph3d) glTranslatef((eye * 2 - 1) * 0.10f, 0, 0);
722
723 glPushMatrix();
724 bobHurt(a);
725
726 // 4J-PB - changing this to be per player
727 //if (mc->options->bobView) bobView(a);
728 bool bNoLegAnim =(localplayer->getAnimOverrideBitmask()&( (1<<HumanoidModel::eAnim_NoLegAnim) | (1<<HumanoidModel::eAnim_NoBobbing) ))!=0;
729 if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a);
730
731 // 4J: Skip hand rendering if render hand is off
732 if (renderHand)
733 {
734 // 4J-PB - changing this to be per player
735 //if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping())
736 if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping())
737 {
738 if (!mc->options->hideGui && !mc->gameMode->isCutScene())
739 {
740 turnOnLightLayer(a);
741 PIXBeginNamedEvent(0,"Item in hand render");
742 itemInHandRenderer->render(a);
743 PIXEndNamedEvent();
744 turnOffLightLayer(a);
745 }
746 }
747 }
748 glPopMatrix();
749
750 // 4J-PB - changing this to be per player
751 //if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping())
752 if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping())
753 {
754 itemInHandRenderer->renderScreenEffect(a);
755 bobHurt(a);
756 }
757
758 // 4J-PB - changing this to be per player
759 //if (mc->options->bobView) bobView(a);
760 if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a);
761}
762
763// 4J - change brought forward from 1.8.2
764void GameRenderer::turnOffLightLayer(double alpha)
765{ // 4J - TODO
766#if 0
767 if (SharedConstants::TEXTURE_LIGHTING)
768 {
769 glClientActiveTexture(GL_TEXTURE1);
770 glActiveTexture(GL_TEXTURE1);
771 glDisable(GL_TEXTURE_2D);
772 glClientActiveTexture(GL_TEXTURE0);
773 glActiveTexture(GL_TEXTURE0);
774 }
775#endif
776 RenderManager.TextureBindVertex(-1);
777}
778
779// 4J - change brought forward from 1.8.2
780void GameRenderer::turnOnLightLayer(double alpha)
781{ // 4J - TODO
782#if 0
783 if (SharedConstants::TEXTURE_LIGHTING)
784 {
785 glClientActiveTexture(GL_TEXTURE1);
786 glActiveTexture(GL_TEXTURE1);
787 glMatrixMode(GL_TEXTURE);
788 glLoadIdentity();
789 // float s = 1 / 16f / 15.0f*16/14.0f;
790 float s = 1 / 16.0f / 15.0f * 15 / 16;
791 glScalef(s, s, s);
792 glTranslatef(8f, 8f, 8f);
793 glMatrixMode(GL_MODELVIEW);
794
795 mc->textures->bind(lightTexture);
796 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
797 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
798
799 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
800 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
801 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
802 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
803 glColor4f(1, 1, 1, 1);
804 glEnable(GL_TEXTURE_2D);
805 glClientActiveTexture(GL_TEXTURE0);
806 glActiveTexture(GL_TEXTURE0);
807 }
808#endif
809 RenderManager.TextureBindVertex(getLightTexture(mc->player->GetXboxPad(), mc->level));
810 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
811 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
812 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
813 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
814}
815
816// 4J - change brought forward from 1.8.2
817void GameRenderer::tickLightTexture()
818{
819 blrt += (float)((Math::random() - Math::random()) * Math::random() * Math::random());
820 blgt += (float)((Math::random() - Math::random()) * Math::random() * Math::random());
821 blrt *= 0.9;
822 blgt *= 0.9;
823 blr += (blrt - blr) * 1;
824 blg += (blgt - blg) * 1;
825 _updateLightTexture = true;
826}
827
828void GameRenderer::updateLightTexture(float a)
829{
830 // 4J-JEV: Now doing light textures on PER PLAYER basis.
831 // 4J - we *had* added separate light textures for all dimensions, and this loop to update them all here
832 for(int j = 0; j < XUSER_MAX_COUNT; j++ )
833 {
834 // Loop over all the players
835 shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j];
836 if (player == NULL) continue;
837
838 Level *level = player->level; // 4J - was mc->level when it was just to update the one light texture
839
840 float skyDarken1 = level->getSkyDarken((float) 1);
841 for (int i = 0; i < 256; i++)
842 {
843 float darken = skyDarken1 * 0.95f + 0.05f;
844 float sky = level->dimension->brightnessRamp[i / 16] * darken;
845 float block = level->dimension->brightnessRamp[i % 16] * (blr * 0.1f + 1.5f);
846
847 if (level->skyFlashTime > 0)
848 {
849 sky = level->dimension->brightnessRamp[i / 16];
850 }
851
852 float rs = sky * (skyDarken1 * 0.65f + 0.35f);
853 float gs = sky * (skyDarken1 * 0.65f + 0.35f);
854 float bs = sky;
855
856 float rb = block;
857 float gb = block * ((block * 0.6f + 0.4f) * 0.6f + 0.4f);
858 float bb = block * ((block * block) * 0.6f + 0.4f);
859
860 float _r = (rs + rb);
861 float _g = (gs + gb);
862 float _b = (bs + bb);
863
864 _r = _r * 0.96f + 0.03f;
865 _g = _g * 0.96f + 0.03f;
866 _b = _b * 0.96f + 0.03f;
867
868 if (darkenWorldAmount > 0)
869 {
870 float amount = darkenWorldAmountO + (darkenWorldAmount - darkenWorldAmountO) * a;
871 _r = _r * (1.0f - amount) + (_r * .7f) * amount;
872 _g = _g * (1.0f - amount) + (_g * .6f) * amount;
873 _b = _b * (1.0f - amount) + (_b * .6f) * amount;
874 }
875
876 if (level->dimension->id == 1)
877 {
878 _r = (0.22f + rb * 0.75f);
879 _g = (0.28f + gb * 0.75f);
880 _b = (0.25f + bb * 0.75f);
881 }
882
883 if (player->hasEffect(MobEffect::nightVision))
884 {
885 float scale = getNightVisionScale(player, a);
886 {
887 float dist = 1.0f / _r;
888 if (dist > (1.0f / _g))
889 {
890 dist = (1.0f / _g);
891 }
892 if (dist > (1.0f / _b))
893 {
894 dist = (1.0f / _b);
895 }
896 _r = _r * (1.0f - scale) + (_r * dist) * scale;
897 _g = _g * (1.0f - scale) + (_g * dist) * scale;
898 _b = _b * (1.0f - scale) + (_b * dist) * scale;
899 }
900 }
901
902 if (_r > 1) _r = 1;
903 if (_g > 1) _g = 1;
904 if (_b > 1) _b = 1;
905
906 float brightness = mc->options->gamma;
907
908 float ir = 1 - _r;
909 float ig = 1 - _g;
910 float ib = 1 - _b;
911 ir = 1 - (ir * ir * ir * ir);
912 ig = 1 - (ig * ig * ig * ig);
913 ib = 1 - (ib * ib * ib * ib);
914 _r = _r * (1 - brightness) + ir * brightness;
915 _g = _g * (1 - brightness) + ig * brightness;
916 _b = _b * (1 - brightness) + ib * brightness;
917
918 _r = _r * 0.96f + 0.03f;
919 _g = _g * 0.96f + 0.03f;
920 _b = _b * 0.96f + 0.03f;
921
922 if (_r > 1) _r = 1;
923 if (_g > 1) _g = 1;
924 if (_b > 1) _b = 1;
925 if (_r < 0) _r = 0;
926 if (_g < 0) _g = 0;
927 if (_b < 0) _b = 0;
928
929 int alpha = 255;
930 int r = (int) (_r * 255);
931 int g = (int) (_g * 255);
932 int b = (int) (_b * 255);
933
934#if ( defined _DURANGO || defined _WIN64 || __PSVITA__ )
935 lightPixels[j][i] = alpha << 24 | b << 16 | g << 8 | r;
936#elif ( defined _XBOX || defined __ORBIS__ )
937 lightPixels[j][i] = alpha << 24 | r << 16 | g << 8 | b;
938#else
939 lightPixels[j][i] = r << 24 | g << 16 | b << 8 | alpha;
940#endif
941 }
942
943 mc->textures->replaceTextureDirect( lightPixels[j], 16, 16, getLightTexture(j,level) );
944 // lightTexture->upload(); // 4J: not relevant
945
946 //_updateLightTexture = false;
947 }
948}
949
950float GameRenderer::getNightVisionScale(shared_ptr<Player> player, float a)
951{
952 int duration = player->getEffect(MobEffect::nightVision)->getDuration();
953 if (duration > (SharedConstants::TICKS_PER_SECOND * 10))
954 {
955 return 1.0f;
956 }
957 else
958 {
959 float flash = max(0.0f, (float)duration - a);
960 return .7f + Mth::sin(flash * PI * .05f) * .3f; // was: .7 + sin(flash*pi*0.2) * .3
961 }
962}
963
964// 4J added, so we can have a light texture for each player to support split screen
965int GameRenderer::getLightTexture(int iPad, Level *level)
966{
967 // Turn the current dimenions id into an index from 0 to 2
968 // int idx = level->dimension->id;
969 // if( idx == -1 ) idx = 2;
970
971 return lightTexture[iPad]; // 4J-JEV: Changing to Per Player lighting textures.
972}
973
974void GameRenderer::render(float a, bool bFirst)
975{
976 if( _updateLightTexture && bFirst) updateLightTexture(a);
977 if (Display::isActive())
978 {
979 lastActiveTime = System::currentTimeMillis();
980 }
981 else
982 {
983 if (System::currentTimeMillis() - lastActiveTime > 500)
984 {
985 mc->pauseGame();
986 }
987 }
988
989#if 0 // 4J - TODO
990 if (mc->mouseGrabbed && focused) {
991 mc->mouseHandler.poll();
992
993 float ss = mc->options->sensitivity * 0.6f + 0.2f;
994 float sens = (ss * ss * ss) * 8;
995 float xo = mc->mouseHandler.xd * sens;
996 float yo = mc->mouseHandler.yd * sens;
997
998 int yAxis = 1;
999 if (mc->options->invertYMouse) yAxis = -1;
1000
1001 if (mc->options->smoothCamera) {
1002
1003 xo = smoothTurnX.getNewDeltaValue(xo, .05f * sens);
1004 yo = smoothTurnY.getNewDeltaValue(yo, .05f * sens);
1005
1006 }
1007
1008 mc->player.turn(xo, yo * yAxis);
1009 }
1010#endif
1011
1012 if (mc->noRender) return;
1013 GameRenderer::anaglyph3d = mc->options->anaglyph3d;
1014
1015 glViewport(0, 0, mc->width, mc->height); // 4J - added
1016 ScreenSizeCalculator ssc(mc->options, mc->width, mc->height);
1017 int screenWidth = ssc.getWidth();
1018 int screenHeight = ssc.getHeight();
1019 int xMouse = Mouse::getX() * screenWidth / mc->width;
1020 int yMouse = screenHeight - Mouse::getY() * screenHeight / mc->height - 1;
1021
1022 int maxFps = getFpsCap(mc->options->framerateLimit);
1023
1024 if (mc->level != NULL)
1025 {
1026 if (mc->options->framerateLimit == 0)
1027 {
1028 renderLevel(a, 0);
1029 }
1030 else
1031 {
1032 renderLevel(a, lastNsTime + 1000000000 / maxFps);
1033 }
1034
1035 lastNsTime = System::nanoTime();
1036
1037
1038 if (!mc->options->hideGui || mc->screen != NULL)
1039 {
1040 mc->gui->render(a, mc->screen != NULL, xMouse, yMouse);
1041 }
1042 }
1043 else
1044 {
1045 glViewport(0, 0, mc->width, mc->height);
1046 glMatrixMode(GL_PROJECTION);
1047 glLoadIdentity();
1048 glMatrixMode(GL_MODELVIEW);
1049 glLoadIdentity();
1050 setupGuiScreen();
1051
1052 lastNsTime = System::nanoTime();
1053 }
1054
1055
1056 if (mc->screen != NULL)
1057 {
1058 glClear(GL_DEPTH_BUFFER_BIT);
1059 mc->screen->render(xMouse, yMouse, a);
1060 if (mc->screen != NULL && mc->screen->particles != NULL) mc->screen->particles->render(a);
1061 }
1062
1063}
1064
1065void GameRenderer::renderLevel(float a)
1066{
1067 renderLevel(a, 0);
1068}
1069
1070#ifdef MULTITHREAD_ENABLE
1071// Request that an item be deleted, when it is safe to do so
1072void GameRenderer::AddForDelete(byte *deleteThis)
1073{
1074 EnterCriticalSection(&m_csDeleteStack);
1075 m_deleteStackByte.push_back(deleteThis);
1076}
1077
1078void GameRenderer::AddForDelete(SparseLightStorage *deleteThis)
1079{
1080 EnterCriticalSection(&m_csDeleteStack);
1081 m_deleteStackSparseLightStorage.push_back(deleteThis);
1082}
1083
1084void GameRenderer::AddForDelete(CompressedTileStorage *deleteThis)
1085{
1086 EnterCriticalSection(&m_csDeleteStack);
1087 m_deleteStackCompressedTileStorage.push_back(deleteThis);
1088}
1089
1090void GameRenderer::AddForDelete(SparseDataStorage *deleteThis)
1091{
1092 EnterCriticalSection(&m_csDeleteStack);
1093 m_deleteStackSparseDataStorage.push_back(deleteThis);
1094}
1095
1096void GameRenderer::FinishedReassigning()
1097{
1098 LeaveCriticalSection(&m_csDeleteStack);
1099}
1100
1101int GameRenderer::runUpdate(LPVOID lpParam)
1102{
1103 Minecraft *minecraft = Minecraft::GetInstance();
1104 Vec3::CreateNewThreadStorage();
1105 AABB::CreateNewThreadStorage();
1106 IntCache::CreateNewThreadStorage();
1107 Tesselator::CreateNewThreadStorage(1024*1024);
1108 Compression::UseDefaultThreadStorage();
1109 RenderManager.InitialiseContext();
1110#ifdef _LARGE_WORLDS
1111 Chunk::CreateNewThreadStorage();
1112#endif
1113 Tile::CreateNewThreadStorage();
1114
1115 ShutdownManager::HasStarted(ShutdownManager::eRenderChunkUpdateThread,m_updateEvents);
1116 while(ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread))
1117 {
1118 //m_updateEvents->Clear(eUpdateEventIsFinished);
1119 //m_updateEvents->WaitForSingle(eUpdateCanRun,INFINITE);
1120 // 4J Stu - We Need to have this happen atomically to avoid deadlocks
1121 m_updateEvents->WaitForAll(INFINITE);
1122
1123 if( !ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread) )
1124 {
1125 break;
1126 }
1127
1128 m_updateEvents->Set(eUpdateCanRun);
1129
1130 // PIXBeginNamedEvent(0,"Updating dirty chunks %d",(count++)&7);
1131
1132 // Update chunks atomically until there aren't any very near ones left - they will be deferred for rendering
1133 // until the call to CBuffDeferredModeEnd if we have anything near to render here
1134 // Now limiting maximum number of updates that can be deferred as have noticed that with redstone clock circuits, it is possible to create
1135 // 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...
1136 int count = 0;
1137 static const int MAX_DEFERRED_UPDATES = 10;
1138 bool shouldContinue = false;
1139 do
1140 {
1141 shouldContinue = minecraft->levelRenderer->updateDirtyChunks();
1142 count++;
1143 } while ( shouldContinue && count < MAX_DEFERRED_UPDATES );
1144
1145 // while( minecraft->levelRenderer->updateDirtyChunks() )
1146 // ;
1147 RenderManager.CBuffDeferredModeEnd();
1148
1149 // If any renderable tile entities were flagged in this last block of chunk(s) that were udpated, then change their
1150 // flags to say that this deferred chunk is over and they are actually safe to be removed now
1151 minecraft->levelRenderer->fullyFlagRenderableTileEntitiesToBeRemoved();
1152
1153 // We've got stacks for things that can only safely be deleted whilst this thread isn't updating things - delete those things now
1154 EnterCriticalSection(&m_csDeleteStack);
1155 for(unsigned int i = 0; i < m_deleteStackByte.size(); i++ )
1156 {
1157 delete m_deleteStackByte[i];
1158 }
1159 m_deleteStackByte.clear();
1160 for(unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); i++ )
1161 {
1162 delete m_deleteStackSparseLightStorage[i];
1163 }
1164 m_deleteStackSparseLightStorage.clear();
1165 for(unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size(); i++ )
1166 {
1167 delete m_deleteStackCompressedTileStorage[i];
1168 }
1169 m_deleteStackCompressedTileStorage.clear();
1170 for(unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++ )
1171 {
1172 delete m_deleteStackSparseDataStorage[i];
1173 }
1174 m_deleteStackSparseDataStorage.clear();
1175 LeaveCriticalSection(&m_csDeleteStack);
1176
1177 // PIXEndNamedEvent();
1178
1179 AABB::resetPool();
1180 Vec3::resetPool();
1181 IntCache::Reset();
1182 m_updateEvents->Set(eUpdateEventIsFinished);
1183 }
1184
1185 ShutdownManager::HasFinished(ShutdownManager::eRenderChunkUpdateThread);
1186 return 0;
1187}
1188#endif
1189
1190void GameRenderer::EnableUpdateThread()
1191{
1192 // #ifdef __PS3__ // MGH - disable the update on PS3 for now
1193 // return;
1194 // #endif
1195#ifdef MULTITHREAD_ENABLE
1196 if( updateRunning) return;
1197 app.DebugPrintf("------------------EnableUpdateThread--------------------\n");
1198 updateRunning = true;
1199 m_updateEvents->Set(eUpdateCanRun);
1200 m_updateEvents->Set(eUpdateEventIsFinished);
1201#endif
1202}
1203
1204void GameRenderer::DisableUpdateThread()
1205{
1206 // #ifdef __PS3__ // MGH - disable the update on PS3 for now
1207 // return;
1208 // #endif
1209#ifdef MULTITHREAD_ENABLE
1210 if( !updateRunning) return;
1211 app.DebugPrintf("------------------DisableUpdateThread--------------------\n");
1212 updateRunning = false;
1213 m_updateEvents->Clear(eUpdateCanRun);
1214 m_updateEvents->WaitForSingle(eUpdateEventIsFinished,INFINITE);
1215#endif
1216}
1217
1218void GameRenderer::renderLevel(float a, __int64 until)
1219{
1220 // 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
1221
1222 glEnable(GL_CULL_FACE);
1223 glEnable(GL_DEPTH_TEST);
1224
1225 // 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
1226 // 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.
1227 bool updateChunks = ( mc->player == mc->localplayers[ProfileManager.GetPrimaryPad()] );
1228
1229 // if (mc->cameraTargetPlayer == NULL) // 4J - removed condition as we want to update this is mc->player changes for different local players
1230 {
1231 mc->cameraTargetPlayer = mc->player;
1232 }
1233 pick(a);
1234
1235 shared_ptr<LivingEntity> cameraEntity = mc->cameraTargetPlayer;
1236 LevelRenderer *levelRenderer = mc->levelRenderer;
1237 ParticleEngine *particleEngine = mc->particleEngine;
1238 double xOff = cameraEntity->xOld + (cameraEntity->x - cameraEntity->xOld) * a;
1239 double yOff = cameraEntity->yOld + (cameraEntity->y - cameraEntity->yOld) * a;
1240 double zOff = cameraEntity->zOld + (cameraEntity->z - cameraEntity->zOld) * a;
1241
1242 for (int i = 0; i < 2; i++)
1243 {
1244 if (mc->options->anaglyph3d)
1245 {
1246 GameRenderer::anaglyphPass = i;
1247 if (GameRenderer::anaglyphPass == 0) glColorMask(false, true, true, false);
1248 else glColorMask(true, false, false, false);
1249 }
1250
1251
1252 glViewport(0, 0, mc->width, mc->height);
1253 setupClearColor(a);
1254 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1255 glEnable(GL_CULL_FACE);
1256
1257 setupCamera(a, i);
1258 Camera::prepare(mc->player, mc->player->ThirdPersonView() == 2);
1259
1260 Frustum::getFrustum();
1261 if (mc->options->viewDistance < 2)
1262 {
1263 setupFog(-1, a);
1264 levelRenderer->renderSky(a);
1265 if(mc->skins->getSelected()->getId() == 1026 ) levelRenderer->renderHaloRing(a);
1266 }
1267 glEnable(GL_FOG);
1268 setupFog(1, a);
1269
1270 if (mc->options->ambientOcclusion)
1271 {
1272 GL11::glShadeModel(GL11::GL_SMOOTH);
1273 }
1274
1275 PIXBeginNamedEvent(0,"Culling");
1276 MemSect(31);
1277 // Culler *frustum = new FrustumCuller();
1278 FrustumCuller frustObj;
1279 Culler *frustum = &frustObj;
1280 MemSect(0);
1281 frustum->prepare(xOff, yOff, zOff);
1282
1283 mc->levelRenderer->cull(frustum, a);
1284 PIXEndNamedEvent();
1285
1286#ifndef MULTITHREAD_ENABLE
1287 if ( (i == 0) && updateChunks ) // 4J - added updateChunks condition
1288 {
1289 int PIXPass = 0;
1290 PIXBeginNamedEvent(0,"Updating dirty chunks");
1291 do
1292 {
1293 PIXBeginNamedEvent(0,"Updating dirty chunks pass %d",PIXPass++);
1294 bool retval = mc->levelRenderer->updateDirtyChunks(cameraEntity, false);
1295 PIXEndNamedEvent();
1296 if( retval ) break;
1297
1298
1299 if (until == 0) break;
1300
1301 __int64 diff = until - System::nanoTime();
1302 if (diff < 0) break;
1303 if (diff > 1000000000) break;
1304 } while (true);
1305 PIXEndNamedEvent();
1306 }
1307#endif
1308
1309
1310 if (cameraEntity->y < Level::genDepth)
1311 {
1312 prepareAndRenderClouds(levelRenderer, a);
1313 }
1314 Frustum::getFrustum(); // 4J added - re-calculate frustum as rendering the clouds does a scale & recalculates one that isn't any good for the rest of the level rendering
1315
1316 setupFog(0, a);
1317 glEnable(GL_FOG);
1318 MemSect(31);
1319 mc->textures->bindTexture(&TextureAtlas::LOCATION_BLOCKS); // 4J was L"/terrain.png"
1320 MemSect(0);
1321 Lighting::turnOff();
1322 PIXBeginNamedEvent(0,"Level render");
1323 levelRenderer->render(cameraEntity, 0, a, updateChunks);
1324 PIXEndNamedEvent();
1325
1326 GL11::glShadeModel(GL11::GL_FLAT);
1327
1328 if (cameraFlip == 0 )
1329 {
1330 Lighting::turnOn();
1331 PIXBeginNamedEvent(0,"Entity render");
1332 // 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
1333 // This fixes flickering minecarts, and pigs that you are riding on
1334 frustum->prepare(cameraEntity->x,cameraEntity->y,cameraEntity->z);
1335 // 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
1336 // our index into the temp Vec3 cache and overwrite the one that was storing the camera position
1337 // Fix for #77745 - TU9: Content: Gameplay: Items and mobs not belonging to end world are disappearing when Enderdragon is damaged.
1338 Vec3 *cameraPosTemp = cameraEntity->getPos(a);
1339 cameraPos->x = cameraPosTemp->x;
1340 cameraPos->y = cameraPosTemp->y;
1341 cameraPos->z = cameraPosTemp->z;
1342 levelRenderer->renderEntities(cameraPos, frustum, a);
1343#ifdef __PSVITA__
1344 // AP - make sure we're using the Alpha cut out effect for particles
1345 glEnable(GL_ALPHA_TEST);
1346#endif
1347 PIXEndNamedEvent();
1348 PIXBeginNamedEvent(0,"Particle render");
1349 turnOnLightLayer(a); // 4J - brought forward from 1.8.2
1350 particleEngine->renderLit(cameraEntity, a, ParticleEngine::OPAQUE_LIST);
1351 Lighting::turnOff();
1352 setupFog(0, a);
1353 particleEngine->render(cameraEntity, a, ParticleEngine::OPAQUE_LIST);
1354 PIXEndNamedEvent();
1355 turnOffLightLayer(a); // 4J - brought forward from 1.8.2
1356
1357 if ( (mc->hitResult != NULL) && cameraEntity->isUnderLiquid(Material::water) && cameraEntity->instanceof(eTYPE_PLAYER) ) //&& !mc->options.hideGui)
1358 {
1359 shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity);
1360 glDisable(GL_ALPHA_TEST);
1361 levelRenderer->renderHit(player, mc->hitResult, 0, player->inventory->getSelected(), a);
1362 glEnable(GL_ALPHA_TEST);
1363 }
1364 }
1365
1366 glDisable(GL_BLEND);
1367 glEnable(GL_CULL_FACE);
1368 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1369 glDepthMask(true);
1370 setupFog(0, a);
1371 glEnable(GL_BLEND);
1372 glDisable(GL_CULL_FACE);
1373 MemSect(31);
1374 mc->textures->bindTexture(&TextureAtlas::LOCATION_BLOCKS); // 4J was L"/terrain.png"
1375 MemSect(0);
1376 // 4J - have changed this fancy rendering option to work with our command buffers. The original used to use frame buffer flags to disable
1377 // writing to colour when doing the z-only pass, but that value gets obliterated by our command buffers. Using alpha blend function instead
1378 // to achieve the same effect.
1379 if (true) // (mc->options->fancyGraphics)
1380 {
1381 if (mc->options->ambientOcclusion)
1382 {
1383 GL11::glShadeModel(GL11::GL_SMOOTH);
1384 }
1385
1386 glBlendFunc(GL_ZERO, GL_ONE);
1387 PIXBeginNamedEvent(0,"Fancy second pass - writing z");
1388 int visibleWaterChunks = levelRenderer->render(cameraEntity, 1, a, updateChunks);
1389 PIXEndNamedEvent();
1390 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1391
1392 if (visibleWaterChunks > 0)
1393 {
1394 PIXBeginNamedEvent(0,"Fancy second pass - actual rendering");
1395 levelRenderer->render(cameraEntity, 1, a, updateChunks); // 4J - chanaged, used to be renderSameAsLast but we don't support that anymore
1396 PIXEndNamedEvent();
1397 }
1398
1399 GL11::glShadeModel(GL11::GL_FLAT);
1400 }
1401 else
1402 {
1403 PIXBeginNamedEvent(0,"Second pass level render");
1404 levelRenderer->render(cameraEntity, 1, a, updateChunks);
1405 PIXEndNamedEvent();
1406 }
1407
1408 // 4J - added - have split out translucent particle rendering so that it happens after the water is rendered, primarily for fireworks
1409 PIXBeginNamedEvent(0,"Particle render (translucent)");
1410 Lighting::turnOn();
1411 turnOnLightLayer(a); // 4J - brought forward from 1.8.2
1412 particleEngine->renderLit(cameraEntity, a, ParticleEngine::TRANSLUCENT_LIST);
1413 Lighting::turnOff();
1414 setupFog(0, a);
1415 particleEngine->render(cameraEntity, a, ParticleEngine::TRANSLUCENT_LIST);
1416 PIXEndNamedEvent();
1417 turnOffLightLayer(a); // 4J - brought forward from 1.8.2
1418 ////////////////////////// End of 4J added section
1419
1420 glDepthMask(true);
1421 glEnable(GL_CULL_FACE);
1422 glDisable(GL_BLEND);
1423
1424 if ( (zoom == 1) && cameraEntity->instanceof(eTYPE_PLAYER) ) //&& !mc->options.hideGui)
1425 {
1426 if (mc->hitResult != NULL && !cameraEntity->isUnderLiquid(Material::water))
1427 {
1428 shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity);
1429 glDisable(GL_ALPHA_TEST);
1430 levelRenderer->renderHitOutline(player, mc->hitResult, 0, a);
1431 glEnable(GL_ALPHA_TEST);
1432 }
1433 }
1434
1435 /* 4J - moved rain rendering to after clouds so that it alpha blends onto them properly
1436 PIXBeginNamedEvent(0,"Rendering snow and rain");
1437 renderSnowAndRain(a);
1438 PIXEndNamedEvent();
1439 glDisable(GL_FOG);
1440 */
1441
1442 glEnable(GL_BLEND);
1443 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1444 levelRenderer->renderDestroyAnimation(Tesselator::getInstance(), dynamic_pointer_cast<Player>(cameraEntity), a);
1445 glDisable(GL_BLEND);
1446
1447 if (cameraEntity->y >= Level::genDepth)
1448 {
1449 prepareAndRenderClouds(levelRenderer, a);
1450 }
1451
1452 // 4J - rain rendering moved here so that it renders after clouds & can blend properly onto them
1453 setupFog(0, a);
1454 glEnable(GL_FOG);
1455 PIXBeginNamedEvent(0,"Rendering snow and rain");
1456 renderSnowAndRain(a);
1457 PIXEndNamedEvent();
1458 glDisable(GL_FOG);
1459
1460
1461 if (zoom == 1)
1462 {
1463 glClear(GL_DEPTH_BUFFER_BIT);
1464 renderItemInHand(a, i);
1465 }
1466
1467
1468 if (!mc->options->anaglyph3d)
1469 {
1470 return;
1471 }
1472 }
1473 glColorMask(true, true, true, false);
1474}
1475
1476void GameRenderer::prepareAndRenderClouds(LevelRenderer *levelRenderer, float a)
1477{
1478 if (mc->options->isCloudsOn())
1479 {
1480 glPushMatrix();
1481 setupFog(0, a);
1482 glEnable(GL_FOG);
1483 PIXBeginNamedEvent(0,"Rendering clouds");
1484 levelRenderer->renderClouds(a);
1485 PIXEndNamedEvent();
1486 glDisable(GL_FOG);
1487 setupFog(1, a);
1488 glPopMatrix();
1489 }
1490}
1491
1492void GameRenderer::tickRain()
1493{
1494 float rainLevel = mc->level->getRainLevel(1);
1495
1496 if (!mc->options->fancyGraphics) rainLevel /= 2;
1497 if (rainLevel == 0) return;
1498
1499 rainLevel /= ( mc->levelRenderer->activePlayers() + 1 );
1500
1501 random->setSeed(_tick * 312987231l);
1502 shared_ptr<LivingEntity> player = mc->cameraTargetPlayer;
1503 Level *level = mc->level;
1504
1505 int x0 = Mth::floor(player->x);
1506 int y0 = Mth::floor(player->y);
1507 int z0 = Mth::floor(player->z);
1508
1509 int r = 10;
1510
1511 double rainPosX = 0;
1512 double rainPosY = 0;
1513 double rainPosZ = 0;
1514 int rainPosSamples = 0;
1515
1516 int rainCount = (int) (100 * rainLevel * rainLevel);
1517 if (mc->options->particles == 1)
1518 {
1519 rainCount >>= 1;
1520 } else if (mc->options->particles == 2)
1521 {
1522 rainCount = 0;
1523 }
1524 for (int i = 0; i < rainCount; i++)
1525 {
1526 int x = x0 + random->nextInt(r) - random->nextInt(r);
1527 int z = z0 + random->nextInt(r) - random->nextInt(r);
1528 int y = level->getTopRainBlock(x, z);
1529 int t = level->getTile(x, y - 1, z);
1530 Biome *biome = level->getBiome(x,z);
1531 if (y <= y0 + r && y >= y0 - r && biome->hasRain() && biome->getTemperature() >= 0.2f)
1532 {
1533 float xa = random->nextFloat();
1534 float za = random->nextFloat();
1535 if (t > 0)
1536 {
1537 if (Tile::tiles[t]->material == Material::lava)
1538 {
1539 mc->particleEngine->add( shared_ptr<SmokeParticle>( new SmokeParticle(level, x + xa, y + 0.1f - Tile::tiles[t]->getShapeY0(), z + za, 0, 0, 0) ) );
1540 }
1541 else
1542 {
1543 if (random->nextInt(++rainPosSamples) == 0)
1544 {
1545 rainPosX = x + xa;
1546 rainPosY = y + 0.1f - Tile::tiles[t]->getShapeY0();
1547 rainPosZ = z + za;
1548 }
1549 mc->particleEngine->add( shared_ptr<WaterDropParticle>( new WaterDropParticle(level, x + xa, y + 0.1f - Tile::tiles[t]->getShapeY0(), z + za) ) );
1550 }
1551 }
1552 }
1553 }
1554
1555
1556 if (rainPosSamples > 0 && random->nextInt(3) < rainSoundTime++)
1557 {
1558 rainSoundTime = 0;
1559 MemSect(24);
1560 if (rainPosY > player->y + 1 && level->getTopRainBlock(Mth::floor(player->x), Mth::floor(player->z)) > Mth::floor(player->y))
1561 {
1562 mc->level->playLocalSound(rainPosX, rainPosY, rainPosZ, eSoundType_AMBIENT_WEATHER_RAIN, 0.1f, 0.5f);
1563 }
1564 else
1565 {
1566 mc->level->playLocalSound(rainPosX, rainPosY, rainPosZ, eSoundType_AMBIENT_WEATHER_RAIN, 0.2f, 1.0f);
1567 }
1568 MemSect(0);
1569 }
1570
1571}
1572
1573// 4J - this whole function updated from 1.8.2
1574void GameRenderer::renderSnowAndRain(float a)
1575{
1576 float rainLevel = mc->level->getRainLevel(a);
1577 if (rainLevel <= 0) return;
1578
1579 // 4J - rain is relatively low poly, but high fill-rate - better to clip it
1580 RenderManager.StateSetEnableViewportClipPlanes(true);
1581
1582 turnOnLightLayer(a);
1583
1584 if (rainXa == NULL)
1585 {
1586 rainXa = new float[32 * 32];
1587 rainZa = new float[32 * 32];
1588
1589 for (int z = 0; z < 32; z++)
1590 {
1591 for (int x = 0; x < 32; x++)
1592 {
1593 float xa = x - 16;
1594 float za = z - 16;
1595 float d = Mth::sqrt(xa * xa + za * za);
1596 rainXa[z << 5 | x] = -za / d;
1597 rainZa[z << 5 | x] = xa / d;
1598 }
1599 }
1600 }
1601
1602 shared_ptr<LivingEntity> player = mc->cameraTargetPlayer;
1603 Level *level = mc->level;
1604
1605 int x0 = Mth::floor(player->x);
1606 int y0 = Mth::floor(player->y);
1607 int z0 = Mth::floor(player->z);
1608
1609 Tesselator *t = Tesselator::getInstance();
1610 glDisable(GL_CULL_FACE);
1611 glNormal3f(0, 1, 0);
1612 glEnable(GL_BLEND);
1613 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1614 glAlphaFunc(GL_GREATER, 0.01f);
1615
1616 MemSect(31);
1617 mc->textures->bindTexture(&SNOW_LOCATION); // 4J was L"/environment/snow.png"
1618 MemSect(0);
1619
1620 double xo = player->xOld + (player->x - player->xOld) * a;
1621 double yo = player->yOld + (player->y - player->yOld) * a;
1622 double zo = player->zOld + (player->z - player->zOld) * a;
1623
1624 int yMin = Mth::floor(yo);
1625
1626
1627 int r = 5;
1628 // 4J - was if(mc.options.fancyGraphics) r = 10;
1629 switch( mc->levelRenderer->activePlayers() )
1630 {
1631 case 1:
1632 default:
1633 r = 9;
1634 break;
1635 case 2:
1636 r = 7;
1637 break;
1638 case 3:
1639 r = 5;
1640 break;
1641 case 4:
1642 r = 5;
1643 break;
1644 }
1645
1646 // 4J - some changes made here to access biome through new interface that caches results in levelchunk flags, as an optimisation
1647
1648 int mode = -1;
1649 float time = _tick + a;
1650
1651 glColor4f(1, 1, 1, 1);
1652
1653 for (int x = x0 - r; x <= x0 + r; x++)
1654 for (int z = z0 - r; z <= z0 + r; z++)
1655 {
1656 int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16);
1657 float xa = rainXa[rainSlot] * 0.5f;
1658 float za = rainZa[rainSlot] * 0.5f;
1659
1660 // 4J - changes here brought forward from 1.8.2
1661 Biome *b = level->getBiome(x, z);
1662 if (!b->hasRain() && !b->hasSnow()) continue;
1663
1664 int floor = level->getTopRainBlock(x, z);
1665
1666 int yy0 = y0 - r;
1667 int yy1 = y0 + r;
1668
1669 if (yy0 < floor) yy0 = floor;
1670 if (yy1 < floor) yy1 = floor;
1671 float s = 1;
1672
1673 int yl = floor;
1674 if (yl < yMin) yl = yMin;
1675
1676 if (yy0 != yy1)
1677 {
1678 random->setSeed((x * x * 3121 + x * 45238971) ^ (z * z * 418711 + z * 13761));
1679
1680 // 4J - changes here brought forward from 1.8.2
1681 float temp = b->getTemperature();
1682 if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f)
1683 {
1684 if (mode != 0)
1685 {
1686 if (mode >= 0) t->end();
1687 mode = 0;
1688 mc->textures->bindTexture(&RAIN_LOCATION);
1689 t->begin();
1690 }
1691
1692 float ra = (((_tick + x * x * 3121 + x * 45238971 + z * z * 418711 + z * 13761) & 31) + a) / 32.0f * (3 + random->nextFloat());
1693
1694 double xd = (x + 0.5f) - player->x;
1695 double zd = (z + 0.5f) - player->z;
1696 float dd = (float) Mth::sqrt(xd * xd + zd * zd) / r;
1697
1698 float br = 1;
1699 t->offset(-xo * 1, -yo * 1, -zo * 1);
1700#ifdef __PSVITA__
1701 // AP - this will set up the 4 vertices in half the time
1702 float Alpha = ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel;
1703 int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
1704 t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s,
1705 x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s,
1706 x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s,
1707 x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s,
1708 br, br, br, Alpha, br, br, br, 0, tex2);
1709#else
1710 t->tex2(level->getLightColor(x, yl, z, 0));
1711 t->color(br, br, br, ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel);
1712 t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s);
1713 t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s);
1714 t->color(br, br, br, 0.0f); // 4J - added to soften the top visible edge of the rain
1715 t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s);
1716 t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s);
1717#endif
1718 t->offset(0, 0, 0);
1719 t->end();
1720 }
1721 else
1722 {
1723 if (mode != 1)
1724 {
1725 if (mode >= 0) t->end();
1726 mode = 1;
1727 mc->textures->bindTexture(&SNOW_LOCATION);
1728 t->begin();
1729 }
1730 float ra = (((_tick) & 511) + a) / 512.0f;
1731 float uo = random->nextFloat() + time * 0.01f * (float) random->nextGaussian();
1732 float vo = random->nextFloat() + time * (float) random->nextGaussian() * 0.001f;
1733 double xd = (x + 0.5f) - player->x;
1734 double zd = (z + 0.5f) - player->z;
1735 float dd = (float) sqrt(xd * xd + zd * zd) / r;
1736 float br = 1;
1737 t->offset(-xo * 1, -yo * 1, -zo * 1);
1738#ifdef __PSVITA__
1739 // AP - this will set up the 4 vertices in half the time
1740 float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel;
1741 int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
1742 t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo,
1743 x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo,
1744 x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo,
1745 x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo,
1746 br, br, br, Alpha, br, br, br, Alpha, tex2);
1747#else
1748 t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4);
1749 t->color(br, br, br, ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel);
1750 t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo);
1751 t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo);
1752 t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo);
1753 t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo);
1754#endif
1755 t->offset(0, 0, 0);
1756 }
1757 }
1758 }
1759
1760 if( mode >= 0 ) t->end();
1761 glEnable(GL_CULL_FACE);
1762 glDisable(GL_BLEND);
1763 glAlphaFunc(GL_GREATER, 0.1f);
1764 turnOffLightLayer(a);
1765
1766 RenderManager.StateSetEnableViewportClipPlanes(false);
1767}
1768
1769// 4J - added forceScale parameter
1770void GameRenderer::setupGuiScreen(int forceScale /*=-1*/)
1771{
1772 ScreenSizeCalculator ssc(mc->options, mc->width, mc->height, forceScale);
1773
1774 glClear(GL_DEPTH_BUFFER_BIT);
1775 glMatrixMode(GL_PROJECTION);
1776 glLoadIdentity();
1777 glOrtho(0, (float)ssc.rawWidth, (float)ssc.rawHeight, 0, 1000, 3000);
1778 glMatrixMode(GL_MODELVIEW);
1779 glLoadIdentity();
1780 glTranslatef(0, 0, -2000);
1781}
1782
1783void GameRenderer::setupClearColor(float a)
1784{
1785 Level *level = mc->level;
1786 shared_ptr<LivingEntity> player = mc->cameraTargetPlayer;
1787
1788 float whiteness = 1.0f / (4 - mc->options->viewDistance);
1789 whiteness = 1 - (float) pow((double)whiteness, 0.25);
1790
1791 Vec3 *skyColor = level->getSkyColor(mc->cameraTargetPlayer, a);
1792 float sr = (float) skyColor->x;
1793 float sg = (float) skyColor->y;
1794 float sb = (float) skyColor->z;
1795
1796 Vec3 *fogColor = level->getFogColor(a);
1797 fr = (float) fogColor->x;
1798 fg = (float) fogColor->y;
1799 fb = (float) fogColor->z;
1800
1801 if (mc->options->viewDistance < 2)
1802 {
1803 Vec3 *sunAngle = Mth::sin(level->getSunAngle(a)) > 0 ? Vec3::newTemp(-1, 0, 0) : Vec3::newTemp(1, 0, 0);
1804 float d = (float) player->getViewVector(a)->dot(sunAngle);
1805 if (d < 0) d = 0;
1806 if (d > 0)
1807 {
1808 float *c = level->dimension->getSunriseColor(level->getTimeOfDay(a), a);
1809 if (c != NULL)
1810 {
1811 d *= c[3];
1812 fr = fr * (1 - d) + c[0] * d;
1813 fg = fg * (1 - d) + c[1] * d;
1814 fb = fb * (1 - d) + c[2] * d;
1815 }
1816 }
1817 }
1818
1819 fr += (sr - fr) * whiteness;
1820 fg += (sg - fg) * whiteness;
1821 fb += (sb - fb) * whiteness;
1822
1823 float rainLevel = level->getRainLevel(a);
1824 if (rainLevel > 0)
1825 {
1826 float ba = 1 - rainLevel * 0.5f;
1827 float bb = 1 - rainLevel * 0.4f;
1828 fr *= ba;
1829 fg *= ba;
1830 fb *= bb;
1831 }
1832 float thunderLevel = level->getThunderLevel(a);
1833 if (thunderLevel > 0)
1834 {
1835 float ba = 1 - thunderLevel * 0.5f;
1836 fr *= ba;
1837 fg *= ba;
1838 fb *= ba;
1839 }
1840
1841 int t = Camera::getBlockAt(mc->level, player, a);
1842 if (isInClouds)
1843 {
1844 Vec3 *cc = level->getCloudColor(a);
1845 fr = (float) cc->x;
1846 fg = (float) cc->y;
1847 fb = (float) cc->z;
1848 }
1849 else if (t != 0 && Tile::tiles[t]->material == Material::water)
1850 {
1851 float clearness = EnchantmentHelper::getOxygenBonus(player) * 0.2f;
1852
1853 unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Water_Clear_Colour );
1854 byte redComponent = ((colour>>16)&0xFF);
1855 byte greenComponent = ((colour>>8)&0xFF);
1856 byte blueComponent = ((colour)&0xFF);
1857
1858 fr = (float)redComponent/256 + clearness;//0.02f;
1859 fg = (float)greenComponent/256 + clearness;//0.02f;
1860 fb = (float)blueComponent/256 + clearness;//0.2f;
1861 }
1862 else if (t != 0 && Tile::tiles[t]->material == Material::lava)
1863 {
1864 unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Lava_Clear_Colour );
1865 byte redComponent = ((colour>>16)&0xFF);
1866 byte greenComponent = ((colour>>8)&0xFF);
1867 byte blueComponent = ((colour)&0xFF);
1868
1869 fr = (float)redComponent/256;//0.6f;
1870 fg = (float)greenComponent/256;//0.1f;
1871 fb = (float)blueComponent/256;//0.00f;
1872 }
1873
1874 float brr = fogBrO + (fogBr - fogBrO) * a;
1875 fr *= brr;
1876 fg *= brr;
1877 fb *= brr;
1878
1879 double yy = (player->yOld + (player->y - player->yOld) * a) * level->dimension->getClearColorScale(); // 4J - getClearColorScale brought forward from 1.2.3
1880
1881 if (player->hasEffect(MobEffect::blindness))
1882 {
1883 int duration = player->getEffect(MobEffect::blindness)->getDuration();
1884 if (duration < 20)
1885 {
1886 yy = yy * (1.0f - (float) duration / 20.0f);
1887 }
1888 else
1889 {
1890 yy = 0;
1891 }
1892 }
1893
1894 if (yy < 1)
1895 {
1896 if (yy < 0) yy = 0;
1897 yy = yy * yy;
1898 fr *= yy;
1899 fg *= yy;
1900 fb *= yy;
1901 }
1902
1903 if (darkenWorldAmount > 0)
1904 {
1905 float amount = darkenWorldAmountO + (darkenWorldAmount - darkenWorldAmountO) * a;
1906 fr = fr * (1.0f - amount) + (fr * .7f) * amount;
1907 fg = fg * (1.0f - amount) + (fg * .6f) * amount;
1908 fb = fb * (1.0f - amount) + (fb * .6f) * amount;
1909 }
1910
1911 if (player->hasEffect(MobEffect::nightVision))
1912 {
1913 float scale = getNightVisionScale(mc->player, a);
1914 {
1915 float dist = FLT_MAX; // MGH - changed this to avoid divide by zero
1916 if ( (fr > 0) && (dist > (1.0f / fr)) )
1917 {
1918 dist = (1.0f / fr);
1919 }
1920 if ( (fg > 0) && (dist > (1.0f / fg)) )
1921 {
1922 dist = (1.0f / fg);
1923 }
1924 if ( (fb > 0) && (dist > (1.0f / fb)) )
1925 {
1926 dist = (1.0f / fb);
1927 }
1928 fr = fr * (1.0f - scale) + (fr * dist) * scale;
1929 fg = fg * (1.0f - scale) + (fg * dist) * scale;
1930 fb = fb * (1.0f - scale) + (fb * dist) * scale;
1931 }
1932 }
1933
1934 if (mc->options->anaglyph3d)
1935 {
1936 float frr = (fr * 30 + fg * 59 + fb * 11) / 100;
1937 float fgg = (fr * 30 + fg * 70) / (100);
1938 float fbb = (fr * 30 + fb * 70) / (100);
1939
1940 fr = frr;
1941 fg = fgg;
1942 fb = fbb;
1943 }
1944
1945 glClearColor(fr, fg, fb, 0.0f);
1946
1947}
1948
1949void GameRenderer::setupFog(int i, float alpha)
1950{
1951 shared_ptr<LivingEntity> player = mc->cameraTargetPlayer;
1952
1953 // 4J - check for creative mode brought forward from 1.2.3
1954 bool creative = false;
1955 if ( player->instanceof(eTYPE_PLAYER) )
1956 {
1957 creative = (dynamic_pointer_cast<Player>(player))->abilities.instabuild;
1958 }
1959
1960 if (i == 999)
1961 {
1962 __debugbreak();
1963 // 4J TODO
1964 /*
1965 glFog(GL_FOG_COLOR, getBuffer(0, 0, 0, 1));
1966 glFogi(GL_FOG_MODE, GL_LINEAR);
1967 glFogf(GL_FOG_START, 0);
1968 glFogf(GL_FOG_END, 8);
1969
1970 if (GLContext.getCapabilities().GL_NV_fog_distance) {
1971 glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
1972 }
1973
1974 glFogf(GL_FOG_START, 0);
1975 */
1976 return;
1977 }
1978
1979 glFog(GL_FOG_COLOR, getBuffer(fr, fg, fb, 1));
1980 glNormal3f(0, -1, 0);
1981 glColor4f(1, 1, 1, 1);
1982
1983 int t = Camera::getBlockAt(mc->level, player, alpha);
1984
1985 if (player->hasEffect(MobEffect::blindness))
1986 {
1987 float distance = 5.0f;
1988 int duration = player->getEffect(MobEffect::blindness)->getDuration();
1989 if (duration < 20)
1990 {
1991 distance = 5.0f + (renderDistance - 5.0f) * (1.0f - (float) duration / 20.0f);
1992 }
1993
1994 glFogi(GL_FOG_MODE, GL_LINEAR);
1995 if (i < 0)
1996 {
1997 glFogf(GL_FOG_START, 0);
1998 glFogf(GL_FOG_END, distance * 0.8f);
1999 }
2000 else
2001 {
2002 glFogf(GL_FOG_START, distance * 0.25f);
2003 glFogf(GL_FOG_END, distance);
2004 }
2005 // 4J - TODO investigate implementing this
2006 // if (GLContext.getCapabilities().GL_NV_fog_distance)
2007 // {
2008 // glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
2009 // }
2010 }
2011 else if (isInClouds)
2012 {
2013 glFogi(GL_FOG_MODE, GL_EXP);
2014 glFogf(GL_FOG_DENSITY, 0.1f); // was 0.06
2015 }
2016 else if (t > 0 && Tile::tiles[t]->material == Material::water)
2017 {
2018 glFogi(GL_FOG_MODE, GL_EXP);
2019 if (player->hasEffect(MobEffect::waterBreathing))
2020 {
2021 glFogf(GL_FOG_DENSITY, 0.05f); // was 0.06
2022 }
2023 else
2024 {
2025 glFogf(GL_FOG_DENSITY, 0.1f - (EnchantmentHelper::getOxygenBonus(player) * 0.03f)); // was 0.06
2026 }
2027 }
2028 else if (t > 0 && Tile::tiles[t]->material == Material::lava)
2029 {
2030 glFogi(GL_FOG_MODE, GL_EXP);
2031 glFogf(GL_FOG_DENSITY, 2.0f); // was 0.06
2032 }
2033 else
2034 {
2035 float distance = renderDistance;
2036 if (!mc->level->dimension->hasCeiling)
2037 {
2038 // 4J - test for doing bedrockfog brought forward from 1.2.3
2039 if (mc->level->dimension->hasBedrockFog() && !creative)
2040 {
2041 double yy = ((player->getLightColor(alpha) & 0xf00000) >> 20) / 16.0 + (player->yOld + (player->y - player->yOld) * alpha + 4) / 32;
2042 if (yy < 1)
2043 {
2044 if (yy < 0) yy = 0;
2045 yy = yy * yy;
2046 float dist = 100 * (float) yy;
2047 if (dist < 5) dist = 5;
2048 if (distance > dist) distance = dist;
2049 }
2050 }
2051 }
2052
2053 glFogi(GL_FOG_MODE, GL_LINEAR);
2054 glFogf(GL_FOG_START, distance * 0.25f);
2055 glFogf(GL_FOG_END, distance);
2056 if (i < 0)
2057 {
2058 glFogf(GL_FOG_START, 0);
2059 glFogf(GL_FOG_END, distance * 0.8f);
2060 }
2061 else
2062 {
2063 glFogf(GL_FOG_START, distance * 0.25f);
2064 glFogf(GL_FOG_END, distance);
2065 }
2066 /* 4J - removed - TODO investigate
2067 if (GLContext.getCapabilities().GL_NV_fog_distance)
2068 {
2069 glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
2070 }
2071 */
2072
2073 if (mc->level->dimension->isFoggyAt((int) player->x, (int) player->z))
2074 {
2075 glFogf(GL_FOG_START, distance * 0.05f);
2076 glFogf(GL_FOG_END, min(distance, 16 * 16 * .75f) * .5f);
2077 }
2078 }
2079
2080 glEnable(GL_COLOR_MATERIAL);
2081 glColorMaterial(GL_FRONT, GL_AMBIENT);
2082
2083}
2084
2085FloatBuffer *GameRenderer::getBuffer(float a, float b, float c, float d)
2086{
2087 lb->clear();
2088 lb->put(a)->put(b)->put(c)->put(d);
2089 lb->flip();
2090 return lb;
2091}
2092
2093int GameRenderer::getFpsCap(int option)
2094{
2095 int maxFps = 200;
2096 if (option == 1) maxFps = 120;
2097 if (option == 2) maxFps = 35;
2098 return maxFps;
2099}
2100
2101void GameRenderer::updateAllChunks()
2102{
2103 // mc->levelRenderer->updateDirtyChunks(mc->cameraTargetPlayer, true);
2104}