the whole game

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

268
src/client/renderer/Chunk.cpp Executable file
View File

@@ -0,0 +1,268 @@
#include "Chunk.h"
#include "Tesselator.h"
#include "TileRenderer.h"
#include "culling/Culler.h"
#include "../../world/entity/Entity.h"
#include "../../world/level/tile/Tile.h"
#include "../../world/level/Region.h"
#include "../../world/level/chunk/LevelChunk.h"
#include "../../util/Mth.h"
//#include "../../platform/time.h"
/*static*/ int Chunk::updates = 0;
//static Stopwatch swRebuild;
//int* _layerChunks[3] = {0, 0, 0}; //Chunk::NumLayers];
//int _layerChunkCount[3] = {0, 0, 0};
Chunk::Chunk( Level* level_, int x, int y, int z, int size, int lists_, GLuint* ptrBuf/*= NULL*/)
: level(level_),
visible(false),
compiled(false),
_empty(true),
xs(size), ys(size), zs(size),
dirty(false),
occlusion_visible(true),
occlusion_querying(false),
lists(lists_),
vboBuffers(ptrBuf),
bb(0,0,0,1,1,1),
t(Tesselator::instance)
{
for (int l = 0; l < NumLayers; l++) {
empty[l] = false;
}
radius = Mth::sqrt((float)(xs * xs + ys * ys + zs * zs)) * 0.5f;
this->x = -999;
setPos(x, y, z);
}
void Chunk::setPos( int x, int y, int z )
{
if (x == this->x && y == this->y && z == this->z) return;
reset();
this->x = x;
this->y = y;
this->z = z;
xm = x + xs / 2;
ym = y + ys / 2;
zm = z + zs / 2;
const float xzg = 1.0f;
const float yp = 2.0f;
const float yn = 0.0f;
bb.set(x-xzg, y-yn, z-xzg, x + xs+xzg, y + ys+yp, z + zs+xzg);
//glNewList(lists + 2, GL_COMPILE);
//ItemRenderer.renderFlat(AABB.newTemp(xRenderOffs - g, yRenderOffs - g, zRenderOffs - g, xRenderOffs + xs + g, yRenderOffs + ys + g, zRenderOffs + zs + g));
//glEndList();
setDirty();
}
void Chunk::translateToPos()
{
glTranslatef2((float)x, (float)y, (float)z);
}
void Chunk::rebuild()
{
if (!dirty) return;
//if (!visible) return;
updates++;
//if (!_layerChunks[0]) {
// for (int i = 0; i < NumLayers; ++i)
// _layerChunks[i] = new int[xs * ys * zs];
//}
//for (int i = 0; i < NumLayers; ++i)
// _layerChunkCount[i] = 0;
//Stopwatch& sw = swRebuild;
//sw.start();
int x0 = x;
int y0 = y;
int z0 = z;
int x1 = x + xs;
int y1 = y + ys;
int z1 = z + zs;
for (int l = 0; l < NumLayers; l++) {
empty[l] = true;
}
_empty = true;
LevelChunk::touchedSky = false;
int r = 1;
Region region(level, x0 - r, y0 - r, z0 - r, x1 + r, y1 + r, z1 + r);
TileRenderer tileRenderer(&region);
bool doRenderLayer[NumLayers] = {true, false, false};
for (int l = 0; l < NumLayers; l++) {
if (!doRenderLayer[l]) continue;
bool renderNextLayer = false;
bool rendered = false;
bool started = false;
int cindex = -1;
for (int y = y0; y < y1; y++) {
for (int z = z0; z < z1; z++) {
for (int x = x0; x < x1; x++) {
++cindex;
//if (l > 0 && cindex != _layerChunks[_layerChunkCount[l]])
int tileId = region.getTile(x, y, z);
if (tileId > 0) {
if (!started) {
started = true;
#ifndef USE_VBO
glNewList(lists + l, GL_COMPILE);
glPushMatrix2();
translateToPos();
float ss = 1.000001f;
glTranslatef2(-zs / 2.0f, -ys / 2.0f, -zs / 2.0f);
glScalef2(ss, ss, ss);
glTranslatef2(zs / 2.0f, ys / 2.0f, zs / 2.0f);
#endif
t.begin();
//printf(".");
//printf("Tesselator::offset : %d, %d, %d\n", this->x, this->y, this->z);
t.offset((float)(-this->x), (float)(-this->y), (float)(-this->z));
//printf("Tesselator::offset : %f, %f, %f\n", this->x, this->y, this->z);
}
Tile* tile = Tile::tiles[tileId];
int renderLayer = tile->getRenderLayer();
// if (renderLayer == l)
// rendered |= tileRenderer.tesselateInWorld(tile, x, y, z);
// else {
// _layerChunks[_layerChunkCount[renderLayer]++] = cindex;
// }
if (renderLayer > l) {
renderNextLayer = true;
doRenderLayer[renderLayer] = true;
} else if (renderLayer == l) {
rendered |= tileRenderer.tesselateInWorld(tile, x, y, z);
}
}
}
}
}
if (started) {
#ifdef USE_VBO
renderChunk[l] = t.end(true, vboBuffers[l]);
renderChunk[l].pos.x = (float)this->x;
renderChunk[l].pos.y = (float)this->y;
renderChunk[l].pos.z = (float)this->z;
#else
t.end(false, -1);
glPopMatrix2();
glEndList();
#endif
t.offset(0, 0, 0);
} else {
rendered = false;
}
if (rendered) {
empty[l] = false;
_empty = false;
}
if (!renderNextLayer) break;
}
//sw.stop();
//sw.printEvery(1, "rebuild-");
skyLit = LevelChunk::touchedSky;
compiled = true;
return;
}
float Chunk::distanceToSqr( const Entity* player ) const
{
float xd = (float) (player->x - xm);
float yd = (float) (player->y - ym);
float zd = (float) (player->z - zm);
return xd * xd + yd * yd + zd * zd;
}
float Chunk::squishedDistanceToSqr( const Entity* player ) const
{
float xd = (float) (player->x - xm);
float yd = (float) (player->y - ym) * 2;
float zd = (float) (player->z - zm);
return xd * xd + yd * yd + zd * zd;
}
void Chunk::reset()
{
for (int i = 0; i < NumLayers; i++) {
empty[i] = true;
}
visible = false;
compiled = false;
_empty = true;
}
int Chunk::getList( int layer )
{
if (!visible) return -1;
if (!empty[layer]) return lists + layer;
return -1;
}
RenderChunk& Chunk::getRenderChunk( int layer )
{
return renderChunk[layer];
}
int Chunk::getAllLists( int displayLists[], int p, int layer )
{
if (!visible) return p;
if (!empty[layer]) displayLists[p++] = (lists + layer);
return p;
}
void Chunk::cull( Culler* culler )
{
visible = culler->isVisible(bb);
}
void Chunk::renderBB()
{
//glCallList(lists + 2);
}
bool Chunk::isEmpty()
{
return compiled && _empty;//empty[0] && empty[1] && empty[2];
// if (!compiled) return false;
// return empty[0] && empty[1];
}
void Chunk::setDirty()
{
dirty = true;
}
void Chunk::setClean()
{
dirty = false;
}
bool Chunk::isDirty()
{
return dirty;
}
void Chunk::resetUpdates()
{
updates = 0;
//swRebuild.reset();
}

74
src/client/renderer/Chunk.h Executable file
View File

@@ -0,0 +1,74 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__Chunk_H__
#define NET_MINECRAFT_CLIENT_RENDERER__Chunk_H__
//package net.minecraft.client.renderer;
#include "RenderChunk.h"
#include "../../world/phys/AABB.h"
class Level;
class Entity;
class Culler;
class Tesselator;
// @note: TileEntity stuff is stripped away
class Chunk
{
static const int NumLayers = 3;
public:
Chunk(Level* level_, int x, int y, int z, int size, int lists_, GLuint* ptrBuf = NULL);
void setPos(int x, int y, int z);
void rebuild();
void setDirty();
void setClean();
bool isDirty();
void reset();
float distanceToSqr(const Entity* player) const;
float squishedDistanceToSqr(const Entity* player) const;
//@todo @fix
int getAllLists(int displayLists[], int p, int layer);
int getList(int layer);
RenderChunk& getRenderChunk(int layer);
bool isEmpty();
void cull(Culler* culler);
void renderBB();
static void resetUpdates();
private:
void translateToPos();
public:
Level* level;
static int updates;// = 0;
int x, y, z, xs, ys, zs;
bool empty[NumLayers];
int xm, ym, zm;
float radius;
AABB bb;
int id;
bool visible;
bool occlusion_visible;
bool occlusion_querying;
int occlusion_id;
bool skyLit;
RenderChunk renderChunk[NumLayers];
private:
Tesselator& t;
int lists;
GLuint* vboBuffers;
bool compiled;
bool dirty;
bool _empty;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__Chunk_H__*/

View File

@@ -0,0 +1,22 @@
#ifndef CHUNKRENDERER_H__
#define CHUNKRENDERER_H__
#include "gles.h"
#include "../../world/level/Region.h"
class ChunkRenderer {
public:
ChunkRenderer(const Region& region)
: r(region)
{
}
void render() {
//glTranslate(r.xc1,
}
private:
const Region& r;
};
#endif /*CHUNKRENDERER_H__*/

53
src/client/renderer/Color4.h Executable file
View File

@@ -0,0 +1,53 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__Color4_H__
#define NET_MINECRAFT_CLIENT_RENDERER__Color4_H__
class Color4
{
public:
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat a;
Color4(GLfloat r_, GLfloat g_, GLfloat b_, GLfloat a_ = 0)
: r(r_),
g(g_),
b(b_),
a(a_)
{}
Color4(int hex) {
r = ((hex>>16)& 255) / 255.0f;
g = ((hex>>8) & 255) / 255.0f;
b = (hex&255) / 255.0f;
a = (hex >> 24) / 255.0f;
}
void add(GLfloat val, bool modifyAlpha) {
r += val;
g += val;
b += val;
if (modifyAlpha) a += val;
sanitize();
}
void mul(GLfloat val, bool modifyAlpha) {
r *= val;
g *= val;
b *= val;
if (modifyAlpha) a *= val;
sanitize();
}
private:
void sanitize() {
range(r);
range(g);
range(b);
range(a);
}
__inline void range(GLfloat& v) {
if (v < 0) v = 0;
if (v > 1) v = 1;
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__Color4_H__*/

View File

@@ -0,0 +1,35 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__DirtyChunkSorter_H__
#define NET_MINECRAFT_CLIENT_RENDERER__DirtyChunkSorter_H__
//package net.minecraft.client.renderer;
#include "../../world/entity/Entity.h"
#include "Chunk.h"
class DirtyChunkSorter
{
Entity* cameraEntity;
public:
DirtyChunkSorter(Entity* cameraEntity) {
this->cameraEntity = cameraEntity;
}
// @attn: c0 > c1
bool operator() (Chunk* c0, Chunk* c1) {
bool i0 = c0->visible;
bool i1 = c1->visible;
if (i0 && !i1) return false; // 1;
if (i1 && !i0) return true; // -1;
float d0 = c0->distanceToSqr(cameraEntity);
float d1 = c1->distanceToSqr(cameraEntity);
if (d0 < d1) return false; // 1;
if (d0 > d1) return true; // -1;
return c0->id > c1->id;// ? -1 : 1;
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__DirtyChunkSorter_H__*/

View File

@@ -0,0 +1,27 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__DistanceChunkSorter_H__
#define NET_MINECRAFT_CLIENT_RENDERER__DistanceChunkSorter_H__
//package net.minecraft.client.renderer;
#include "../../world/entity/Entity.h"
#include "Chunk.h"
class DistanceChunkSorter
{
Entity* player;
public:
DistanceChunkSorter(Entity* player) {
this->player = player;
}
bool operator() (const Chunk* c0, const Chunk* c1) {
float d0 = c0->distanceToSqr(player);
float d1 = c1->distanceToSqr(player);
if (d0 > 32 * 32 && c0->y < 64) d0 *= 10.0f;
if (d1 > 32 * 32 && c1->y < 64) d1 *= 10.0f;
return d0 < d1;//? -1 : 1;
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__DistanceChunkSorter_H__*/

View File

@@ -0,0 +1,8 @@
#include "EntityTileRenderer.h"
EntityTileRenderer* EntityTileRenderer::instance = new EntityTileRenderer();
void EntityTileRenderer::render( Tile* tile, int data, float brightness )
{
TileEntityRenderDispatcher::getInstance()->render(&chest, 0, 0, 0, 0);
}

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__EntityTileRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER__EntityTileRenderer_H__
//package net.minecraft.client.renderer;
#include "../../world/level/tile/entity/ChestTileEntity.h"
#include "tileentity/TileEntityRenderDispatcher.h"
class Tile;
class EntityTileRenderer
{
public:
static EntityTileRenderer* instance;
void render(Tile* tile, int data, float brightness);
ChestTileEntity chest;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__EntityTileRenderer_H__*/

View File

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

View File

@@ -0,0 +1,117 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__GameRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER__GameRenderer_H__
//package net.minecraft.client.renderer;
#include "gles.h"
#include <cstddef>
#include "../../util/SmoothFloat.h"
#include "../../world/phys/Vec3.h"
#include "../gui/components/ImageButton.h"
class Minecraft;
class Entity;
class ItemInHandRenderer;
class LevelRenderer;
class GameRenderer
{
public:
GameRenderer(Minecraft* mc_);
~GameRenderer();
void pick(float a);
void updateAllChunks();
void zoomRegion(float zoom, float xa, float ya);
void unZoomRegion();
void setupGuiScreen(bool clearColorBuffer);
void tick(int nTick, int maxTick);
void render(float a);
void renderLevel(float a);
void renderItemInHand(float a, int eye);
void onGraphicsReset();
void setupCamera(float a, int eye);
void moveCameraToPlayer(float a);
void setupClearColor(float a);
float getFov(float a, bool applyEffects);
private:
void setupFog(int i);
void tickFov();
void bobHurt(float a);
void bobView(float a);
bool updateFreeformPickDirection(float a, Vec3& outDir);
void prepareAndRenderClouds(LevelRenderer* levelRenderer, float a);
public:
ItemInHandRenderer* itemInHandRenderer;
private:
Minecraft* mc;
float renderDistance;
int _tick;
Vec3 pickDirection;
// smooth camera movement
SmoothFloat smoothTurnX;
SmoothFloat smoothTurnY;
// // third-person distance etc
// SmoothFloat smoothDistance = /*new*/ SmoothFloat();
// SmoothFloat smoothRotation = /*new*/ SmoothFloat();
// SmoothFloat smoothTilt = /*new*/ SmoothFloat();
// SmoothFloat smoothRoll = /*new*/ SmoothFloat();
float thirdDistance;
float thirdDistanceO;
float thirdRotation;
float thirdRotationO;
float thirdTilt;
float thirdTiltO;
// zoom
float zoom;
float zoom_x;
float zoom_y;
// fov modification
float fov, oFov;
float fovOffset;
float fovOffsetO;
float _setupCameraFov;
// roll modification
float cameraRoll;
float cameraRollO;
float fr;
float fg;
float fb;
float fogBrO, fogBr;
float _rotX;
float _rotY;
float _rotXlast;
float _rotYlast;
float _lastTickT;
void saveMatrices();
float lastProjMatrix[16];
float lastModelMatrix[16];
// Scissor area that Minecraft::screen defines
bool useScreenScissor;
IntRectangle screenScissorArea;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__GameRenderer_H__*/

View File

@@ -0,0 +1,533 @@
#include "ItemInHandRenderer.h"
#include "gles.h"
#include "Tesselator.h"
#include "entity/EntityRenderDispatcher.h"
#include "entity/EntityRenderer.h"
#include "entity/MobRenderer.h"
#include "../Minecraft.h"
#include "../player/LocalPlayer.h"
#include "../../world/entity/player/Player.h"
#include "../../world/item/Item.h"
#include "../../world/level/material/Material.h"
#include "../../world/level/tile/Tile.h"
#include "../../world/level/Level.h"
#include "../../util/Mth.h"
#include "../../world/entity/player/Inventory.h"
#include "../../platform/time.h"
#include "Textures.h"
#include "../../world/item/UseAnim.h"
#include "../../world/item/BowItem.h"
#include "../../world/level/tile/LeafTile.h"
#include "entity/HumanoidMobRenderer.h"
//static StopwatchHandler handler;
ItemInHandRenderer::ItemInHandRenderer( Minecraft* mc )
: mc(mc),
lastSlot(-1),
height(0),
oHeight(0),
lastIconRendered(0),
lastItemRendered(0),
//selectedItem(NULL),
item(0, 1, 0)
{
GLuint ids[MaxNumRenderObjects];
glGenBuffers2(MaxNumRenderObjects, ids);
for (int i = 0; i < MaxNumRenderObjects; ++i) {
renderObjects[i].itemId = -1;
renderObjects[i].chunk.vboId = ids[i];
//LOGI("IDS: %d\n", ids[i]);
}
//LOGI("SizeOf :%d (256 * %d)\n", sizeof(renderObjects), sizeof(RenderCall));
}
void ItemInHandRenderer::tick()
{
oHeight = height;
item.id = 0;
ItemInstance* itemInHand = mc->player->inventory->getSelected();
if (itemInHand && itemInHand->count > 0) {
item.id = itemInHand->id;
item.setAuxValue(itemInHand->getAuxValue());
}
float max = 0.4f;
float tHeight = 1;//matches ? 1 : 0;
float dd = tHeight - height;
if (dd < -max) dd = -max;
if (dd > max) dd = max;
height += dd;
}
void ItemInHandRenderer::renderItem(Mob* mob, ItemInstance* item )
{
//Stopwatch& w = handler.get("item:" + Tile::tiles[item->id]->getDescriptionId());
//w.start();
int itemId = item->id;
// Ugly hack, but what the heck, I don't have time at the moment
// Use spare slots between 200 and 255 (for now) for items with different
// graphics per data. @note: Check Tile.cpp for needed IDs to override
if (itemId == Tile::cloth->id) {
itemId = 200 + item->getAuxValue(); // 200 to 215
} else if (itemId == Tile::treeTrunk->id) {
itemId = 216 + item->getAuxValue(); // 216 to 219 @treeTrunk
} else if (itemId == Tile::sapling->id) {
itemId = 220 + item->getAuxValue(); // 220 to 223 @sapling
} else if (itemId == Tile::stoneSlabHalf->id) {
itemId = 224 + item->getAuxValue(); // 224 to 231 @stoneslab
} else if (itemId == ((Tile*)Tile::leaves)->id) {
itemId = 232 + (item->getAuxValue() & LeafTile::LEAF_TYPE_MASK); // 232 to 235 @leaves
}
RenderCall& renderObject = renderObjects[itemId];
int itemIcon = item->getIcon();
if(mob != NULL) {
itemIcon = mob->getItemInHandIcon(item, 0);
}
bool reTesselate(false);
if(itemIcon != lastIconRendered && lastItemRendered == itemId)
reTesselate = true;
lastItemRendered = itemId;
lastIconRendered = itemIcon;
//const int aux = item->getAuxValue();
if (renderObject.itemId == -1 || reTesselate) {
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape())) {
Tesselator& t = Tesselator::instance;
t.beginOverride();
int renderedItemId = item->id;
if (renderedItemId == ((Tile*)Tile::leaves)->id)
renderedItemId = ((Tile*)Tile::leaves_carried)->id;
if (renderedItemId == Tile::grass->id)
renderedItemId = Tile::grass_carried->id;
tileRenderer.renderTile(Tile::tiles[renderedItemId], item->getAuxValue());
renderObject.chunk = t.endOverride(renderObject.chunk.vboId);
renderObject.texture = "terrain.png";
renderObject.itemId = itemId;
renderObject.isFlat = false;
} else {
renderObject.itemId = itemId;
renderObject.isFlat = true;
if (item->id < 256) {
renderObject.texture = "terrain.png";
//mc->textures->loadAndBindTexture("terrain.png");
} else {
renderObject.texture = "gui/items.png";
//mc->textures->loadAndBindTexture("gui/items.png");
}
// glDisable2(GL_LIGHTING);
Tesselator& t = Tesselator::instance;
t.beginOverride();
t.color(0xff, 0xff, 0xff);
const int up = itemIcon & 15;
const int vp = itemIcon >> 4;
float u1 = (up * 16 + 0.00f) / 256.0f;
float u0 = (up * 16 + 15.99f) / 256.0f;
float v0 = (vp * 16 + 0.00f) / 256.0f;
float v1 = (vp * 16 + 15.99f) / 256.0f;
float r = 1.0f;
// float xo = 0.0f;
// float yo = 0.3f;
/*
//glEnable2(GL_RESCALE_NORMAL);
glTranslatef2(-xo, -yo, 0);
float s = 1.5f;
glScalef2(s, s, s);
glRotatef2(50, 0, 1, 0);
glRotatef2(45 + 290, 0, 0, 1);
glTranslatef2(-15 / 16.0f, -1 / 16.0f, 0);
*/
float dd = 1 / 16.0f;
t.vertexUV(0, 0, 0, u0, v1);
t.vertexUV(r, 0, 0, u1, v1);
t.vertexUV(r, 1, 0, u1, v0);
t.vertexUV(0, 1, 0, u0, v0);
t.vertexUV(0, 1, 0 - dd, u0, v0);
t.vertexUV(r, 1, 0 - dd, u1, v0);
t.vertexUV(r, 0, 0 - dd, u1, v1);
t.vertexUV(0, 0, 0 - dd, u0, v1);
for (int i = 0; i < 16; i++) {
float p = i / 16.0f;
float uu = u0 + (u1 - u0) * p - 0.5f / 256.0f;
float xx = r * p;
t.vertexUV(xx, 0, 0 - dd, uu, v1);
t.vertexUV(xx, 0, 0, uu, v1);
t.vertexUV(xx, 1, 0, uu, v0);
t.vertexUV(xx, 1, 0 - dd, uu, v0);
}
for (int i = 0; i < 16; i++) {
float p = i / 16.0f;
float uu = u0 + (u1 - u0) * p - 0.5f / 256.0f;
float xx = r * p + 1 / 16.0f;
t.vertexUV(xx, 1, 0 - dd, uu, v0);
t.vertexUV(xx, 1, 0, uu, v0);
t.vertexUV(xx, 0, 0, uu, v1);
t.vertexUV(xx, 0, 0 - dd, uu, v1);
}
for (int i = 0; i < 16; i++) {
float p = i / 16.0f;
float vv = v1 + (v0 - v1) * p - 0.5f / 256.0f;
float yy = r * p + 1 / 16.0f;
t.vertexUV(0, yy, 0, u0, vv);
t.vertexUV(r, yy, 0, u1, vv);
t.vertexUV(r, yy, 0 - dd, u1, vv);
t.vertexUV(0, yy, 0 - dd, u0, vv);
}
for (int i = 0; i < 16; i++) {
float p = i / 16.0f;
float vv = v1 + (v0 - v1) * p - 0.5f / 256.0f;
float yy = r * p;
t.vertexUV(r, yy, 0, u1, vv);
t.vertexUV(0, yy, 0, u0, vv);
t.vertexUV(0, yy, 0 - dd, u0, vv);
t.vertexUV(r, yy, 0 - dd, u1, vv);
}
renderObject.chunk = t.endOverride(renderObject.chunk.vboId);
}
}
if (renderObject.itemId >= 0) {
if (renderObject.isFlat) {
float xo = 0.0f;
float yo = 0.3f;
glPushMatrix2();
glTranslatef2(-xo, -yo, 0);
float s = 1.5f;
glScalef2(s, s, s);
glRotatef2(50, 0, 1, 0);
glRotatef2(45 + 290, 0, 0, 1);
glTranslatef2(-15 / 16.0f, -1 / 16.0f, 0);
}
mc->textures->loadAndBindTexture(renderObject.texture);
drawArrayVT_NoState(renderObject.chunk.vboId, renderObject.chunk.vertexCount);
if (renderObject.isFlat)
glPopMatrix2();
}
//w.stop();
//handler.printEvery(100);
}
void ItemInHandRenderer::render( float a )
{
//return;
//Stopwatch& w = handler.get("render");
//w.start();
float h = oHeight + (height - oHeight) * a;
Player* player = mc->player;
// if (selectedTile==NULL) return;
glPushMatrix2();
glRotatef2(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0);
glRotatef2(player->yRotO + (player->yRot - player->yRotO) * a, 0, 1, 0);
glPopMatrix2();
float br = mc->level->getBrightness(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
ItemInstance* item;// = selectedItem;
//if (player.fishing != NULL) {
// item = /*new*/ ItemInstance(Item.stick);
//}
if (this->item.id > 0)
item = &this->item;
else
item = NULL;
if (item != NULL) {
glColor4f2(br, br, br, 1);
bool isUsing = player->getUseItemDuration() > 0;
bool isBow = item->id == Item::bow->id;
bool noSwingAnimation = isUsing && (isBow || (item->getUseAnimation() != UseAnim::none));
const float swing = noSwingAnimation ? 0 : player->getAttackAnim(a);
const float sqrtSwing = Mth::sqrt(swing);
const float swing3 = Mth::sin(swing * swing * Mth::PI);
const float swing1 = Mth::sin(swing * Mth::PI);
const float swing2 = Mth::sin(sqrtSwing * Mth::PI);
const float d = 0.8f;
glPushMatrix2();
if (isUsing) {
UseAnim::UseAnimation anim = item->getUseAnimation();
if (anim == UseAnim::eat || anim == UseAnim::drink) {
float t = (player->getUseItemDuration() - a + 1);
float useProgress = 1 - (t / item->getUseDuration());
float swing = useProgress;
float is = 1 - swing;
is = is * is * is;
is = is * is * is;
is = is * is * is;
float iss = 1 - is;
glTranslatef(0, Mth::abs(Mth::cos(t / 4 * Mth::PI) * 0.1f) * (swing > 0.2 ? 1 : 0), 0);
glTranslatef(iss * 0.6f, -iss * 0.5f, 0);
glRotatef(iss * 90, 0, 1, 0);
glRotatef(iss * 10, 1, 0, 0);
glRotatef(iss * 30, 0, 0, 1);
}
} else {
glTranslatef2(-swing2 * 0.4f, (float) Mth::sin(sqrtSwing * Mth::PI * 2) * 0.2f, -swing1 * 0.2f);
}
glTranslatef2(0.7f * d, -0.65f * d - (1 - h) * 0.6f, -0.9f * d);
glRotatef2(45, 0, 1, 0);
//glEnable2(GL_RESCALE_NORMAL);
glRotatef2(-swing3 * 20, 0, 1, 0);
glRotatef2(-swing2 * 20, 0, 0, 1);
glRotatef2(-swing2 * 80, 1, 0, 0);
float ss = 0.4f;
glScalef2(ss, ss, ss);
if (player->getUseItemDuration() > 0) {
UseAnim::UseAnimation anim = item->getUseAnimation();
if(anim == UseAnim::bow) {
glRotatef(-18, 0, 0, 1);
glRotatef(-12, 0, 1, 0);
glRotatef(-8, 1, 0, 0);
glTranslatef(-0.9f, 0.2f, 0.0f);
float timeHeld = (item->getUseDuration() - (player->getUseItemDuration() - a + 1));
float pow = timeHeld / (float) (BowItem::MAX_DRAW_DURATION);
pow = ((pow * pow) + pow * 2) / 3;
if (pow > 1) pow = 1;
if (pow > 0.1f) {
glTranslatef(0, Mth::sin((timeHeld - 0.1f) * 1.3f) * 0.01f * (pow - 0.1f), 0);
}
glTranslatef(0, 0, pow * 0.1f);
glRotatef(-45 - 290, 0, 0, 1);
glRotatef(-50, 0, 1, 0);
glTranslatef(0, 0.5f, 0);
float ys = 1 + pow * 0.2f;
glScalef(1, 1, ys);
glTranslatef(0, -0.5f, 0);
glRotatef(50, 0, 1, 0);
glRotatef(45 + 290, 0, 0, 1);
}
}
if (item->getItem()->isMirroredArt()) {
glRotatef2(180, 0, 1, 0);
}
glEnableClientState2(GL_VERTEX_ARRAY);
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
renderItem(player, item);
glDisableClientState2(GL_VERTEX_ARRAY);
glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
glPopMatrix2();
} else {
glColor4f2(br, br, br, 1);
glPushMatrix2();
float d = 0.8f;
const float swing = player->getAttackAnim(a);
const float sqrtSwing = Mth::sqrt(swing);
const float swing3 = Mth::sin(swing * swing * Mth::PI);
const float swing1 = Mth::sin(swing * Mth::PI);
const float swing2 = Mth::sin(sqrtSwing * Mth::PI);
glTranslatef2(-swing2 * 0.3f, (float) Mth::sin(Mth::sqrt(swing) * Mth::PI * 2) * 0.4f, -swing1 * 0.4f);
glTranslatef2(0.8f * d, -0.75f * d - (1 - h) * 0.6f, -0.9f * d);
glRotatef2(45, 0, 1, 0);
//glEnable2(GL_RESCALE_NORMAL);
glRotatef2(swing2 * 70, 0, 1, 0);
glRotatef2(-swing3 * 20, 0, 0, 1);
// glRotatef2(-swing2 * 80, 1, 0, 0);
mc->textures->loadAndBindTexture("mob/char.png");
glTranslatef2(-1.0f, +3.6f, +3.5f);
glRotatef2(120, 0, 0, 1);
glRotatef2(180 + 20, 1, 0, 0);
glRotatef2(-90 - 45, 0, 1, 0);
glScalef2(1.5f / 24.0f * 16, 1.5f / 24.0f * 16, 1.5f / 24.0f * 16);
glTranslatef2(5.6f, 0, 0);
EntityRenderer* er = EntityRenderDispatcher::getInstance()->getRenderer(mc->player);
HumanoidMobRenderer* playerRenderer = (HumanoidMobRenderer*) er;
float ss = 1;
glScalef2(ss, ss, ss);
playerRenderer->renderHand();
glPopMatrix2();
}
//glDisable2(GL_RESCALE_NORMAL);
//Lighting.turnOff();
//w.stop();
}
void ItemInHandRenderer::renderScreenEffect( float a )
{
glDisable2(GL_ALPHA_TEST);
if (mc->player->isOnFire()) {
mc->textures->loadAndBindTexture("terrain.png");
renderFire(a);
}
if (mc->player->isInWall()) // Inside a tile
{
int x = Mth::floor(mc->player->x);
int y = Mth::floor(mc->player->y);
int z = Mth::floor(mc->player->z);
mc->textures->loadAndBindTexture("terrain.png");
int tile = mc->level->getTile(x, y, z);
if (Tile::tiles[tile] != NULL) {
renderTex(a, Tile::tiles[tile]->getTexture(2));
}
}
// if (mc->player->isUnderLiquid(Material::water)) {
//mc->textures->loadAndBindTexture("misc/water.png");
// renderWater(a);
// }
glEnable2(GL_ALPHA_TEST);
}
void ItemInHandRenderer::itemPlaced()
{
height = 0;
}
void ItemInHandRenderer::itemUsed()
{
height = 0;
}
void ItemInHandRenderer::renderTex( float a, int tex )
{
Tesselator& t = Tesselator::instance;
float br;// = mc->player->getBrightness(a);
br = 0.1f;
glColor4f2(br, br, br, 0.5f);
glPushMatrix2();
float x0 = -1;
float x1 = +1;
float y0 = -1;
float y1 = +1;
float z0 = -0.5f;
float r = 2 / 256.0f;
float u0 = (tex % 16) / 256.0f - r;
float u1 = (tex % 16 + 15.99f) / 256.0f + r;
float v0 = (tex / 16) / 256.0f - r;
float v1 = (tex / 16 + 15.99f) / 256.0f + r;
t.begin();
t.vertexUV(x0, y0, z0, u1, v1);
t.vertexUV(x1, y0, z0, u0, v1);
t.vertexUV(x1, y1, z0, u0, v0);
t.vertexUV(x0, y1, z0, u1, v0);
//t.end();
t.draw();
glPopMatrix2();
glColor4f2(1, 1, 1, 1);
}
void ItemInHandRenderer::renderWater( float a )
{
Tesselator& t = Tesselator::instance;
float br = mc->player->getBrightness(a);
glColor4f2(br, br, br, 0.5f);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix2();
float size = 4;
float x0 = -1;
float x1 = +1;
float y0 = -1;
float y1 = +1;
float z0 = -0.5f;
float uo = -mc->player->yRot / 64.0f;
float vo = +mc->player->xRot / 64.0f;
t.begin();
t.vertexUV(x0, y0, z0, size + uo, size + vo);
t.vertexUV(x1, y0, z0, 0 + uo, size + vo);
t.vertexUV(x1, y1, z0, 0 + uo, 0 + vo);
t.vertexUV(x0, y1, z0, size + uo, 0 + vo);
//t.end();
t.draw();
glPopMatrix2();
glColor4f2(1, 1, 1, 1);
glDisable2(GL_BLEND);
}
void ItemInHandRenderer::renderFire( float a )
{
Tesselator& t = Tesselator::instance;
glColor4f2(1, 1, 1, 0.9f);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float size = 1;
for (int i = 0; i < 2; i++) {
glPushMatrix2();
int tex = ((Tile*)Tile::fire)->tex + i * 16;
int xt = (tex & 0xf) << 4;
int yt = tex & 0xf0;
float u0 = (xt) / 256.0f;
float u1 = (xt + 15.99f) / 256.0f;
float v0 = (yt) / 256.0f;
float v1 = (yt + 15.99f) / 256.0f;
float x0 = (0 - size) / 2;
float x1 = x0 + size;
float y0 = 0 - size / 2;
float y1 = y0 + size;
float z0 = -0.5f;
glTranslatef2(-(i * 2 - 1) * 0.24f, -0.3f, 0);
glRotatef2((i * 2 - 1) * 10.f, 0, 1, 0);
t.begin();
t.vertexUV(x0, y0, z0, u1, v1);
t.vertexUV(x1, y0, z0, u0, v1);
t.vertexUV(x1, y1, z0, u0, v0);
t.vertexUV(x0, y1, z0, u1, v0);
//t.end();
t.draw();
glPopMatrix2();
}
glColor4f2(1, 1, 1, 1);
glDisable2(GL_BLEND);
}
void ItemInHandRenderer::onGraphicsReset()
{
GLuint ids[MaxNumRenderObjects];
glGenBuffers2(MaxNumRenderObjects, ids);
for (int i = 0; i < MaxNumRenderObjects; ++i) {
renderObjects[i].itemId = -1;
renderObjects[i].chunk.vboId = ids[i];
}
}

View File

@@ -0,0 +1,57 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__ItemInHandRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER__ItemInHandRenderer_H__
//package net.minecraft.client.renderer;
#include "TileRenderer.h"
#include "../renderer/RenderChunk.h"
#include "../../world/item/ItemInstance.h"
class Minecraft;
typedef struct RenderCall {
int itemId;
RenderChunk chunk;
std::string texture;
bool isFlat;
} RenderCall;
class ItemInHandRenderer
{
public:
ItemInHandRenderer(Minecraft* mc);
void tick();
void render(float a);
void renderItem(Mob* player, ItemInstance* item);
void renderScreenEffect(float a);
void itemPlaced();
void itemUsed();
void onGraphicsReset();
private:
void renderTex(float a, int tex);
void renderWater(float a);
void renderFire(float a);
private:
int lastIconRendered;
int lastItemRendered;
int lastSlot;
ItemInstance item;
Minecraft* mc;
//ItemInstance* selectedItem;
float height;
float oHeight;
TileRenderer tileRenderer;
static const int MaxNumRenderObjects = 512;
RenderCall renderObjects[MaxNumRenderObjects];
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__ItemInHandRenderer_H__*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,130 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__LevelRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER__LevelRenderer_H__
//package net.minecraft.client.renderer;
#include "../../world/level/LevelListener.h"
#include "../../world/phys/Vec3.h"
#include "RenderList.h"
#include "gles.h"
#include <vector>
class Minecraft;
class Textures;
class Culler;
class Chunk;
class TileRenderer;
class Level;
class Mob;
class Player;
class HitResult;
class AABB;
class TripodCamera;
class LevelRenderer: public LevelListener
{
public:
static const int CHUNK_SIZE;
static const int MAX_VISIBLE_REBUILDS_PER_FRAME = 3;
static const int MAX_INVISIBLE_REBUILDS_PER_FRAME = 1;
float xOld;
float yOld;
float zOld;
float destroyProgress;
LevelRenderer(Minecraft* mc);
~LevelRenderer();
void setLevel(Level* level);
void allChanged();
int render(Mob* player, int layer, float alpha);
void renderDebug(const AABB& b, float a) const;
void renderSky(float alpha);
void renderClouds(float alpha);
void renderEntities(Vec3 cam, Culler* culler, float a);
void renderSameAsLast(int layer, float alpha);
void renderHit(Player* player, const HitResult& h, int mode, /*ItemInstance*/void* inventoryItem, float a);
void renderHitOutline(Player* player, const HitResult& h, int mode, /*ItemInstance*/void* inventoryItem, float a);
void renderHitSelect(Player* player, const HitResult& h, int mode, /*ItemInstance*/void* inventoryItem, float a);
void entityAdded(Entity* entity);
void tick();
bool updateDirtyChunks(Mob* player, bool force);
void setDirty(int x0, int y0, int z0, int x1, int y1, int z1);
void tileChanged(int x, int y, int z);
void setTilesDirty(int x0, int y0, int z0, int x1, int y1, int z1);
void cull(Culler* culler, float a);
void skyColorChanged();
//void addParticle(ParticleType::Id name, float x, float y, float z, float xa, float ya, float za, int data);
void addParticle(const std::string& name, float x, float y, float z, float xa, float ya, float za, int data);
void playSound(const std::string& name, float x, float y, float z, float volume, float pitch);
void takePicture(TripodCamera* cam, Entity* entity);
void levelEvent(Player* source, int type, int x, int y, int z, int data);
std::string gatherStats1();
void render(const AABB& b) const;
void onGraphicsReset();
private:
void generateSky();
int renderChunks(int from, int to, int layer, float alpha);
void resortChunks(int xc, int yc, int zc);
void deleteChunks();
//void checkQueryResults(int from, int to);
__inline int getLinearCoord(int x, int y, int z) {
return (z * yChunks + y) * xChunks + x;
}
int noEntityRenderFrames;
int totalEntities;
int renderedEntities;
int culledEntities;
std::vector<Chunk*> _renderChunks;
int cullStep;
//static const int renderListsLength = 4;
RenderList renderList;//[renderListsLength];
int totalChunks, offscreenChunks, occludedChunks, renderedChunks, emptyChunks;
int chunkFixOffs;
int xMinChunk, yMinChunk, zMinChunk;
int xMaxChunk, yMaxChunk, zMaxChunk;
Level* level;
std::vector<Chunk*> dirtyChunks;
Chunk** chunks;
Chunk** sortedChunks;
int chunksLength;
public:
TileRenderer* tileRenderer;
private:
int xChunks, yChunks, zChunks;
int chunkLists;
Minecraft* mc;
bool occlusionCheck;
int lastViewDistance;
int ticks;
int starList, skyList, darkList;
int numListsOrBuffers;
GLuint* chunkBuffers;
GLuint skyBuffer;
int skyVertexCount;
// /*public*/ std::vector<TileEntity*> renderableTileEntities;
Textures* textures;
// /*private*/ TileRenderer tileRenderer;
// /*private*/ IntBuffer occlusionCheckIds;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__LevelRenderer_H__*/

View File

@@ -0,0 +1,17 @@
#include "RenderChunk.h"
int RenderChunk::runningId = 0;
RenderChunk::RenderChunk() :
vboId(-1),
vertexCount(0)
{
id = ++runningId;
}
RenderChunk::RenderChunk( GLuint vboId_, int vertexCount_ )
: vboId(vboId_),
vertexCount(vertexCount_)
{
id = ++runningId;
}

View File

@@ -0,0 +1,24 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__RenderChunk_H__
#define NET_MINECRAFT_CLIENT_RENDERER__RenderChunk_H__
//package net.minecraft.client.renderer;
#include "gles.h"
#include "../../world/phys/Vec3.h"
class RenderChunk
{
public:
RenderChunk();
RenderChunk(GLuint vboId_, int vertexCount_);
GLuint vboId;
GLsizei vertexCount;
int id;
Vec3 pos;
private:
static int runningId;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__RenderChunk_H__*/

View File

@@ -0,0 +1,23 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__RenderChunkHandler_H__
#define NET_MINECRAFT_CLIENT_RENDERER__RenderChunkHandler_H__
#include <vector>
#include "RenderChunk.h"
typedef std::vector<RenderChunk> ChunkList;
class RenderChunkHandler
{
public:
int vboCount;
ChunkList chunks;
RenderChunkHandler() {
vboCount = Tesselator::getVboCount();
}
void render() {
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__RenderChunkHandler_H__*/

View File

@@ -0,0 +1,96 @@
#include "RenderList.h"
#include "gles.h"
#include "RenderChunk.h"
#include "Tesselator.h"
RenderList::RenderList()
: inited(false),
rendered(false)
{
lists = new int[MAX_NUM_OBJECTS];
rlists = new RenderChunk[MAX_NUM_OBJECTS];
for (int i = 0; i < MAX_NUM_OBJECTS; ++i)
rlists[i].vboId = -1;
}
RenderList::~RenderList() {
delete[] lists;
delete[] rlists;
}
void RenderList::init(float xOff, float yOff, float zOff) {
inited = true;
listIndex = 0;
this->xOff = (float) xOff;
this->yOff = (float) yOff;
this->zOff = (float) zOff;
}
void RenderList::add(int list) {
lists[listIndex] = list;
if (listIndex == MAX_NUM_OBJECTS) /*lists.remaining() == 0)*/ render();
}
void RenderList::addR(const RenderChunk& chunk) {
rlists[listIndex] = chunk;
}
void RenderList::render() {
if (!inited) return;
if (!rendered) {
bufferLimit = listIndex;
listIndex = 0;
rendered = true;
}
if (listIndex < bufferLimit) {
glPushMatrix2();
glTranslatef2(-xOff, -yOff, -zOff);
#ifndef USE_VBO
glCallLists(bufferLimit, GL_UNSIGNED_INT, lists);
#else
renderChunks();
#endif/*!USE_VBO*/
glPopMatrix2();
}
}
void RenderList::renderChunks() {
//glDisableClientState2(GL_NORMAL_ARRAY);
glEnableClientState2(GL_VERTEX_ARRAY);
glEnableClientState2(GL_COLOR_ARRAY);
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
const int Stride = VertexSizeBytes;
for (int i = 0; i < bufferLimit; ++i) {
RenderChunk& rc = rlists[i];
glPushMatrix2();
glTranslatef2(rc.pos.x, rc.pos.y, rc.pos.z);
glBindBuffer2(GL_ARRAY_BUFFER, rc.vboId);
glVertexPointer2 (3, GL_FLOAT, Stride, 0);
glTexCoordPointer2 (2, GL_FLOAT, Stride, (GLvoid*) (3 * 4));
glColorPointer2 (4, GL_UNSIGNED_BYTE, Stride, (GLvoid*) (5 * 4));
glDrawArrays2(GL_TRIANGLES, 0, rc.vertexCount);
glPopMatrix2();
}
glDisableClientState2(GL_VERTEX_ARRAY);
glDisableClientState2(GL_COLOR_ARRAY);
glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
}
void RenderList::clear() {
inited = false;
rendered = false;
}

View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__RenderList_H__
#define NET_MINECRAFT_CLIENT_RENDERER__RenderList_H__
//package net.minecraft.client.renderer;
class RenderChunk;
class RenderList
{
static const int MAX_NUM_OBJECTS = 1024 * 3;
public:
RenderList();
~RenderList();
void init(float xOff, float yOff, float zOff);
void add(int list);
void addR(const RenderChunk& chunk);
__inline void next() { ++listIndex; }
void render();
void renderChunks();
void clear();
float xOff, yOff, zOff;
int* lists;
RenderChunk* rlists;
int listIndex;
bool inited;
bool rendered;
private:
int bufferLimit;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__RenderList_H__*/

View File

@@ -0,0 +1,430 @@
#include "Tesselator.h"
#include <cstdio>
#include <cstring>
#include <algorithm>
Tesselator Tesselator::instance(sizeof(GLfloat) * MAX_FLOATS); // max size in bytes
const int VertexSizeBytes = sizeof(VERTEX);
Tesselator::Tesselator( int size )
: size(size),
vertices(0),
u(0), v(0),
_color(0),
hasColor(false),
hasTexture(false),
hasNormal(false),
p(0),
count(0),
_noColor(false),
mode(0),
xo(0), yo(0), zo(0),
_normal(0),
_sx(1), _sy(1),
tesselating(false),
vboId(-1),
vboCounts(128),
totalSize(0),
accessMode(ACCESS_STATIC),
maxVertices(size / sizeof(VERTEX)),
_voidBeginEnd(false)
{
vboIds = new GLuint[vboCounts];
_varray = new VERTEX[maxVertices];
char* a = (char*)&_varray[0];
char* b = (char*)&_varray[1];
LOGI("Vsize: %lu, %d\n", sizeof(VERTEX), (b-a));
}
Tesselator::~Tesselator()
{
delete[] vboIds;
delete[] _varray;
}
void Tesselator::init()
{
#ifndef STANDALONE_SERVER
glGenBuffers2(vboCounts, vboIds);
#endif
}
void Tesselator::clear()
{
accessMode = ACCESS_STATIC;
vertices = 0;
count = 0;
p = 0;
_voidBeginEnd = false;
}
int Tesselator::getVboCount() {
return vboCounts;
}
RenderChunk Tesselator::end( bool useMine, int bufferId )
{
#ifndef STANDALONE_SERVER
//if (!tesselating) throw /*new*/ IllegalStateException("Not tesselating!");
if (!tesselating)
LOGI("not tesselating!\n");
if (!tesselating || _voidBeginEnd) return RenderChunk();
tesselating = false;
const int o_vertices = vertices;
if (vertices > 0) {
if (++vboId >= vboCounts)
vboId = 0;
#ifdef USE_VBO
// Using VBO, use default buffer id only if we don't send in any
if (!useMine) {
bufferId = vboIds[vboId];
}
#else
// Not using VBO - always use the next buffer object
bufferId = vboIds[vboId];
#endif
int access = GL_STATIC_DRAW;//(accessMode==ACCESS_DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
int bytes = p * sizeof(VERTEX);
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
glBufferData2(GL_ARRAY_BUFFER, bytes, _varray, access); // GL_STREAM_DRAW
totalSize += bytes;
#ifndef USE_VBO
// 0 1 2 3 4 5 6 7
// x y z u v c
if (hasTexture) {
glTexCoordPointer2(2, GL_FLOAT, VertexSizeBytes, (GLvoid*) (3 * 4));
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
}
if (hasColor) {
glColorPointer2(4, GL_UNSIGNED_BYTE, VertexSizeBytes, (GLvoid*) (5 * 4));
glEnableClientState2(GL_COLOR_ARRAY);
}
if (hasNormal) {
glNormalPointer(GL_BYTE, VertexSizeBytes, (GLvoid*) (6 * 4));
glEnableClientState2(GL_NORMAL_ARRAY);
}
glVertexPointer2(3, GL_FLOAT, VertexSizeBytes, 0);
glEnableClientState2(GL_VERTEX_ARRAY);
if (mode == GL_QUADS) {
glDrawArrays2(GL_TRIANGLES, 0, vertices);
} else {
glDrawArrays2(mode, 0, vertices);
}
//printf("drawing %d tris, size %d (%d,%d,%d)\n", vertices, p, hasTexture, hasColor, hasNormal);
glDisableClientState2(GL_VERTEX_ARRAY);
if (hasTexture) glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
if (hasColor) glDisableClientState2(GL_COLOR_ARRAY);
if (hasNormal) glDisableClientState2(GL_NORMAL_ARRAY);
#endif /*!USE_VBO*/
}
clear();
RenderChunk out(bufferId, o_vertices);
//map.insert( std::make_pair(bufferId, out.id) );
return out;
#else
return RenderChunk();
#endif
}
void Tesselator::begin( int mode )
{
if (tesselating || _voidBeginEnd) {
if (tesselating && !_voidBeginEnd)
LOGI("already tesselating!\n");
return;
}
//if (tesselating) {
// throw /*new*/ IllegalStateException("Already tesselating!");
//}
tesselating = true;
clear();
this->mode = mode;
hasNormal = false;
hasColor = false;
hasTexture = false;
_noColor = false;
}
void Tesselator::begin()
{
begin(GL_QUADS);
}
void Tesselator::tex( float u, float v )
{
hasTexture = true;
this->u = u;
this->v = v;
}
int Tesselator::getColor() {
return _color;
}
void Tesselator::color( float r, float g, float b )
{
color((int) (r * 255), (int) (g * 255), (int) (b * 255));
}
void Tesselator::color( float r, float g, float b, float a )
{
color((int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255));
}
void Tesselator::color( int r, int g, int b )
{
color(r, g, b, 255);
}
void Tesselator::color( int r, int g, int b, int a )
{
if (_noColor) return;
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (a > 255) a = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
if (a < 0) a = 0;
hasColor = true;
//if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
if (true) {
_color = (a << 24) | (b << 16) | (g << 8) | (r);
} else {
_color = (r << 24) | (g << 16) | (b << 8) | (a);
}
}
void Tesselator::color( char r, char g, char b )
{
color(r & 0xff, g & 0xff, b & 0xff);
}
void Tesselator::color( int c )
{
int r = ((c >> 16) & 255);
int g = ((c >> 8) & 255);
int b = ((c) & 255);
color(r, g, b);
}
//@note: doesn't care about endianess
void Tesselator::colorABGR( int c )
{
if (_noColor) return;
hasColor = true;
_color = c;
}
void Tesselator::color( int c, int alpha )
{
int r = ((c >> 16) & 255);
int g = ((c >> 8) & 255);
int b = ((c) & 255);
color(r, g, b, alpha);
}
void Tesselator::vertexUV( float x, float y, float z, float u, float v )
{
tex(u, v);
vertex(x, y, z);
}
void Tesselator::scale2d(float sx, float sy) {
_sx *= sx;
_sy *= sy;
}
void Tesselator::resetScale() {
_sx = _sy = 1;
}
void Tesselator::vertex( float x, float y, float z )
{
#ifndef STANDALONE_SERVER
count++;
if (mode == GL_QUADS && (count & 3) == 0) {
for (int i = 0; i < 2; i++) {
const int offs = 3 - i;
VERTEX& src = _varray[p - offs];
VERTEX& dst = _varray[p];
if (hasTexture) {
dst.u = src.u;
dst.v = src.v;
}
if (hasColor) {
dst.color = src.color;
}
//if (hasNormal) {
// dst.normal = src.normal;
//}
dst.x = src.x;
dst.y = src.y;
dst.z = src.z;
++vertices;
++p;
}
}
VERTEX& vertex = _varray[p];
if (hasTexture) {
vertex.u = u;
vertex.v = v;
}
if (hasColor) {
vertex.color = _color;
}
//if (hasNormal) {
// vertex.normal = _normal;
//}
vertex.x = _sx * (x + xo);
vertex.y = _sy * (y + yo);
vertex.z = z + zo;
++p;
++vertices;
if ((vertices & 3) == 0 && p >= maxVertices-1) {
for (int i = 0; i < 3; ++i)
printf("Overwriting the vertex buffer! This chunk/entity won't show up\n");
clear();
}
#endif
}
void Tesselator::noColor()
{
_noColor = true;
}
void Tesselator::setAccessMode(int mode)
{
accessMode = mode;
}
void Tesselator::normal( float x, float y, float z )
{
static int _warn_t = 0;
if ((++_warn_t & 32767) == 1)
LOGI("WARNING: Can't use normals (Tesselator::normal)\n");
return;
if (!tesselating) printf("But..");
hasNormal = true;
char xx = (char) (x * 128);
char yy = (char) (y * 127);
char zz = (char) (z * 127);
_normal = xx | (yy << 8) | (zz << 16);
}
void Tesselator::offset( float xo, float yo, float zo ) {
this->xo = xo;
this->yo = yo;
this->zo = zo;
}
void Tesselator::addOffset( float x, float y, float z ) {
xo += x;
yo += y;
zo += z;
}
void Tesselator::offset( const Vec3& v ) {
xo = v.x;
yo = v.y;
zo = v.z;
}
void Tesselator::addOffset( const Vec3& v ) {
xo += v.x;
yo += v.y;
zo += v.z;
}
void Tesselator::draw()
{
#ifndef STANDALONE_SERVER
if (!tesselating)
LOGI("not (draw) tesselating!\n");
if (!tesselating || _voidBeginEnd)
return;
tesselating = false;
if (vertices > 0) {
if (++vboId >= vboCounts)
vboId = 0;
int bufferId = vboIds[vboId];
int access = GL_DYNAMIC_DRAW;//(accessMode==ACCESS_DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
int bytes = p * sizeof(VERTEX);
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
glBufferData2(GL_ARRAY_BUFFER, bytes, _varray, access); // GL_STREAM_DRAW
if (hasTexture) {
glTexCoordPointer2(2, GL_FLOAT, VertexSizeBytes, (GLvoid*) (3 * 4));
//glTexCoordPointer2(2, GL_FLOAT, VertexSizeBytes, (GLvoid*) &_varray->u);
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
}
if (hasColor) {
glColorPointer2(4, GL_UNSIGNED_BYTE, VertexSizeBytes, (GLvoid*) (5 * 4));
//glColorPointer2(4, GL_UNSIGNED_BYTE, VertexSizeBytes, (GLvoid*) &_varray->color);
glEnableClientState2(GL_COLOR_ARRAY);
}
//if (hasNormal) {
// glNormalPointer(GL_BYTE, VertexSizeBytes, (GLvoid*) (6 * 4));
// glEnableClientState2(GL_NORMAL_ARRAY);
//}
//glVertexPointer2(3, GL_FLOAT, VertexSizeBytes, (GLvoid*)&_varray);
glVertexPointer2(3, GL_FLOAT, VertexSizeBytes, 0);
glEnableClientState2(GL_VERTEX_ARRAY);
if (mode == GL_QUADS) {
glDrawArrays2(GL_TRIANGLES, 0, vertices);
} else {
glDrawArrays2(mode, 0, vertices);
}
glDisableClientState2(GL_VERTEX_ARRAY);
if (hasTexture) glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
if (hasColor) glDisableClientState2(GL_COLOR_ARRAY);
//if (hasNormal) glDisableClientState2(GL_NORMAL_ARRAY);
}
clear();
#endif
}
void Tesselator::voidBeginAndEndCalls(bool doVoid) {
_voidBeginEnd = doVoid;
}
void Tesselator::enableColor() {
_noColor = false;
}

130
src/client/renderer/Tesselator.h Executable file
View File

@@ -0,0 +1,130 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__Tesselator_H__
#define NET_MINECRAFT_CLIENT_RENDERER__Tesselator_H__
//package net.minecraft.client.renderer;
#include <map>
#include "RenderChunk.h"
#include "gles.h"
#include "VertecDecl.h"
extern const int VertexSizeBytes;
typedef VertexDeclPTC VERTEX;
typedef std::map<GLuint, GLsizei> IntGLMap;
class Tesselator
{
static const int MAX_MEMORY_USE = 16 * 1024 * 1024;
static const int MAX_FLOATS = MAX_MEMORY_USE / 4 / 2;
Tesselator(int size);
public:
static const int ACCESS_DYNAMIC = 1;
static const int ACCESS_STATIC = 2;
static Tesselator instance;
~Tesselator();
void init();
void clear();
void begin();
void begin(int mode);
void draw();
RenderChunk end(bool useMine, int bufferId);
void color(int c);
void color(int c, int alpha);
void color(float r, float g, float b);
void color(float r, float g, float b, float a);
void color(int r, int g, int b);
void color(int r, int g, int b, int a);
void color(char r, char g, char b);
void colorABGR( int c );
void normal(float x, float y, float z);
void voidBeginAndEndCalls(bool doVoid);
void tex(float u, float v);
void vertex(float x, float y, float z);
void vertexUV(float x, float y, float z, float u, float v);
void scale2d(float x, float y);
void resetScale();
void noColor();
void enableColor();
private:
void setAccessMode(int mode);
public:
void offset(float xo, float yo, float zo);
void offset(const Vec3& v);
void addOffset(float x, float y, float z);
void addOffset(const Vec3& v);
int getVboCount();
int getColor();
__inline void beginOverride() {
begin();
voidBeginAndEndCalls(true);
}
__inline void endOverrideAndDraw() {
voidBeginAndEndCalls(false);
draw();
}
__inline bool isOverridden() {
return _voidBeginEnd;
}
__inline RenderChunk endOverride(int bufferId) {
voidBeginAndEndCalls(false);
return end(true, bufferId);
}
private:
Tesselator(const Tesselator& rhs) {}
Tesselator& operator=(const Tesselator& rhs) { return *this; }
VERTEX* _varray;
int vertices;
float xo, yo, zo;
float u, v;
unsigned int _color;
int _normal;
float _sx, _sy;
bool hasColor;
bool hasTexture;
bool hasNormal;
bool _noColor;
bool _voidBeginEnd;
int p;
int count;
bool tesselating;
bool vboMode;
int vboCounts;
int vboId;
GLuint* vboIds;
int size;
int totalSize;
int maxVertices;
int mode;
int accessMode;
IntGLMap map;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__Tesselator_H__*/

View File

@@ -0,0 +1,37 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__TextureData_H__
#define NET_MINECRAFT_CLIENT_RENDERER__TextureData_H__
enum TextureFormat
{
TEXF_UNCOMPRESSED_8888,
TEXF_UNCOMPRESSED_565,
TEXF_UNCOMPRESSED_5551,
TEXF_UNCOMPRESSED_4444,
TEXF_COMPRESSED_PVRTC_565,
TEXF_COMPRESSED_PVRTC_5551,
TEXF_COMPRESSED_PVRTC_4444
};
typedef struct TextureData {
TextureData()
: w(0),
h(0),
data(NULL),
numBytes(0),
transparent(true),
memoryHandledExternally(false),
format(TEXF_UNCOMPRESSED_8888),
identifier(-1)
{}
int w, h;
unsigned char* data;
int numBytes;
bool transparent;
bool memoryHandledExternally;
TextureFormat format;
int identifier;
} TextureData;
#endif /*NET_MINECRAFT_CLIENT_RENDERER__Textures_H__*/

358
src/client/renderer/Textures.cpp Executable file
View File

@@ -0,0 +1,358 @@
#include "Textures.h"
#include "TextureData.h"
#include "ptexture/DynamicTexture.h"
#include "../Options.h"
#include "../../platform/time.h"
#include "../../AppPlatform.h"
/*static*/ int Textures::textureChanges = 0;
/*static*/ bool Textures::MIPMAP = false;
Textures::Textures( Options* options_, AppPlatform* platform_ )
: clamp(false),
blur(false),
options(options_),
platform(platform_),
lastBoundTexture(Textures::InvalidId)
{
}
Textures::~Textures()
{
clear();
for (unsigned int i = 0; i < dynamicTextures.size(); ++i)
delete dynamicTextures[i];
}
void Textures::clear()
{
for (TextureMap::iterator it = idMap.begin(); it != idMap.end(); ++it) {
if (it->second != Textures::InvalidId)
glDeleteTextures(1, &it->second);
}
for (TextureImageMap::iterator it = loadedImages.begin(); it != loadedImages.end(); ++it) {
if (!(it->second).memoryHandledExternally)
delete[] (it->second).data;
}
idMap.clear();
loadedImages.clear();
lastBoundTexture = Textures::InvalidId;
}
TextureId Textures::loadAndBindTexture( const std::string& resourceName )
{
//static Stopwatch t;
//t.start();
TextureId id = loadTexture(resourceName);
//t.stop();
if (id != Textures::InvalidId)
bind(id);
//t.printEvery(1000);
return id;
}
TextureId Textures::loadTexture( const std::string& resourceName, bool inTextureFolder /* = true */ )
{
TextureMap::iterator it = idMap.find(resourceName);
if (it != idMap.end())
return it->second;
TextureData texdata = platform->loadTexture(resourceName, inTextureFolder);
if (texdata.data)
return assignTexture(resourceName, texdata);
else if (texdata.identifier != InvalidId) {
//LOGI("Adding id: %d for %s\n", texdata.identifier, resourceName.c_str());
idMap.insert(std::make_pair(resourceName, texdata.identifier));
}
else {
idMap.insert(std::make_pair(resourceName, Textures::InvalidId));
//loadedImages.insert(std::make_pair(InvalidId, texdata));
}
return Textures::InvalidId;
}
TextureId Textures::assignTexture( const std::string& resourceName, const TextureData& img )
{
TextureId id;
glGenTextures(1, &id);
bind(id);
if (MIPMAP) {
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (blur) {
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (clamp) {
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
switch (img.format)
{
case TEXF_COMPRESSED_PVRTC_4444:
case TEXF_COMPRESSED_PVRTC_565:
case TEXF_COMPRESSED_PVRTC_5551:
{
#if defined(__APPLE__)
int fmt = img.transparent? GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, img.w, img.h, 0, img.numBytes, img.data);
#endif
break;
}
default:
const GLint mode = img.transparent? GL_RGBA : GL_RGB;
if (img.format == TEXF_UNCOMPRESSED_565) {
glTexImage2D2(GL_TEXTURE_2D, 0, mode, img.w, img.h, 0, mode, GL_UNSIGNED_SHORT_5_6_5, img.data);
}
else if (img.format == TEXF_UNCOMPRESSED_4444) {
glTexImage2D2(GL_TEXTURE_2D, 0, mode, img.w, img.h, 0, mode, GL_UNSIGNED_SHORT_4_4_4_4, img.data);
}
else if (img.format == TEXF_UNCOMPRESSED_5551) {
glTexImage2D2(GL_TEXTURE_2D, 0, mode, img.w, img.h, 0, mode, GL_UNSIGNED_SHORT_5_5_5_1, img.data);
}
else {
glTexImage2D2(GL_TEXTURE_2D, 0, mode, img.w, img.h, 0, mode, GL_UNSIGNED_BYTE, img.data);
}
break;
}
//LOGI("Adding id: %d to map\n", id);
idMap.insert(std::make_pair(resourceName, id));
loadedImages.insert(std::make_pair(id, img));
return id;
}
const TextureData* Textures::getTemporaryTextureData( TextureId id )
{
TextureImageMap::iterator it = loadedImages.find(id);
if (it == loadedImages.end())
return NULL;
return &it->second;
}
void Textures::tick(bool uploadToGraphicsCard)
{
for (unsigned int i = 0; i < dynamicTextures.size(); ++i ) {
DynamicTexture* tex = dynamicTextures[i];
tex->tick();
if (uploadToGraphicsCard) {
tex->bindTexture(this);
for (int xx = 0; xx < tex->replicate; xx++)
for (int yy = 0; yy < tex->replicate; yy++) {
glTexSubImage2D2(GL_TEXTURE_2D, 0, tex->tex % 16 * 16 + xx * 16,
tex->tex / 16 * 16 + yy * 16, 16, 16,
GL_RGBA, GL_UNSIGNED_BYTE, tex->pixels);
}
}
}
}
void Textures::addDynamicTexture( DynamicTexture* dynamicTexture )
{
dynamicTextures.push_back(dynamicTexture);
dynamicTexture->tick();
}
void Textures::reloadAll()
{
//TexturePack skin = skins.selected;
//for (int id : loadedImages.keySet()) {
// BufferedImage image = loadedImages.get(id);
// loadTexture(image, id);
//}
////for (HttpTexture httpTexture : httpTextures.values()) {
//// httpTexture.isLoaded = false;
////}
//for (std::string name : idMap.keySet()) {
// try {
// BufferedImage image;
// if (name.startsWith("##")) {
// image = makeStrip(readImage(skin.getResource(name.substring(2))));
// } else if (name.startsWith("%clamp%")) {
// clamp = true;
// image = readImage(skin.getResource(name.substring(7)));
// } else if (name.startsWith("%blur%")) {
// blur = true;
// image = readImage(skin.getResource(name.substring(6)));
// } else {
// image = readImage(skin.getResource(name));
// }
// int id = idMap.get(name);
// loadTexture(image, id);
// blur = false;
// clamp = false;
// } catch (IOException e) {
// e.printStackTrace();
// }
//}
}
int Textures::smoothBlend( int c0, int c1 )
{
int a0 = (int) (((c0 & 0xff000000) >> 24)) & 0xff;
int a1 = (int) (((c1 & 0xff000000) >> 24)) & 0xff;
return ((a0 + a1) >> 1 << 24) + (((c0 & 0x00fefefe) + (c1 & 0x00fefefe)) >> 1);
}
int Textures::crispBlend( int c0, int c1 )
{
int a0 = (int) (((c0 & 0xff000000) >> 24)) & 0xff;
int a1 = (int) (((c1 & 0xff000000) >> 24)) & 0xff;
int a = 255;
if (a0 + a1 == 0) {
a0 = 1;
a1 = 1;
a = 0;
}
int r0 = ((c0 >> 16) & 0xff) * a0;
int g0 = ((c0 >> 8) & 0xff) * a0;
int b0 = ((c0) & 0xff) * a0;
int r1 = ((c1 >> 16) & 0xff) * a1;
int g1 = ((c1 >> 8) & 0xff) * a1;
int b1 = ((c1) & 0xff) * a1;
int r = (r0 + r1) / (a0 + a1);
int g = (g0 + g1) / (a0 + a1);
int b = (b0 + b1) / (a0 + a1);
return (a << 24) | (r << 16) | (g << 8) | b;
}
///*public*/ int loadHttpTexture(std::string url, std::string backup) {
// HttpTexture texture = httpTextures.get(url);
// if (texture != NULL) {
// if (texture.loadedImage != NULL && !texture.isLoaded) {
// if (texture.id < 0) {
// texture.id = getTexture(texture.loadedImage);
// } else {
// loadTexture(texture.loadedImage, texture.id);
// }
// texture.isLoaded = true;
// }
// }
// if (texture == NULL || texture.id < 0) {
// if (backup == NULL) return -1;
// return loadTexture(backup);
// }
// return texture.id;
//}
//HttpTexture addHttpTexture(std::string url, HttpTextureProcessor processor) {
// HttpTexture texture = httpTextures.get(url);
// if (texture == NULL) {
// httpTextures.put(url, /*new*/ HttpTexture(url, processor));
// } else {
// texture.count++;
// }
// return texture;
//}
//void removeHttpTexture(std::string url) {
// HttpTexture texture = httpTextures.get(url);
// if (texture != NULL) {
// texture.count--;
// if (texture.count == 0) {
// if (texture.id >= 0) releaseTexture(texture.id);
// httpTextures.remove(url);
// }
// }
//}
//void tick() {
// for (int i = 0; i < dynamicTextures.size(); i++) {
// DynamicTexture dynamicTexture = dynamicTextures.get(i);
// dynamicTexture.anaglyph3d = options.anaglyph3d;
// dynamicTexture.tick();
//
// pixels.clear();
// pixels.put(dynamicTexture.pixels);
// pixels.position(0).limit(dynamicTexture.pixels.length);
//
// dynamicTexture.bindTexture(this);
//
// for (int xx = 0; xx < dynamicTexture.replicate; xx++)
// for (int yy = 0; yy < dynamicTexture.replicate; yy++) {
//
// glTexSubImage2D2(GL_TEXTURE_2D, 0, dynamicTexture.tex % 16 * 16 + xx * 16, dynamicTexture.tex / 16 * 16 + yy * 16, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// if (MIPMAP) {
// for (int level = 1; level <= 4; level++) {
// int os = 16 >> (level - 1);
// int s = 16 >> level;
//
// for (int x = 0; x < s; x++)
// for (int y = 0; y < s; y++) {
// int c0 = pixels.getInt(((x * 2 + 0) + (y * 2 + 0) * os) * 4);
// int c1 = pixels.getInt(((x * 2 + 1) + (y * 2 + 0) * os) * 4);
// int c2 = pixels.getInt(((x * 2 + 1) + (y * 2 + 1) * os) * 4);
// int c3 = pixels.getInt(((x * 2 + 0) + (y * 2 + 1) * os) * 4);
// int col = smoothBlend(smoothBlend(c0, c1), smoothBlend(c2, c3));
// pixels.putInt((x + y * s) * 4, col);
// }
// glTexSubImage2D2(GL_TEXTURE_2D, level, dynamicTexture.tex % 16 * s, dynamicTexture.tex / 16 * s, s, s, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// }
// }
// }
// }
//
// for (int i = 0; i < dynamicTextures.size(); i++) {
// DynamicTexture dynamicTexture = dynamicTextures.get(i);
//
// if (dynamicTexture.copyTo > 0) {
// pixels.clear();
// pixels.put(dynamicTexture.pixels);
// pixels.position(0).limit(dynamicTexture.pixels.length);
// glBindTexture2(GL_TEXTURE_2D, dynamicTexture.copyTo);
// glTexSubImage2D2(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// if (MIPMAP) {
// for (int level = 1; level <= 4; level++) {
// int os = 16 >> (level - 1);
// int s = 16 >> level;
//
// for (int x = 0; x < s; x++)
// for (int y = 0; y < s; y++) {
// int c0 = pixels.getInt(((x * 2 + 0) + (y * 2 + 0) * os) * 4);
// int c1 = pixels.getInt(((x * 2 + 1) + (y * 2 + 0) * os) * 4);
// int c2 = pixels.getInt(((x * 2 + 1) + (y * 2 + 1) * os) * 4);
// int c3 = pixels.getInt(((x * 2 + 0) + (y * 2 + 1) * os) * 4);
// int col = smoothBlend(smoothBlend(c0, c1), smoothBlend(c2, c3));
// pixels.putInt((x + y * s) * 4, col);
// }
// glTexSubImage2D2(GL_TEXTURE_2D, level, 0, 0, s, s, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// }
// }
// }
// }
//}
// void releaseTexture(int id) {
// loadedImages.erase(id);
// glDeleteTextures(1, (const GLuint*)&id);
// }

77
src/client/renderer/Textures.h Executable file
View File

@@ -0,0 +1,77 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__Textures_H__
#define NET_MINECRAFT_CLIENT_RENDERER__Textures_H__
//package net.minecraft.client.renderer;
#include <string>
#include <map>
#include <utility>
#include "gles.h"
#include "TextureData.h"
class DynamicTexture;
class Options;
class AppPlatform;
typedef GLuint TextureId;
typedef std::map<std::string, TextureId> TextureMap;
typedef std::map<TextureId, TextureData> TextureImageMap;
//@todo: Should probably delete the data buffers with image data
// after we've created an OpenGL-texture, and rewrite the
// getTemporaryTextureData() to actually load from file IF
// it's only read ~once anyway.
class Textures
{
public:
Textures(Options* options_, AppPlatform* platform_);
~Textures();
void addDynamicTexture(DynamicTexture* dynamicTexture);
__inline void bind(TextureId id) {
if (id != Textures::InvalidId && lastBoundTexture != id) {
glBindTexture2(GL_TEXTURE_2D, id);
lastBoundTexture = id;
++textureChanges;
} else if (id == Textures::InvalidId){
LOGI("invalidId!\n");
}
}
TextureId loadTexture(const std::string& resourceName, bool inTextureFolder = true);
TextureId loadAndBindTexture(const std::string& resourceName);
TextureId assignTexture(const std::string& resourceName, const TextureData& img);
const TextureData* getTemporaryTextureData(TextureId id);
void tick(bool uploadToGraphicsCard);
void clear();
void reloadAll();
__inline static bool isTextureIdValid(TextureId t) { return t != Textures::InvalidId; }
private:
int smoothBlend(int c0, int c1);
int crispBlend(int c0, int c1);
public:
static bool MIPMAP;
static int textureChanges;
static const TextureId InvalidId = -1;
private:
TextureMap idMap;
TextureImageMap loadedImages;
Options* options;
AppPlatform* platform;
bool clamp;
bool blur;
int lastBoundTexture;
std::vector<DynamicTexture*> dynamicTextures;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__Textures_H__*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,85 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__TileRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER__TileRenderer_H__
//package net.minecraft.client.renderer;
class Tile;
class FenceTile;
class FenceGateTile;
class ThinFenceTile;
class StairTile;
class LevelSource;
class Material;
class TileRenderer
{
public:
TileRenderer(LevelSource* level = 0);
void tesselateInWorld(Tile* tile, int x, int y, int z, int fixedTexture);
bool tesselateInWorld(Tile* tt, int x, int y, int z);
void tesselateInWorldNoCulling(Tile* tile, int x, int y, int z);
bool tesselateTorchInWorld(Tile* tt, int x, int y, int z);
bool tesselateLadderInWorld(Tile* tt, int x, int y, int z);
bool tesselateCactusInWorld(Tile* tt, int x, int y, int z);
bool tesselateCactusInWorld(Tile* tt, int x, int y, int z, float r, float g, float b);
bool tesselateCrossInWorld(Tile* tt, int x, int y, int z);
bool tesselateStemInWorld(Tile* _tt, int x, int y, int z);
bool tesselateWaterInWorld(Tile* tt, int x, int y, int z);
bool tesselateStairsInWorld(StairTile* tt, int x, int y, int z);
bool tesselateDoorInWorld(Tile* tt, int x, int y, int z);
bool tesselateFenceInWorld(FenceTile* tt, int x, int y, int z);
bool tesselateThinFenceInWorld(ThinFenceTile* tt, int x, int y, int z);
bool tesselateFenceGateInWorld(FenceGateTile* tt, int x, int y, int z);
bool tesselateBedInWorld(Tile *tt, int x, int y, int z);
bool tesselateRowInWorld(Tile* tt, int x, int y, int z);
void tesselateTorch(Tile* tt, float x, float y, float z, float xxa, float zza);
void tesselateCrossTexture(Tile* tt, int data, float x, float y, float z);
void tesselateStemTexture(Tile* tt, int data, float h, float x, float y, float z);
void tesselateStemDirTexture(Tile* tt, int data, int dir, float h, float x, float y, float z);
void tesselateRowTexture(Tile* tt, int data, float x, float y, float z);
void renderBlock(Tile* tt, LevelSource* level, int x, int y, int z);
/*public*/
bool tesselateBlockInWorld(Tile* tt, int x, int y, int z);
bool tesselateBlockInWorld(Tile* tt, int x, int y, int z, float r, float g, float b);
bool tesselateBlockInWorldWithAmbienceOcclusion(Tile* tt, int pX, int pY, int pZ, float pBaseRed, float pBaseGreen, float pBaseBlue);
void renderFaceDown(Tile* tt, float x, float y, float z, int tex);
void renderFaceUp(Tile* tt, float x, float y, float z, int tex);
void renderNorth(Tile* tt, float x, float y, float z, int tex);
void renderSouth(Tile* tt, float x, float y, float z, int tex);
void renderWest(Tile* tt, float x, float y, float z, int tex);
void renderEast(Tile* tt, float x, float y, float z, int tex);
void renderTile(Tile* tile, int data);
void renderGuiTile(Tile* tile, int data);
static bool canRender(int renderShape);
private:
float getWaterHeight(int x, int y, int z, const Material* m);
LevelSource* level;
int fixedTexture;
bool xFlipTexture;
bool noCulling;
bool applyAmbienceOcclusion;
float ll000, llx00, ll0y0, ll00z, llX00, ll0Y0, ll00Z;
float llxyz, llxy0, llxyZ, ll0yz, ll0yZ, llXyz, llXy0;
float llXyZ, llxYz, llxY0, llxYZ, ll0Yz, llXYz, llXY0;
float ll0YZ, llXYZ, llx0z, llX0z, llx0Z, llX0Z;
int blsmooth;
float c1r, c2r, c3r, c4r;
float c1g, c2g, c3g, c4g;
float c1b, c2b, c3b, c4b;
bool llTrans0Yz, llTransXY0, llTransxY0, llTrans0YZ;
bool llTransx0z, llTransX0Z, llTransx0Z, llTransX0z;
bool llTrans0yz, llTransXy0, llTransxy0, llTrans0yZ;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER__TileRenderer_H__*/

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__VertexDecl_H__
#define NET_MINECRAFT_CLIENT_RENDERER__VertexDecl_H__
typedef struct VertexDeclPTC
{
GLfloat x, y, z;
GLfloat u, v;
GLuint color;
} VertexDeclPTC;
typedef struct VertexDeclPTCN
{
GLfloat x, y, z;
GLfloat u, v;
GLuint color;
GLuint normal;
} VertexDeclPTCN;
#endif /*#ifndef NET_MINECRAFT_CLIENT_RENDERER__VertexDecl_H__ */

View File

@@ -0,0 +1,29 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__AllowAllCuller_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__AllowAllCuller_H__
//package net.minecraft.client.renderer.culling;
#include "Culler.h"
class AABB;
class AllowAllCuller: public Culler
{
public:
bool isVisible(const AABB& bb) {
return true;
}
bool cubeFullyInFrustum(float x1, float y1, float z1, float x2, float y2, float z2) {
return true;
}
bool cubeInFrustum(float x1, float y1, float z1, float x2, float y2, float z2) {
return true;
}
void prepare(float xOff, float yOff, float zOff) {
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__AllowAllCuller_H__*/

View File

@@ -0,0 +1,22 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__Culler_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__Culler_H__
//package net.minecraft.client.renderer.culling;
class AABB;
class Culler
{
public:
virtual ~Culler() {}
virtual bool isVisible(const AABB& bb) = 0;
virtual bool cubeInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) = 0;
virtual bool cubeFullyInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) = 0;
virtual void prepare(float xOff, float yOff, float zOff) {}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__Culler_H__*/

View File

@@ -0,0 +1,3 @@
#include "Frustum.h"
Frustum Frustum::frustum;

View File

@@ -0,0 +1,163 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__Frustum_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__Frustum_H__
//package net.minecraft.client.renderer.culling;
/* import static org.lwjgl.opengl.GL11.* */
// 1) Stolen and ported to java from the web somewhere.
// 2) ... and then ported back to C++!
//***********************************************************************//
// //
// - "Talk to me like I'm a 3 year old!" Programming Lessons - //
// //
// $Author: DigiBen digiben@gametutorials.com //
// //
// $Program: Frustum Culling //
// //
// $Description: Demonstrates checking if shapes are in view //
// //
// $Date: 8/28/01 //
// //
//***********************************************************************//
//#include "main.h"
#include "FrustumData.h"
#include "../../../util/Mth.h"
#include "../gles.h"
class Frustum: public FrustumData
{
private:
static Frustum frustum;
public:
static FrustumData& getFrustum() {
frustum.calculateFrustum();
return frustum;
}
///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This normalizes a plane (A side) from a given frustum.
/////
///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
private:
void normalizePlane(float frustum[16][16], int side)
{
// Here we calculate the magnitude of the normal to the plane (point A B C)
// Remember that (A, B, C) is that same thing as the normal's (X, Y, Z).
// To calculate magnitude you use the equation: magnitude = sqrt( x^2 + y^2 + z^2)
float invMagnitude = Mth::invSqrt(frustum[side][A] * frustum[side][A] + frustum[side][B] * frustum[side][B] + frustum[side][C] * frustum[side][C]);
// Then we divide the plane's values by it's magnitude.
// This makes it easier to work with.
frustum[side][A] *= invMagnitude;
frustum[side][B] *= invMagnitude;
frustum[side][C] *= invMagnitude;
frustum[side][D] *= invMagnitude;
}
float _proj[16];
float _modl[16];
float _clip[16];
void calculateFrustum()
{
// glGetFloatv() is used to extract information about our OpenGL world.
// Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
// It then stores the matrix into an array of [16].
glGetFloatv(GL_PROJECTION_MATRIX, proj);
// By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
// This also stores it in an array of [16].
glGetFloatv(GL_MODELVIEW_MATRIX, modl);
// Now that we have our modelview and projection matrix, if we combine these 2 matrices,
// it will give us our clipping planes. To combine 2 matrices, we multiply them.
clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12];
clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13];
clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14];
clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15];
clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12];
clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13];
clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14];
clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15];
clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12];
clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13];
clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14];
clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15];
clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12];
clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13];
clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14];
clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15];
// Now we actually want to get the sides of the frustum. To do this we take
// the clipping planes we received above and extract the sides from them.
// This will extract the RIGHT side of the frustum
m_Frustum[RIGHT][A] = clip[3] - clip[0];
m_Frustum[RIGHT][B] = clip[7] - clip[4];
m_Frustum[RIGHT][C] = clip[11] - clip[8];
m_Frustum[RIGHT][D] = clip[15] - clip[12];
// Now that we have a normal (A,B,C) and a distance (D) to the plane,
// we want to normalize that normal and distance.
// Normalize the RIGHT side
normalizePlane(m_Frustum, RIGHT);
// This will extract the LEFT side of the frustum
m_Frustum[LEFT][A] = clip[3] + clip[0];
m_Frustum[LEFT][B] = clip[7] + clip[4];
m_Frustum[LEFT][C] = clip[11] + clip[8];
m_Frustum[LEFT][D] = clip[15] + clip[12];
// Normalize the LEFT side
normalizePlane(m_Frustum, LEFT);
// This will extract the BOTTOM side of the frustum
m_Frustum[BOTTOM][A] = clip[3] + clip[1];
m_Frustum[BOTTOM][B] = clip[7] + clip[5];
m_Frustum[BOTTOM][C] = clip[11] + clip[9];
m_Frustum[BOTTOM][D] = clip[15] + clip[13];
// Normalize the BOTTOM side
normalizePlane(m_Frustum, BOTTOM);
// This will extract the TOP side of the frustum
m_Frustum[TOP][A] = clip[3] - clip[1];
m_Frustum[TOP][B] = clip[7] - clip[5];
m_Frustum[TOP][C] = clip[11] - clip[9];
m_Frustum[TOP][D] = clip[15] - clip[13];
// Normalize the TOP side
normalizePlane(m_Frustum, TOP);
// This will extract the BACK side of the frustum
m_Frustum[BACK][A] = clip[3] - clip[2];
m_Frustum[BACK][B] = clip[7] - clip[6];
m_Frustum[BACK][C] = clip[11] - clip[10];
m_Frustum[BACK][D] = clip[15] - clip[14];
// Normalize the BACK side
normalizePlane(m_Frustum, BACK);
// This will extract the FRONT side of the frustum
m_Frustum[FRONT][A] = clip[3] + clip[2];
m_Frustum[FRONT][B] = clip[7] + clip[6];
m_Frustum[FRONT][C] = clip[11] + clip[10];
m_Frustum[FRONT][D] = clip[15] + clip[14];
// Normalize the FRONT side
normalizePlane(m_Frustum, FRONT);
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__Frustum_H__*/

View File

@@ -0,0 +1,39 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__
//package net.minecraft.client.renderer.culling;
#include "FrustumData.h"
#include "Frustum.h"
class FrustumCuller: public Culler {
private:
FrustumData frustum;
float xOff, yOff, zOff;
public:
FrustumCuller() {
frustum = Frustum::getFrustum();
}
void prepare(float xOff, float yOff, float zOff) {
this->xOff = xOff;
this->yOff = yOff;
this->zOff = zOff;
}
bool cubeFullyInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) {
return frustum.cubeFullyInFrustum(x0 - xOff, y0 - yOff, z0 - zOff, x1 - xOff, y1 - yOff, z1 - zOff);
}
bool cubeInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) {
return frustum.cubeInFrustum(x0 - xOff, y0 - yOff, z0 - zOff, x1 - xOff, y1 - yOff, z1 - zOff);
}
bool isVisible(const AABB& bb) {
return cubeInFrustum(bb.x0, bb.y0, bb.z0, bb.x1, bb.y1, bb.z1);
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__*/

View File

@@ -0,0 +1,97 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumData_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumData_H__
//package net.minecraft.client.renderer.culling;
#include "../../../world/phys/AABB.h"
// We create an enum of the sides so we don't have to call each side 0 or 1.
// This way it makes it more understandable and readable when dealing with frustum sides.
class FrustumData
{
public:
//enum FrustumSide
static const int RIGHT = 0; // The RIGHT side of the frustum
static const int LEFT = 1; // The LEFT side of the frustum
static const int BOTTOM = 2; // The BOTTOM side of the frustum
static const int TOP = 3; // The TOP side of the frustum
static const int BACK = 4; // The BACK side of the frustum
static const int FRONT = 5; // The FRONT side of the frustum
// Like above, instead of saying a number for the ABC and D of the plane, we
// want to be more descriptive.
static const int A = 0; // The X value of the plane's normal
static const int B = 1; // The Y value of the plane's normal
static const int C = 2; // The Z value of the plane's normal
static const int D = 3; // The distance the plane is from the origin
float m_Frustum[16][16];
float proj[16];
float modl[16];
float clip[16];
bool pointInFrustum(float x, float y, float z)
{
for (int i = 0; i < 6; i++)
{
if (m_Frustum[i][A] * x + m_Frustum[i][B] * y + m_Frustum[i][C] * z + m_Frustum[i][D] <= 0)
{
return false;
}
}
return true;
}
bool sphereInFrustum(float x, float y, float z, float radius)
{
for (int i = 0; i < 6; i++)
{
if (m_Frustum[i][A] * x + m_Frustum[i][B] * y + m_Frustum[i][C] * z + m_Frustum[i][D] <= -radius)
{
return false;
}
}
return true;
}
bool cubeFullyInFrustum(float x1, float y1, float z1, float x2, float y2, float z2)
{
for (int i = 0; i < 6; i++)
{
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
}
return true;
}
bool cubeInFrustum(float x1, float y1, float z1, float x2, float y2, float z2)
{
for (int i = 0; i < 6; i++)
{
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
return false;
}
return true;
}
bool isVisible(const AABB& aabb)
{
return cubeInFrustum(aabb.x0, aabb.y0, aabb.z0, aabb.x1, aabb.y1, aabb.z1);
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumData_H__*/

View File

@@ -0,0 +1,172 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__Frustum_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__Frustum_H__
//package net.minecraft.client.renderer.culling;
/* import static org.lwjgl.opengl.GL11.* */
#include "java/nio/FloatBuffer.h"
#include "client/MemoryTracker.h"
// Stolen and ported to java from the web somewhere.
//***********************************************************************//
// //
// - "Talk to me like I'm a 3 year old!" Programming Lessons - //
// //
// $Author: DigiBen digiben@gametutorials.com //
// //
// $Program: Frustum Culling //
// //
// $Description: Demonstrates checking if shapes are in view //
// //
// $Date: 8/28/01 //
// //
//***********************************************************************//
//#include "main.h"
// We create an enum of the sides so we don't have to call each side 0 or 1.
// This way it makes it more understandable and readable when dealing with frustum sides.
/*public*/ class Frustum: public FrustumData
{
/*private*/ static Frustum frustum = /*new*/ Frustum();
/*public*/ static FrustumData getFrustum()
{
frustum.calculateFrustum();
return frustum;
}
///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This normalizes a plane (A side) from a given frustum.
/////
///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/*private*/ void normalizePlane(float[][] frustum, int side)
{
// Here we calculate the magnitude of the normal to the plane (point A B C)
// Remember that (A, B, C) is that same thing as the normal's (X, Y, Z).
// To calculate magnitude you use the equation: magnitude = sqrt( x^2 + y^2 + z^2)
float magnitude = (float) util.Mth.sqrt(frustum[side][A] * frustum[side][A] + frustum[side][B] * frustum[side][B] + frustum[side][C] * frustum[side][C]);
// Then we divide the plane's values by it's magnitude.
// This makes it easier to work with.
frustum[side][A] /= magnitude;
frustum[side][B] /= magnitude;
frustum[side][C] /= magnitude;
frustum[side][D] /= magnitude;
}
/*private*/ FloatBuffer _proj = MemoryTracker.createFloatBuffer(16);
/*private*/ FloatBuffer _modl = MemoryTracker.createFloatBuffer(16);
/*private*/ FloatBuffer _clip = MemoryTracker.createFloatBuffer(16);
/*private*/ void calculateFrustum()
{
_proj.clear();
_modl.clear();
_clip.clear();
// glGetFloatv() is used to extract information about our OpenGL world.
// Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
// It then stores the matrix into an array of [16].
glGetFloat(GL_PROJECTION_MATRIX, _proj);
// By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
// This also stores it in an array of [16].
glGetFloat(GL_MODELVIEW_MATRIX, _modl);
_proj.flip().limit(16);
_proj.get(proj);
_modl.flip().limit(16);
_modl.get(modl);
// Now that we have our modelview and projection matrix, if we combine these 2 matrices,
// it will give us our clipping planes. To combine 2 matrices, we multiply them.
clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12];
clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13];
clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14];
clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15];
clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12];
clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13];
clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14];
clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15];
clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12];
clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13];
clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14];
clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15];
clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12];
clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13];
clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14];
clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15];
// Now we actually want to get the sides of the frustum. To do this we take
// the clipping planes we received above and extract the sides from them.
// This will extract the RIGHT side of the frustum
m_Frustum[RIGHT][A] = clip[3] - clip[0];
m_Frustum[RIGHT][B] = clip[7] - clip[4];
m_Frustum[RIGHT][C] = clip[11] - clip[8];
m_Frustum[RIGHT][D] = clip[15] - clip[12];
// Now that we have a normal (A,B,C) and a distance (D) to the plane,
// we want to normalize that normal and distance.
// Normalize the RIGHT side
normalizePlane(m_Frustum, RIGHT);
// This will extract the LEFT side of the frustum
m_Frustum[LEFT][A] = clip[3] + clip[0];
m_Frustum[LEFT][B] = clip[7] + clip[4];
m_Frustum[LEFT][C] = clip[11] + clip[8];
m_Frustum[LEFT][D] = clip[15] + clip[12];
// Normalize the LEFT side
normalizePlane(m_Frustum, LEFT);
// This will extract the BOTTOM side of the frustum
m_Frustum[BOTTOM][A] = clip[3] + clip[1];
m_Frustum[BOTTOM][B] = clip[7] + clip[5];
m_Frustum[BOTTOM][C] = clip[11] + clip[9];
m_Frustum[BOTTOM][D] = clip[15] + clip[13];
// Normalize the BOTTOM side
normalizePlane(m_Frustum, BOTTOM);
// This will extract the TOP side of the frustum
m_Frustum[TOP][A] = clip[3] - clip[1];
m_Frustum[TOP][B] = clip[7] - clip[5];
m_Frustum[TOP][C] = clip[11] - clip[9];
m_Frustum[TOP][D] = clip[15] - clip[13];
// Normalize the TOP side
normalizePlane(m_Frustum, TOP);
// This will extract the BACK side of the frustum
m_Frustum[BACK][A] = clip[3] - clip[2];
m_Frustum[BACK][B] = clip[7] - clip[6];
m_Frustum[BACK][C] = clip[11] - clip[10];
m_Frustum[BACK][D] = clip[15] - clip[14];
// Normalize the BACK side
normalizePlane(m_Frustum, BACK);
// This will extract the FRONT side of the frustum
m_Frustum[FRONT][A] = clip[3] + clip[2];
m_Frustum[FRONT][B] = clip[7] + clip[6];
m_Frustum[FRONT][C] = clip[11] + clip[10];
m_Frustum[FRONT][D] = clip[15] + clip[14];
// Normalize the FRONT side
normalizePlane(m_Frustum, FRONT);
}
}
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__Frustum_H__*/

View File

@@ -0,0 +1,165 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__
//package net.minecraft.client.renderer.culling;
#include "Culler.h"
#include "../../../world/phys/AABB.h"
class FrustumCuller: public Culler
{
float xOff, yOff, zOff;
float frustum[6][4];
public:
FrustumCuller() {
ExtractFrustum();
}
void prepare(float xOff, float yOff, float zOff) {
this->xOff = xOff;
this->yOff = yOff;
this->zOff = zOff;
}
//bool cubeFullyInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) {
// return frustum.cubeFullyInFrustum(x0 - xOff, y0 - yOff, z0 - zOff, x1 - xOff, y1 - yOff, z1 - zOff);
//}
bool cubeFullyInFrustum( float x0, float y0, float z0, float x1, float y1, float z1 ) {
int c2 = 0;
for( int p = 0; p < 6; p++ ) {
int c = 0;
if( frustum[p][0] * (x0) + frustum[p][1] * (y0) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x1) + frustum[p][1] * (y0) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x0) + frustum[p][1] * (y1) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x1) + frustum[p][1] * (y1) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x0) + frustum[p][1] * (y0) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x1) + frustum[p][1] * (y0) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x0) + frustum[p][1] * (y1) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) c++;
if( frustum[p][0] * (x1) + frustum[p][1] * (y1) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) c++;
if( c == 0 )
return false; // 0
if( c == 8 )
c2++;
}
return c2 == 6; //(c2 == 6) ? 2 : 1;
}
bool isVisible(const AABB& bb) {
printf("cube is : %s\n", bb.toString().c_str());
return cubeInFrustum(bb.x0, bb.y0, bb.z0, bb.x1, bb.y1, bb.z1);
}
bool cubeInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) {
for(int p = 0; p < 6; p++ ) {
if( frustum[p][0] * (x0) + frustum[p][1] * (y0) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x1) + frustum[p][1] * (y0) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x0) + frustum[p][1] * (y1) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x1) + frustum[p][1] * (y1) + frustum[p][2] * (z0) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x0) + frustum[p][1] * (y0) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x1) + frustum[p][1] * (y0) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x0) + frustum[p][1] * (y1) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) continue;
if( frustum[p][0] * (x1) + frustum[p][1] * (y1) + frustum[p][2] * (z1) + frustum[p][3] > 0 ) continue;
return false;
}
return true;
}
private:
void ExtractFrustum() {
float proj[16];
float modl[16];
float clip[16];
float t;
/* Get the current PROJECTION matrix from OpenGL */
glGetFloatv( GL_PROJECTION_MATRIX, proj );
/* Get the current MODELVIEW matrix from OpenGL */
glGetFloatv( GL_MODELVIEW_MATRIX, modl );
/* Combine the two matrices (multiply projection by modelview) */
clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
/* Extract the numbers for the RIGHT plane */
frustum[0][0] = clip[ 3] - clip[ 0];
frustum[0][1] = clip[ 7] - clip[ 4];
frustum[0][2] = clip[11] - clip[ 8];
frustum[0][3] = clip[15] - clip[12];
/* Normalize the result */
t = sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
frustum[0][0] /= t;
frustum[0][1] /= t;
frustum[0][2] /= t;
frustum[0][3] /= t;
/* Extract the numbers for the LEFT plane */
frustum[1][0] = clip[ 3] + clip[ 0];
frustum[1][1] = clip[ 7] + clip[ 4];
frustum[1][2] = clip[11] + clip[ 8];
frustum[1][3] = clip[15] + clip[12];
/* Normalize the result */
t = sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
frustum[1][0] /= t;
frustum[1][1] /= t;
frustum[1][2] /= t;
frustum[1][3] /= t;
/* Extract the BOTTOM plane */
frustum[2][0] = clip[ 3] + clip[ 1];
frustum[2][1] = clip[ 7] + clip[ 5];
frustum[2][2] = clip[11] + clip[ 9];
frustum[2][3] = clip[15] + clip[13];
/* Normalize the result */
t = sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
frustum[2][0] /= t;
frustum[2][1] /= t;
frustum[2][2] /= t;
frustum[2][3] /= t;
/* Extract the TOP plane */
frustum[3][0] = clip[ 3] - clip[ 1];
frustum[3][1] = clip[ 7] - clip[ 5];
frustum[3][2] = clip[11] - clip[ 9];
frustum[3][3] = clip[15] - clip[13];
/* Normalize the result */
t = sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
frustum[3][0] /= t;
frustum[3][1] /= t;
frustum[3][2] /= t;
frustum[3][3] /= t;
/* Extract the FAR plane */
frustum[4][0] = clip[ 3] - clip[ 2];
frustum[4][1] = clip[ 7] - clip[ 6];
frustum[4][2] = clip[11] - clip[10];
frustum[4][3] = clip[15] - clip[14];
/* Normalize the result */
t = sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
frustum[4][0] /= t;
frustum[4][1] /= t;
frustum[4][2] /= t;
frustum[4][3] /= t;
/* Extract the NEAR plane */
frustum[5][0] = clip[ 3] + clip[ 2];
frustum[5][1] = clip[ 7] + clip[ 6];
frustum[5][2] = clip[11] + clip[10];
frustum[5][3] = clip[15] + clip[14];
/* Normalize the result */
t = sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
frustum[5][0] /= t;
frustum[5][1] /= t;
frustum[5][2] /= t;
frustum[5][3] /= t;
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__*/

View File

@@ -0,0 +1,102 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumData_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumData_H__
//package net.minecraft.client.renderer.culling;
#include "world/phys/AABB.h"
/*public*/ class FrustumData
{
//enum FrustumSide
/*public*/ static const int RIGHT = 0; // The RIGHT side of the frustum
/*public*/ static const int LEFT = 1; // The LEFT side of the frustum
/*public*/ static const int BOTTOM = 2; // The BOTTOM side of the frustum
/*public*/ static const int TOP = 3; // The TOP side of the frustum
/*public*/ static const int BACK = 4; // The BACK side of the frustum
/*public*/ static const int FRONT = 5; // The FRONT side of the frustum
// Like above, instead of saying a number for the ABC and D of the plane, we
// want to be more descriptive.
/*public*/ static const int A = 0; // The X value of the plane's normal
/*public*/ static const int B = 1; // The Y value of the plane's normal
/*public*/ static const int C = 2; // The Z value of the plane's normal
/*public*/ static const int D = 3; // The distance the plane is from the origin
/*public*/ float** m_Frustum; // = /*new*/ float[16][16];
/*public*/ float* proj; // = /*new*/ float[16];
/*public*/ float* modl; // = /*new*/ float[16];
/*public*/ float* clip; // = /*new*/ float[16];
/*
/*public*/ FrustumData(float** mFrustum, float* proj, float* modl, float* clip)
{
m_Frustum = mFrustum;
this->proj = proj;
this->modl = modl;
this->clip = clip;
}
/*public*/ bool pointInFrustum(float x, float y, float z)
{
for (int i = 0; i < 6; i++)
{
if (m_Frustum[i][A] * x + m_Frustum[i][B] * y + m_Frustum[i][C] * z + m_Frustum[i][D] <= 0)
{
return false;
}
}
return true;
}
/*public*/ bool sphereInFrustum(float x, float y, float z, float radius)
{
for (int i = 0; i < 6; i++)
{
if (m_Frustum[i][A] * x + m_Frustum[i][B] * y + m_Frustum[i][C] * z + m_Frustum[i][D] <= -radius)
{
return false;
}
}
return true;
}
/*public*/ bool cubeFullyInFrustum(float x1, float y1, float z1, float x2, float y2, float z2)
{
for (int i = 0; i < 6; i++)
{
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
if (!(m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0)) return false;
}
return true;
}
/*public*/ bool cubeInFrustum(float x1, float y1, float z1, float x2, float y2, float z2)
{
for (int i = 0; i < 6; i++)
{
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z1) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y1) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x1) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
if (m_Frustum[i][A] * (x2) + m_Frustum[i][B] * (y2) + m_Frustum[i][C] * (z2) + m_Frustum[i][D] > 0) continue;
return false;
}
return true;
}
/*public*/ bool isVisible(AABB aabb)
{
return cubeInFrustum(aabb.x0, aabb.y0, aabb.z0, aabb.x1, aabb.y1, aabb.z1);
}
}
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumData_H__*/

View File

@@ -0,0 +1,37 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__
#define NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__
//package net.minecraft.client.renderer.culling;
#include "world/phys/AABB.h"
/*public*/ class FrustumCuller: /*implements-interface*/ public Culler {
/*private*/ FrustumData frustum;
/*public*/ FrustumCuller() {
frustum = Frustum.getFrustum();
}
/*private*/ float xOff, yOff, zOff;
/*public*/ void prepare(float xOff, float yOff, float zOff) {
this->xOff = xOff;
this->yOff = yOff;
this->zOff = zOff;
}
/*public*/ bool cubeFullyInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) {
return frustum.cubeFullyInFrustum(x0 - xOff, y0 - yOff, z0 - zOff, x1 - xOff, y1 - yOff, z1 - zOff);
}
/*public*/ bool cubeInFrustum(float x0, float y0, float z0, float x1, float y1, float z1) {
return frustum.cubeInFrustum(x0 - xOff, y0 - yOff, z0 - zOff, x1 - xOff, y1 - yOff, z1 - zOff);
}
/*public*/ bool isVisible(AABB bb) {
return cubeInFrustum(bb.x0, bb.y0, bb.z0, bb.x1, bb.y1, bb.z1);
}
}
#endif /*NET_MINECRAFT_CLIENT_RENDERER_CULLING__FrustumCuller_H__*/

View File

@@ -0,0 +1,63 @@
#include "ArrowRenderer.h"
#include "../Tesselator.h"
#include "../Textures.h"
#include "../gles.h"
#include "../../../world/entity/Entity.h"
#include "../../../world/entity/projectile/Arrow.h"
void ArrowRenderer::render(Entity* entity, float x, float y, float z, float rot, float a) {
bindTexture("item/arrows.png");
Arrow* arrow = (Arrow*) entity;
glPushMatrix2();
glTranslatef(x, y, z);
glRotatef(arrow->yRotO + (arrow->yRot - arrow->yRotO) * a - 90, 0, 1, 0);
glRotatef(arrow->xRotO + (arrow->xRot - arrow->xRotO) * a, 0, 0, 1);
Tesselator& t = Tesselator::instance;
int type = 0;
float u0 = 0 / 32.0f;
float u1 = 16 / 32.0f;
float v0 = (0 + type * 10) / 32.0f;
float v1 = (5 + type * 10) / 32.0f;
float u02 = 0 / 32.0f;
float u12 = 5 / 32.0f;
float v02 = (5 + type * 10) / 32.0f;
float v12 = (10 + type * 10) / 32.0f;
float ss = 0.9f / 16.0f;
float shake = arrow->shakeTime - a;
if (shake > 0) {
float pow = -Mth::sin(shake * 3) * shake;
glRotatef(pow, 0, 0, 1);
}
glRotatef(45, 1, 0, 0);
glScalef(ss, ss, ss);
glTranslatef(-4, 0, 0);
t.begin();
t.vertexUV(-7, -2, -2, u02, v02);
t.vertexUV(-7, -2, +2, u12, v02);
t.vertexUV(-7, +2, +2, u12, v12);
t.vertexUV(-7, +2, -2, u02, v12);
t.vertexUV(-7, +2, -2, u02, v02);
t.vertexUV(-7, +2, +2, u12, v02);
t.vertexUV(-7, -2, +2, u12, v12);
t.vertexUV(-7, -2, -2, u02, v12);
t.draw();
for (int i = 0; i < 4; i++) {
glRotatef(90, 1, 0, 0);
t.begin();
t.vertexUV(-8, -2, 0, u0, v0);
t.vertexUV(+8, -2, 0, u1, v0);
t.vertexUV(+8, +2, 0, u1, v1);
t.vertexUV(-8, +2, 0, u0, v1);
t.endOverrideAndDraw();
}
glPopMatrix2();
}

View File

@@ -0,0 +1,9 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ArrowRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ArrowRenderer_H__
#include "EntityRenderer.h"
class ArrowRenderer : public EntityRenderer {
void render(Entity* arrow, float x, float y, float z, float rot, float a);
};
#endif /* NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ArrowRenderer_H__ */

View File

@@ -0,0 +1,23 @@
#include "ChickenRenderer.h"
#include "../../../util/Mth.h"
#include "../../../world/entity/animal/Chicken.h"
ChickenRenderer::ChickenRenderer( Model* model, float shadow )
: super(model, shadow)
{
}
void ChickenRenderer::render( Entity* mob, float x, float y, float z, float rot, float a )
{
super::render(mob, x, y, z, rot, a);
}
float ChickenRenderer::getBob( Mob* mob_, float a )
{
Chicken* mob = (Chicken*) mob_;
float flap = mob->oFlap+(mob->flap-mob->oFlap)*a;
float flapSpeed = mob->oFlapSpeed+(mob->flapSpeed-mob->oFlapSpeed)*a;
return (Mth::sin(flap)+1)*flapSpeed;
}

View File

@@ -0,0 +1,22 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ChickenRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ChickenRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "MobRenderer.h"
class Mob;
class ChickenRenderer: public MobRenderer
{
typedef MobRenderer super;
public:
ChickenRenderer(Model* model, float shadow);
void render(Entity* mob, float x, float y, float z, float rot, float a);
protected:
float getBob(Mob* mob_, float a);
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ChickenRenderer_H__*/

View File

@@ -0,0 +1,94 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__CreeperRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__CreeperRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "MobRenderer.h"
#include "../../model/CreeperModel.h"
#include "../../model/Model.h"
#include "../../../world/entity/monster/Creeper.h"
#include "../../../util/Mth.h"
class CreeperRenderer: public MobRenderer
{
typedef MobRenderer super;
public:
CreeperRenderer()
: super(new CreeperModel(), 0.5f)
{
}
protected:
void scale(Mob* mob, float a) {
Creeper* creeper = (Creeper*) mob;
float g = creeper->getSwelling(a);
float wobble = 1.0f + Mth::sin(g * 100) * g * 0.01f;
if (g < 0) g = 0;
if (g > 1) g = 1;
g = g * g;
g = g * g;
float s = (1.0f + g * 0.4f) * wobble;
float hs = (1.0f + g * 0.1f) / wobble;
glScalef(s, hs, s);
}
int getOverlayColor(Mob* mob, float br, float a) {
Creeper* creeper = (Creeper*) mob;
float step = creeper->getSwelling(a);
if ((int) (step * 10) % 2 == 0) return 0;
int _a = (int) (step * 0.2f * 255);
if (_a < 0) _a = 0;
if (_a > 255) _a = 255;
int r = 255;
int g = 255;
int b = 255;
return (_a << 24) | (r << 16) | (g << 8) | b;
}
// int prepareArmor(Mob* mob, int layer, float a) {
//Creeper* creeper = (Creeper*) mob;
// if (creeper->isPowered()) {
// if (layer == 1) {
// float time = mob->tickCount + a;
// bindTexture("/armor/power.png");
// glMatrixMode(GL_TEXTURE);
// glLoadIdentity();
// float uo = time * 0.01f;
// float vo = time * 0.01f;
// glTranslatef(uo, vo, 0);
// setArmor(armorModel);
// glMatrixMode(GL_MODELVIEW);
// glEnable(GL_BLEND);
// float br = 0.5f;
// glColor4f2(br, br, br, 1);
// glDisable(GL_LIGHTING);
// glBlendFunc2(GL_ONE, GL_ONE);
// return 1;
// }
// if (layer == 2) {
// glMatrixMode(GL_TEXTURE);
// glLoadIdentity();
// glMatrixMode(GL_MODELVIEW);
// glEnable(GL_LIGHTING);
// glDisable(GL_BLEND);
// }
// }
// return -1;
// }
// int prepareArmorOverlay(Mob* mob, int layer, float a) {
// return -1;
// }
//private:
//Model* armorModel = /*new*/ CreeperModel(2);
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__CreeperRenderer_H__*/

View File

@@ -0,0 +1,194 @@
#include "EntityRenderDispatcher.h"
#include "../../Options.h"
#include "../../../world/entity/player/Player.h"
#include "../../../world/item/Item.h"
#include "../../../world/level/Level.h"
#include "../../../world/level/tile/Tile.h"
#include "../../model/ModelInclude.h"
#include "ItemSpriteRenderer.h"
#include "FallingTileRenderer.h"
#include "HumanoidMobRenderer.h"
#include "ItemRenderer.h"
#include "TntRenderer.h"
#include "TripodCameraRenderer.h"
#include "PigRenderer.h"
#include "MobRenderer.h"
#include "PlayerRenderer.h"
#include "CreeperRenderer.h"
#include "SpiderRenderer.h"
#include "ChickenRenderer.h"
#include "SheepRenderer.h"
#include "ArrowRenderer.h"
#include "PaintingRenderer.h"
/*static*/
EntityRenderDispatcher* EntityRenderDispatcher::instance = NULL;
/*static*/
float EntityRenderDispatcher::xOff = 0,
EntityRenderDispatcher::yOff = 0,
EntityRenderDispatcher::zOff = 0;
EntityRenderDispatcher::EntityRenderDispatcher()
: itemInHandRenderer(NULL)
{
//@note: The Models (model/armor) will be deleted by resp. MobRenderer
assign( ER_ITEM_RENDERER, new ItemRenderer());
assign( ER_HUMANOID_RENDERER, new HumanoidMobRenderer(new HumanoidModel(), 0));
assign( ER_PIG_RENDERER, new PigRenderer(new PigModel(), NULL/*new PigModel(0.5f)*/, 0));
assign( ER_COW_RENDERER, new MobRenderer(new CowModel(), 0));
assign( ER_CHICKEN_RENDERER, new ChickenRenderer( new ChickenModel(), 0));
assign( ER_SHEEP_RENDERER, new SheepRenderer(new SheepModel(), new SheepFurModel(), 0));
assign( ER_SKELETON_RENDERER, new HumanoidMobRenderer(new SkeletonModel(), 0.5f));
assign( ER_ZOMBIE_RENDERER, new HumanoidMobRenderer(new ZombieModel(), 0.5f));
assign( ER_CREEPER_RENDERER, new CreeperRenderer());
assign( ER_SPIDER_RENDERER, new SpiderRenderer());
assign( ER_TNT_RENDERER, new TntRenderer());
assign( ER_ARROW_RENDERER, new ArrowRenderer());
assign( ER_PLAYER_RENDERER, new PlayerRenderer(new HumanoidModel(), 0));
assign( ER_THROWNEGG_RENDERER, new ItemSpriteRenderer(Item::egg->getIcon(0)));
assign( ER_SNOWBALL_RENDERER, new ItemSpriteRenderer(Item::snowBall->getIcon(0)));
assign( ER_PAINTING_RENDERER, new PaintingRenderer());
assign( ER_FALLINGTILE_RENDERER,new FallingTileRenderer());
for (RendererIterator it = _renderers.begin(); it != _renderers.end(); ++it) {
it->second->init(this);
}
}
void EntityRenderDispatcher::destroy()
{
if (instance) {
delete instance;
instance = NULL;
}
}
EntityRenderDispatcher* EntityRenderDispatcher::getInstance()
{
if (!instance)
instance = new EntityRenderDispatcher();
return instance;
}
EntityRenderDispatcher::~EntityRenderDispatcher()
{
std::set<EntityRenderer*> destroyed;
for (RendererCIterator cit = _renderers.begin(); cit != _renderers.end(); ++cit) {
if (destroyed.find(cit->second) == destroyed.end()) {
destroyed.insert(cit->second);
delete cit->second;
}
}
}
void EntityRenderDispatcher::prepare( Level* level, Font* font, Mob* player, Options* options, float a )
{
this->level = level;
this->options = options;
this->cameraEntity = player;
this->_font = font;
if(player->isSleeping()) {
int t = level->getTile(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
if (t == Tile::bed->id) {
int data = level->getData(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
int direction = data & 3;
playerRotY = float(direction * 90 + 180);
playerRotX = 0;
}
}
else {
playerRotY = player->yRotO + (player->yRot - player->yRotO) * a;
playerRotX = player->xRotO + (player->xRot - player->xRotO) * a;
}
xPlayer = player->xOld + (player->x - player->xOld) * a;
yPlayer = player->yOld + (player->y - player->yOld) * a;
zPlayer = player->zOld + (player->z - player->zOld) * a;
}
void EntityRenderDispatcher::render( Entity* entity, float a )
{
float x = entity->xOld + (entity->x - entity->xOld) * a;
float y = entity->yOld + (entity->y - entity->yOld) * a;
float z = entity->zOld + (entity->z - entity->zOld) * a;
float r = entity->yRotO + (entity->yRot - entity->yRotO) * a;
float br = entity->getBrightness(a);
glColor4f2(br, br, br, 1);
render(entity, x - xOff, y - yOff, z - zOff, r, a);
}
void EntityRenderDispatcher::render( Entity* entity, float x, float y, float z, float rot, float a )
{
EntityRenderer* renderer = getRenderer(entity);
if (renderer != NULL) {
renderer->render(entity, x, y, z, rot, a);
//renderer->postRender(entity, x, y, z, rot, a);
}
}
EntityRenderer* EntityRenderDispatcher::getRenderer( Entity* entity )
{
EntityRendererId rendererId = entity->entityRendererId;
if (rendererId == ER_QUERY_RENDERER)
rendererId = entity->queryEntityRenderer();
return getRenderer(rendererId);
}
EntityRenderer* EntityRenderDispatcher::getRenderer( EntityRendererId rendererId )
{
EntityRenderer* renderer = NULL;
RendererCIterator cit = _renderers.find(rendererId);
if (cit != _renderers.end()) {
renderer = cit->second;
}
return renderer;
}
void EntityRenderDispatcher::setLevel( Level* level )
{
this->level = level;
}
void EntityRenderDispatcher::setMinecraft( Minecraft* minecraft )
{
this->minecraft = minecraft;
}
float EntityRenderDispatcher::distanceToSqr( float x, float y, float z )
{
float xd = x - xPlayer;
float yd = y - yPlayer;
float zd = z - zPlayer;
return xd * xd + yd * yd + zd * zd;
}
Font* EntityRenderDispatcher::getFont()
{
return _font;
}
void EntityRenderDispatcher::onGraphicsReset()
{
for (RendererIterator it = _renderers.begin(); it != _renderers.end(); ++it) {
it->second->onGraphicsReset();
}
}
void EntityRenderDispatcher::assign( EntityRendererId id, EntityRenderer* renderer )
{
_renderers.insert(std::make_pair(id, renderer));
}

View File

@@ -0,0 +1,76 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__EntityRenderDispatcher_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__EntityRenderDispatcher_H__
//package net.minecraft.client.renderer.entity;
#include <map>
#include "../../../world/entity/EntityRendererId.h"
class EntityRenderer;
class Level;
class Font;
class Textures;
class ItemInHandRenderer;
class Minecraft;
class Textures;
class Options;
class Entity;
class Mob;
class EntityRenderDispatcher
{
typedef std::map<EntityRendererId, EntityRenderer*> RendererMap;
typedef RendererMap::iterator RendererIterator;
typedef RendererMap::const_iterator RendererCIterator;
public:
EntityRenderDispatcher();
~EntityRenderDispatcher();
static EntityRenderDispatcher* getInstance();
static void destroy();
void prepare(Level* level, Font* font, Mob* player, Options* options, float a);
void render(Entity* entity, float a);
void render(Entity* entity, float x, float y, float z, float rot, float a);
EntityRenderer* getRenderer( Entity* entity );
EntityRenderer* getRenderer( EntityRendererId rendererId );
void setLevel(Level* level);
void setMinecraft(Minecraft* minecraft);
float distanceToSqr(float x, float y, float z);
Font* getFont();
void onGraphicsReset();
private:
void assign(EntityRendererId id, EntityRenderer* renderer);
public:
ItemInHandRenderer* itemInHandRenderer;
//TripodCameraRenderer tripodCameraRenderer;
static float xOff, yOff, zOff;
Textures* textures;
Level* level;
Minecraft* minecraft;
Mob* cameraEntity;
float playerRotY;
float playerRotX;
Options* options;
float xPlayer, yPlayer, zPlayer;
private:
static EntityRenderDispatcher* instance;
Font* _font;
// For onGraphicsReset etc
RendererMap _renderers;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__EntityRenderDispatcher_H__*/

View File

@@ -0,0 +1,249 @@
#include "EntityRenderer.h"
#include "../Tesselator.h"
#include "../Textures.h"
#include "../gles.h"
#include "../../../world/phys/AABB.h"
#include "EntityRenderDispatcher.h"
EntityRenderDispatcher* EntityRenderer::entityRenderDispatcher = NULL;
EntityRenderer::EntityRenderer()
: shadowRadius(0),
shadowStrength(1.0f)
{}
void EntityRenderer::bindTexture(const std::string& resourceName) {
entityRenderDispatcher->textures->loadAndBindTexture(resourceName);
}
//bool bindTexture(std::string urlTexture, std::string backupTexture) {
// Textures t = entityRenderDispatcher.textures;
// int id = t.loadHttpTexture(urlTexture, backupTexture);
// if (id >= 0) {
// t.bind(id);
// return true;
// } else {
// return false;
// }
//}
/*static*/
void EntityRenderer::render(const AABB& bb, float xo, float yo, float zo) {
glDisable2(GL_TEXTURE_2D);
Tesselator& t = Tesselator::instance;
glColor4f2(1, 1, 1, 1);
t.begin();
t.offset(xo, yo, zo);
//t.normal(0, 0, -1);
t.vertex(bb.x0, bb.y1, bb.z0);
t.vertex(bb.x1, bb.y1, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z0);
t.vertex(bb.x0, bb.y0, bb.z0);
//t.normal(0, 0, 1);
t.vertex(bb.x0, bb.y0, bb.z1);
t.vertex(bb.x1, bb.y0, bb.z1);
t.vertex(bb.x1, bb.y1, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z1);
//t.normal(0, -1, 0);
t.vertex(bb.x0, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z1);
t.vertex(bb.x0, bb.y0, bb.z1);
//t.normal(0, 1, 0);
t.vertex(bb.x0, bb.y1, bb.z1);
t.vertex(bb.x1, bb.y1, bb.z1);
t.vertex(bb.x1, bb.y1, bb.z0);
t.vertex(bb.x0, bb.y1, bb.z0);
//t.normal(-1, 0, 0);
t.vertex(bb.x0, bb.y0, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z0);
t.vertex(bb.x0, bb.y0, bb.z0);
//t.normal(1, 0, 0);
t.vertex(bb.x1, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y1, bb.z0);
t.vertex(bb.x1, bb.y1, bb.z1);
t.vertex(bb.x1, bb.y0, bb.z1);
t.offset(0, 0, 0);
t.draw();
glEnable2(GL_TEXTURE_2D);
// model.render(0, 1)
}
/*static*/
void EntityRenderer::renderFlat(const AABB& bb) {
Tesselator& t = Tesselator::instance;
t.begin();
t.vertex(bb.x0, bb.y1, bb.z0);
t.vertex(bb.x1, bb.y1, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z0);
t.vertex(bb.x0, bb.y0, bb.z0);
t.vertex(bb.x0, bb.y0, bb.z1);
t.vertex(bb.x1, bb.y0, bb.z1);
t.vertex(bb.x1, bb.y1, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z1);
t.vertex(bb.x0, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z1);
t.vertex(bb.x0, bb.y0, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z1);
t.vertex(bb.x1, bb.y1, bb.z1);
t.vertex(bb.x1, bb.y1, bb.z0);
t.vertex(bb.x0, bb.y1, bb.z0);
t.vertex(bb.x0, bb.y0, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z1);
t.vertex(bb.x0, bb.y1, bb.z0);
t.vertex(bb.x0, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y0, bb.z0);
t.vertex(bb.x1, bb.y1, bb.z0);
t.vertex(bb.x1, bb.y1, bb.z1);
t.vertex(bb.x1, bb.y0, bb.z1);
t.draw();
}
void EntityRenderer::init(EntityRenderDispatcher* entityRenderDispatcher) {
this->entityRenderDispatcher = entityRenderDispatcher;
}
Font* EntityRenderer::getFont() {
return entityRenderDispatcher->getFont();
}
//void postRender(Entity entity, float x, float y, float z, float rot, float a) {
// if (entityRenderDispatcher.options.fancyGraphics && shadowRadius > 0) {
// float dist = entityRenderDispatcher.distanceToSqr(entity.x, entity.y, entity.z);
// float pow = (float) ((1 - dist / (16.0f * 16.0f)) * shadowStrength);
// if (pow > 0) {
// renderShadow(entity, x, y, z, pow, a);
// }
// }
// if (entity.isOnFire()) renderFlame(entity, x, y, z, a);
//}
//void renderFlame(Entity e, float x, float y, float z, float a) {
// glDisable2(GL_LIGHTING);
// int tex = Tile.fire.tex;
// int xt = (tex & 0xf) << 4;
// int yt = tex & 0xf0;
// float u0 = (xt) / 256.0f;
// float u1 = (xt + 15.99f) / 256.0f;
// float v0 = (yt) / 256.0f;
// float v1 = (yt + 15.99f) / 256.0f;
// glPushMatrix2();
// glTranslatef2((float) x, (float) y, (float) z);
// float s = e.bbWidth * 1.4f;
// glScalef2(s, s, s);
// bindTexture("terrain.png");
// Tesselator t = Tesselator.instance;
// float r = 1.0f;
// float xo = 0.5f;
// float yo = 0.0f;
// float h = e.bbHeight / e.bbWidth;
// glRotatef2(-entityRenderDispatcher.playerRotY, 0, 1, 0);
// glTranslatef2(0, 0, -0.4f + ((int) h) * 0.02f);
// glColor4f2(1, 1, 1, 1);
// // glRotatef2(-playerRotX, 1, 0, 0);
// t.begin();
// while (h > 0) {
// t.vertexUV(r - xo, 0 - yo, 0, u1, v1);
// t.vertexUV(0 - xo, 0 - yo, 0, u0, v1);
// t.vertexUV(0 - xo, 1.4f - yo, 0, u0, v0);
// t.vertexUV(r - xo, 1.4f - yo, 0, u1, v0);
// h -= 1;
// yo -= 1;
// r *= 0.9f;
// glTranslatef2(0, 0, -0.04f);
// }
// t.end();
// glPopMatrix2();
// glEnable2(GL_LIGHTING);
//}
//void renderShadow(Entity e, float x, float y, float z, float pow, float a) {
// glEnable2(GL_BLEND);
// glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Textures textures = entityRenderDispatcher.textures;
// textures.bind(textures.loadTexture("%clamp%/misc/shadow.png"));
// Level level = getLevel();
// glDepthMask(false);
// float r = shadowRadius;
// float ex = e.xOld + (e.x - e.xOld) * a;
// float ey = e.yOld + (e.y - e.yOld) * a + e.getShadowHeightOffs();
// float ez = e.zOld + (e.z - e.zOld) * a;
// int x0 = Mth.floor(ex - r);
// int x1 = Mth.floor(ex + r);
// int y0 = Mth.floor(ey - r);
// int y1 = Mth.floor(ey);
// int z0 = Mth.floor(ez - r);
// int z1 = Mth.floor(ez + r);
// float xo = x - ex;
// float yo = y - ey;
// float zo = z - ez;
// Tesselator tt = Tesselator.instance;
// tt.begin();
// for (int xt = x0; xt <= x1; xt++)
// for (int yt = y0; yt <= y1; yt++)
// for (int zt = z0; zt <= z1; zt++) {
// int t = level.getTile(xt, yt - 1, zt);
// if (t > 0 && level.getRawBrightness(xt, yt, zt) > 3) {
// renderTileShadow(Tile.tiles[t], x, y + e.getShadowHeightOffs(), z, xt, yt, zt, pow, r, xo, yo + e.getShadowHeightOffs(), zo);
// }
// }
// tt.end();
// glColor4f2(1, 1, 1, 1);
// glDisable2(GL_BLEND);
// glDepthMask(true);
//}
//Level* getLevel() {
// return entityRenderDispatcher.level;
//}
//void renderTileShadow(Tile tt, float x, float y, float z, int xt, int yt, int zt, float pow, float r, float xo, float yo, float zo) {
// Tesselator t = Tesselator.instance;
// if (!tt.isCubeShaped()) return;
// float a = ((pow - (y - (yt + yo)) / 2) * 0.5f) * getLevel().getBrightness(xt, yt, zt);
// if (a < 0) return;
// if (a > 1) a = 1;
// t.color(1, 1, 1, (float) a);
// // glColor4f2(1, 1, 1, (float) a);
// float x0 = xt + tt.xx0 + xo;
// float x1 = xt + tt.xx1 + xo;
// float y0 = yt + tt.yy0 + yo + 1.0 / 64.0f;
// float z0 = zt + tt.zz0 + zo;
// float z1 = zt + tt.zz1 + zo;
// float u0 = (float) ((x - (x0)) / 2 / r + 0.5f);
// float u1 = (float) ((x - (x1)) / 2 / r + 0.5f);
// float v0 = (float) ((z - (z0)) / 2 / r + 0.5f);
// float v1 = (float) ((z - (z1)) / 2 / r + 0.5f);
// t.vertexUV(x0, y0, z0, u0, v0);
// t.vertexUV(x0, y0, z1, u0, v1);
// t.vertexUV(x1, y0, z1, u1, v1);
// t.vertexUV(x1, y0, z0, u1, v0);
//}

View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__EntityRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__EntityRenderer_H__
//package net.minecraft.client.renderer.entity;
#include <string>
#include "../../model/HumanoidModel.h"
class Textures;
class Tesselator;
class EntityRenderDispatcher;
class Entity;
class AABB;
class Font;
class EntityRenderer
{
protected:
EntityRenderer();
public:
virtual ~EntityRenderer() {}
void init(EntityRenderDispatcher* entityRenderDispatcher);
virtual void render(Entity* entity, float x, float y, float z, float rot, float a) = 0;
static void render(const AABB& bb, float xo, float yo, float zo);
static void renderFlat(const AABB& bb);
Font* getFont();
virtual void onGraphicsReset() {}
protected:
void bindTexture(const std::string& resourceName);
float shadowRadius;
float shadowStrength;
static EntityRenderDispatcher* entityRenderDispatcher;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__EntityRenderer_H__*/

View File

@@ -0,0 +1,32 @@
#include "FallingTileRenderer.h"
#include "../TileRenderer.h"
#include "../../../world/entity/item/FallingTile.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../world/level/Level.h"
FallingTileRenderer::FallingTileRenderer() {
this->shadowRadius = 0.5f;
tileRenderer = new TileRenderer();
}
FallingTileRenderer::~FallingTileRenderer() {
delete tileRenderer;
}
void FallingTileRenderer::render( Entity* e, float x, float y, float z, float rot, float a ) {
FallingTile* tile = (FallingTile*) e;
glPushMatrix();
glTranslatef(x, y, z);
bindTexture("terrain.png");
Tile* tt = Tile::tiles[tile->tile];
Level* level = tile->getLevel();
if (tt != NULL) {
tileRenderer->renderBlock(tt, level, Mth::floor(tile->x), Mth::floor(tile->y), Mth::floor(tile->z));
}
glPopMatrix();
}

View File

@@ -0,0 +1,22 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__FallingTileRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__FallingTileRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "EntityRenderer.h"
class TileRenderer;
class FallingTileRenderer: public EntityRenderer
{
typedef EntityRenderer super;
public:
FallingTileRenderer();
~FallingTileRenderer();
void render(Entity* e, float x, float y, float z, float rot, float a);
private:
TileRenderer* tileRenderer;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__FallingTileRenderer_H__*/

View File

@@ -0,0 +1,83 @@
#include "HumanoidMobRenderer.h"
#include "EntityRenderDispatcher.h"
#include "../ItemInHandRenderer.h"
#include "../TileRenderer.h"
#include "../../model/HumanoidModel.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../world/entity/player/Player.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../../world/item/ItemInstance.h"
#include "../../../world/item/Item.h"
#include "../../../world/item/BowItem.h"
HumanoidMobRenderer::HumanoidMobRenderer(HumanoidModel* humanoidModel, float shadow)
: super(humanoidModel, shadow),
humanoidModel(humanoidModel)
{
}
void HumanoidMobRenderer::renderHand() {
humanoidModel->attackTime = 0;
humanoidModel->setupAnim(0, 0, 0, 0, 0, 1 / 16.0f);
//@attn @cuberender @enableClientState @vertexarray
glEnableClientState2(GL_VERTEX_ARRAY);
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
//glEnableClientState2(GL_COLOR_ARRAY);
humanoidModel->arm0.render(1 / 16.0f);
glDisableClientState2(GL_VERTEX_ARRAY);
glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
//glDisableClientState2(GL_COLOR_ARRAY);
}
void HumanoidMobRenderer::additionalRendering(Mob* mob, float a) {
ItemInstance* item = mob->getCarriedItem();
if (item != NULL && item->count > 0) {
glPushMatrix2();
humanoidModel->arm0.translateTo(1 / 16.0f);
glTranslatef2(-1.0f / 16.0f, 7.0f / 16.0f, 1.0f / 16.0f);
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape())) {
float s = 8.0f / 16.0f;
glTranslatef2(0.0f, 3.0f / 16.0f, -5 / 16.0f);
s *= 0.75f;
glRotatef2(20.0f, 1.0f, 0.0f, 0.0f);
glRotatef2(45.0f, 0.0f, 1.0f, 0.0f);
glScalef2(s, -s, s);
} else if (item->id == Item::bow->id) {
const float s = 10.0f / 16.0f;
glTranslatef2(0 / 16.0f, 2 / 16.0f, 5 / 16.0f);
glRotatef2(-20, 0, 1, 0);
glScalef2(s, -s, s);
glRotatef2(-100, 1, 0, 0);
glRotatef2(45, 0, 1, 0);
} else if (Item::items[item->id]->isHandEquipped()) {
float s = 10.0f / 16.0f;
glTranslatef2(0.0f, 3.0f / 16.0f, 0.0f);
glScalef2(s, -s, s);
glRotatef2(-100.0f, 1.0f, 0.0f, 0.0f);
glRotatef2(45.0f, 0.0f, 1.0f, 0.0f);
} else {
float s = 6 / 16.0f;
glTranslatef2(+4 / 16.0f, +3 / 16.0f, -3 / 16.0f);
glScalef2(s, s, s);
glRotatef2(60.0f, 0.0f, 0.0f, 1.0f);
glRotatef2(-90.0f, 1.0f, 0.0f, 0.0f);
glRotatef2(20.0f, 0.0f, 0.0f, 1.0f);
}
entityRenderDispatcher->itemInHandRenderer->renderItem(mob, item);
glPopMatrix2();
}
}
void HumanoidMobRenderer::render( Entity* mob_, float x, float y, float z, float rot, float a ) {
Mob* mob = (Mob*)mob_;
ItemInstance* carriedItem = mob->getCarriedItem();
if(carriedItem != NULL)
humanoidModel->holdingRightHand = true;
humanoidModel->sneaking = mob->isSneaking();
super::render(mob_, x, y, z, rot, a);
humanoidModel->holdingRightHand = false;
}

View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__HumanoidMobRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__HumanoidMobRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "MobRenderer.h"
class HumanoidModel;
class Mob;
class HumanoidMobRenderer: public MobRenderer
{
typedef MobRenderer super;
public:
HumanoidMobRenderer(HumanoidModel* humanoidModel, float shadow);
void renderHand();
void render(Entity* mob_, float x, float y, float z, float rot, float a);
protected:
void additionalRendering(Mob* mob, float a);
private:
HumanoidModel* humanoidModel;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__HumanoidMobRenderer_H__*/

View File

@@ -0,0 +1,321 @@
#include "ItemRenderer.h"
#include "EntityRenderDispatcher.h"
#include "../Tesselator.h"
#include "../TileRenderer.h"
#include "../Textures.h"
#include "../../gui/Font.h"
#include "../../../world/entity/item/ItemEntity.h"
#include "../../../world/item/ItemInstance.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../util/Mth.h"
#include "../../../util/Random.h"
#include "EntityRenderer.h"
#include "../ItemInHandRenderer.h"
#include "../../gui/Gui.h"
#include "../../../world/item/Item.h"
/*static*/
TileRenderer* ItemRenderer::tileRenderer = new TileRenderer();
ItemRenderer::ItemRenderer()
{
shadowRadius = 0.15f;
shadowStrength = 0.75f;
}
void ItemRenderer::teardown_static() {
if (tileRenderer) {
delete tileRenderer;
tileRenderer = NULL;
}
}
void ItemRenderer::render(Entity* itemEntity_, float x, float y, float z, float rot, float a) {
ItemEntity* itemEntity = (ItemEntity*) itemEntity_;
random.setSeed(187);
ItemInstance* item = &itemEntity->item;
glPushMatrix2();
float bob = Mth::sin((itemEntity->age + a) / 10.0f + itemEntity->bobOffs) * 0.1f + 0.1f;
float spin = ((itemEntity->age + a) / 20.0f + itemEntity->bobOffs) * Mth::RADDEG;
int count = 1;
if (item->count > 20) count = 4;
else if (item->count > 5) count = 3;
else if (item->count > 1) count = 2;
glTranslatef2((float) x, (float) y + bob, (float) z);
//glEnable2(GL_RESCALE_NORMAL);
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape())) {
glRotatef2(spin, 0, 1, 0);
float br = itemEntity->getBrightness(a);
if (item->id == Tile::sand->id || item->id == Tile::sandStone->id) br *= 0.8f;
glColor4f2(br, br, br, 1.0f);
bindTexture("terrain.png");
float s = 1 / 4.0f;
//if (!Tile::tiles[item->id]->isCubeShaped() && item->id != Tile::stoneSlabHalf->id) {
const int shape = Tile::tiles[item->id]->getRenderShape();
if (shape == Tile::SHAPE_CROSS_TEXTURE || shape == Tile::SHAPE_TORCH)
s = 0.5f;
glScalef2(s, s, s);
for (int i = 0; i < count; i++) {
if (i > 0) {
glPushMatrix2();
float xo = (random.nextFloat() * 2 - 1) * 0.2f / s;
float yo = (random.nextFloat() * 2 - 1) * 0.2f / s;
float zo = (random.nextFloat() * 2 - 1) * 0.2f / s;
glTranslatef2(xo, yo, zo);
}
//static Stopwatch w;
//w.start();
entityRenderDispatcher->itemInHandRenderer->renderItem(NULL, item);
//tileRenderer->renderTile(Tile::tiles[item->id], item->getAuxValue());
//w.stop();
//w.printEvery(100, "render-item");
if (i > 0) glPopMatrix2();
}
} else {
glScalef2(1 / 2.0f, 1 / 2.0f, 1 / 2.0f);
int icon = item->getIcon();
if (item->id < 256) {
bindTexture("terrain.png");
} else {
bindTexture("gui/items.png");
}
Tesselator& t = Tesselator::instance;
float u0 = ((icon % 16) * 16 + 0) / 256.0f;
float u1 = ((icon % 16) * 16 + 16) / 256.0f;
float v0 = ((icon / 16) * 16 + 0) / 256.0f;
float v1 = ((icon / 16) * 16 + 16) / 256.0f;
float r = 1.0f;
float xo = 0.5f;
float yo = 0.25f;
// glRotatef2(-playerRotX, 1, 0, 0);
for (int i = 0; i < count; i++) {
glPushMatrix2();
if (i > 0) {
float _xo = (random.nextFloat() * 2 - 1) * 0.3f;
float _yo = (random.nextFloat() * 2 - 1) * 0.3f;
float _zo = (random.nextFloat() * 2 - 1) * 0.3f;
glTranslatef2(_xo, _yo, _zo);
}
glRotatef2(180 - entityRenderDispatcher->playerRotY, 0, 1, 0);
t.begin();
//t.normal(0, 1, 0);
t.vertexUV(0 - xo, 0 - yo, 0, u0, v1);
t.vertexUV(r - xo, 0 - yo, 0, u1, v1);
t.vertexUV(r - xo, 1 - yo, 0, u1, v0);
t.vertexUV(0 - xo, 1 - yo, 0, u0, v0);
//t.end();
t.draw();
glPopMatrix2();
}
}
//glDisable2(GL_RESCALE_NORMAL);
glPopMatrix2();
}
// @note: _18 -> a,b,c,-1, a,b,c-1, ...
static const signed short _6[] = {139, 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _17[] = {16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _18[] = {79, 80, 81, -1, 79, 80, 81, -1, 79, 80, 81, -1, 79, 80, 81, -1};
static const signed short _24[] = {11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _35[] = {52, 59, 58, 57, 56, 55, 54, 53, 67, 66, 65, 64, 63, 62, 61, 60};
static const signed short _44[] = {28, 32, 30, 29, 31, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _98[] = {1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _155[] = {34, 36, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _263[] = {230, 151, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static const signed short _351[] = {-1, 152, 154, -1, 193, 215, 216, -1, -1, 217, 218, 219, 220, 221, 222, 144};
static const signed short _mapper[] = {-1, 7, 9, 8, 0, 5, -2, -1, -1, -1, -1, -1, 14, 15, 39, 38, 37, -2, -2, -1, 49, 41, 46, -1, -2, -1, -1, -1, -1, -1, 235, -1, -1, -1, -1, -2, -1, 134, 135, 136, 137, 43, 44, -1, -2, 6, 76, 71, 4, 47, 129, -1, -1, 22, 74, -1, 40, 45, 72, -1, -1, 75, -1, -1, -1, 128, -1, 21, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, 48, 77, 10, 236, -1, 69, -1, 20, -1, 50, -1, -1, -1, -1, -1, -1, 68, -1, -2, -1, -1, -1, 130, 78, -1, -1, -1, 70, 23, 25, -1, -1, 19, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, -1, 51, -1, -1, -1, -1, -1, 82, -1, -1, 174, 173, 175, 231, 234, 147, 190, -2, 153, 150, 149, 146, 185, 166, 164, 167, 186, 170, 169, 171, 187, 177, 176, 178, 165, 195, 194, 188, 181, 180, 182, 189, 191, 228, 168, 172, 145, 179, 183, 142, 233, 232, 198, 200, 201, 202, -1, -1, -1, -1, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 192, 156, 157, 133, -1, 148, 131, -1, -1, -1, -1, -1, -1, -1, 226, -1, 199, -1, 159, 158, 138, 224, 225, -1, -1, -1, -1, -1, -1, -1, 227, -1, -1, -2, 223, 229, -1, 132, -1, -1, -1, 184, 196, -1, 143, 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 155, 197};
#define IRMAPCASE(x) case x: return _##x [item->getAuxValue() & 15]
int ItemRenderer::getAtlasPos(const ItemInstance* item) {
int id = item->id;
if (id < 0 || id >= sizeof(_mapper) / sizeof(const signed short))
return -1;
int texId = _mapper[id];
if (texId != -2)
return texId;
switch(id) {
IRMAPCASE(6);
IRMAPCASE(17);
IRMAPCASE(18);
IRMAPCASE(24);
IRMAPCASE(35);
IRMAPCASE(44);
IRMAPCASE(98);
IRMAPCASE(155);
IRMAPCASE(263);
IRMAPCASE(351);
default:
break;
}
return -1;
}
/*static*/
void ItemRenderer::renderGuiItem(Font* font, Textures* textures, const ItemInstance* item, float x, float y, bool fancy) {
renderGuiItem(font, textures, item, x, y, 16, 16, fancy);
}
void ItemRenderer::renderGuiItem(Font* font, Textures* textures, const ItemInstance* item, float x, float y, float w, float h, bool fancy) {
if (item == NULL) {
//LOGW("item is NULL @ ItemRenderer::renderGuiItem\n");
return;
}
const int id = item->id;
if (!Item::items[id])
return;
int i = getAtlasPos(item);
if (i < 0) {
Tesselator& t = Tesselator::instance;
if (!t.isOverridden())
renderGuiItemCorrect(font, textures, item, int(x), int(y));
else {
// @huge @attn @todo @fix: This is just guess-works..
// it we're batching for saving the
// buffer, this will fail miserably
t.endOverrideAndDraw();
glDisable2(GL_TEXTURE_2D);
fillRect(t, x, y, w, h, 0xff0000);
glEnable2(GL_TEXTURE_2D);
renderGuiItemCorrect(font, textures, item, int(x), int(y));
t.beginOverride();
}
return;
}
textures->loadAndBindTexture("gui/gui_blocks.png");
float u0, u1, v0, v1;
if (i < 128) {
const float P = 48.0f / 512.0f;
u0 = (float)(i%10) * P;
v0 = (float)(i/10) * P;
u1 = u0 + P;
v1 = v0 + P;
} else {
i -= 128;
const float P = 16.0f / 512.0f;
u0 = float(i & 31) * P;
v0 = 27 * P + float(i >> 5) * P; // 27 "icon" rows down
u1 = u0 + P;
v1 = v0 + P;
}
const float blitOffset = 0;
Tesselator& t = Tesselator::instance;
t.begin();
t.colorABGR( item->count>0? 0xffffffff : 0x60ffffff);
t.vertexUV(x, y + h, blitOffset, u0, v1);
t.vertexUV(x + w, y + h, blitOffset, u1, v1);
t.vertexUV(x + w, y, blitOffset, u1, v0);
t.vertexUV(x, y, blitOffset, u0, v0);
t.draw();
}
void ItemRenderer::renderGuiItemDecorations(const ItemInstance* item, float x, float y) {
if (!item) return;
if (item->count > 0 && item->isDamaged()) {
float p = std::floor(13.5f - (float) item->getDamageValue() * 13.0f / (float) item->getMaxDamage());
int cc = (int) std::floor(255.5f - (float) item->getDamageValue() * 255.0f / (float) item->getMaxDamage());
//glDisable(GL_LIGHTING);
//glDisable(GL_DEPTH_TEST);
//glDisable(GL_TEXTURE_2D);
Tesselator& t = Tesselator::instance;
int ca = (255 - cc) << 16 | (cc) << 8;
int cb = ((255 - cc) / 4) << 16 | (255 / 4) << 8;
fillRect(t, x + 2, y + 13, 13, 1, 0x000000);
fillRect(t, x + 2, y + 13, 12, 1, cb);
fillRect(t, x + 2, y + 13, p, 1, ca);
//glEnable(GL_TEXTURE_2D);
//glEnable(GL_LIGHTING);
//glEnable(GL_DEPTH_TEST);
glColor4f2(1, 1, 1, 1);
}
}
void ItemRenderer::fillRect(Tesselator& t, float x, float y, float w, float h, int c) {
t.begin();
t.color(c);
t.vertex(x + 0, y + 0, 0);
t.vertex(x + 0, y + h, 0);
t.vertex(x + w, y + h, 0);
t.vertex(x + w, y + 0, 0);
t.draw();
}
void ItemRenderer::renderGuiItemCorrect(Font* font, Textures* textures, const ItemInstance* item, int x, int y) {
if (item == NULL)
return;
//glDisable(GL_CULL_FACE);
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape()))
{
int paint = item->id;
textures->loadAndBindTexture("terrain.png");
static float ff = 0;// ff += 0.005f;
static float gg = 0;// gg += 0.01f;
Tile* tile = Tile::tiles[paint];
glPushMatrix2();
glTranslatef2((GLfloat)(x - 2), (GLfloat)(y + 3), -8);
glScalef2(10.0f, 10.0f, 10.0f);
glTranslatef2(1.0f, 0.5f, 0.0f);
glRotatef2(ff + 180.0f + 30.0f, 1, 0, 0);
glRotatef2(gg + 45.0f, 0, 1, 0);
//glColor4f2(1, 1, 1, 1);
glScalef2(1, 1, 1);
tileRenderer->renderGuiTile(tile, item->getAuxValue());
glPopMatrix2();
}
else if (item->getIcon() >= 0)
{
//if (item->id == Item::camera->id) {
// printf("item->id: %d, %d\n", item->id, item->getIcon());
//}
if (item->id < 256) {
textures->loadAndBindTexture("terrain.png");
} else {
textures->loadAndBindTexture("gui/items.png");
}
//Tesselator& t = Tesselator::instance;
//t.scale2d(Gui::InvGuiScale, Gui::InvGuiScale);
blit((float)x, (float)y, (float)(item->getIcon() % 16 * 16), (float)(item->getIcon() / 16 * 16), 16, 16);
//t.resetScale();
}
//glEnable(GL_CULL_FACE);
}
/*static*/
void ItemRenderer::blit(float x, float y, float sx, float sy, float w, float h) {
float blitOffset = 0;
const float us = 1 / 256.0f;
const float vs = 1 / 256.0f;
Tesselator& t = Tesselator::instance;
t.begin();
t.vertexUV(x, y + h, blitOffset, sx * us, (sy + h) * vs);
t.vertexUV(x + w, y + h, blitOffset, (sx + w) * us, (sy + h) * vs);
t.vertexUV(x + w, y, blitOffset, (sx + w) * us, sy * vs);
t.vertexUV(x, y, blitOffset, sx * us, sy * vs);
//t.end();
t.draw();
}

View File

@@ -0,0 +1,38 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ItemRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ItemRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "EntityRenderer.h"
#include "../../../util/Random.h"
class Font;
class Entity;
class ItemInstance;
class Textures;
class Tesselator;
class TileRenderer;
class ItemRenderer: public EntityRenderer
{
public:
ItemRenderer();
void render(Entity* itemEntity_, float x, float y, float z, float rot, float a);
static void renderGuiItem(Font* font, Textures* textures, const ItemInstance* item, float x, float y, bool fancy);
static void renderGuiItem(Font* font, Textures* textures, const ItemInstance* item, float x, float y, float w, float h, bool fancy);
static void renderGuiItemCorrect(Font* font, Textures* textures, const ItemInstance* item, int x, int y);
//void renderGuiItemDecorations(Font* font, Textures* textures, ItemInstance* item, int x, int y);
static void renderGuiItemDecorations(const ItemInstance* item, float x, float y);
static void blit(float x, float y, float sx, float sy, float w, float h);
static int getAtlasPos(const ItemInstance* item);
static void teardown_static();
private:
static void fillRect(Tesselator& t, float x, float y, float w, float h, int c);
static TileRenderer* tileRenderer;
Random random;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ItemRenderer_H__*/

View File

@@ -0,0 +1,41 @@
#include "ItemSpriteRenderer.h"
#include "EntityRenderDispatcher.h"
#include "../Tesselator.h"
#include "../../../world/entity/Entity.h"
ItemSpriteRenderer::ItemSpriteRenderer( int icon )
: icon(icon)
{
}
void ItemSpriteRenderer::render( Entity* e, float x, float y, float z, float rot, float a )
{
glPushMatrix2();
glTranslatef2((float) x, (float) y, (float) z);
glScalef2(1 / 2.0f, 1 / 2.0f, 1 / 2.0f);
bindTexture("gui/items.png");
Tesselator& t = Tesselator::instance;
float u0 = ((icon % 16) * 16 + 0) / 256.0f;
float u1 = ((icon % 16) * 16 + 16) / 256.0f;
float v0 = ((icon / 16) * 16 + 0) / 256.0f;
float v1 = ((icon / 16) * 16 + 16) / 256.0f;
float r = 1.0f;
float xo = 0.5f;
float yo = 0.25f;
glRotatef2(180 - entityRenderDispatcher->playerRotY, 0, 1, 0);
glRotatef2(-entityRenderDispatcher->playerRotX, 1, 0, 0);
t.begin();
t.vertexUV(0 - xo, 0 - yo, 0, u0, v1);
t.vertexUV(r - xo, 0 - yo, 0, u1, v1);
t.vertexUV(r - xo, 1 - yo, 0, u1, v0);
t.vertexUV(0 - xo, 1 - yo, 0, u0, v0);
t.draw();
glPopMatrix2();
}

View File

@@ -0,0 +1,18 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ItemSpriteRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ItemSpriteRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "EntityRenderer.h"
class ItemSpriteRenderer: public EntityRenderer
{
public:
ItemSpriteRenderer(int icon);
void render(Entity* e, float x, float y, float z, float rot, float a);
private:
int icon;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__ItemSpriteRenderer_H__*/

View File

@@ -0,0 +1,241 @@
#include "MobRenderer.h"
#include "EntityRenderDispatcher.h"
#include "../../gui/Font.h"
#include "../Tesselator.h"
#include "../../Minecraft.h"
#include "../../model/Model.h"
#include "../../../world/entity/Mob.h"
#include "../../../util/Mth.h"
MobRenderer::MobRenderer(Model* model, float shadow)
: model(model),
armor(NULL)
{
shadowRadius = shadow;
}
MobRenderer::~MobRenderer() {
delete model;
}
void MobRenderer::setArmor(Model* armor) {
this->armor = armor;
}
Model* MobRenderer::getArmor() {
return armor;
}
void MobRenderer::render(Entity* e, float x, float y, float z, float rot, float a)
{
Mob* mob = (Mob*) e;
glPushMatrix2();
glDisable2(GL_CULL_FACE);
model->attackTime = getAttackAnim(mob, a);
model->riding = false;//mob.isRiding();
model->young = mob->isBaby();
if (armor) {
armor->riding = model->riding;
armor->young = model->young;
armor->attackTime = model->attackTime;
}
float bodyRot = (mob->yBodyRotO + (mob->yBodyRot - mob->yBodyRotO) * a);
float headRot = (mob->yRotO + (mob->yRot - mob->yRotO) * a);
float headRotx = (mob->xRotO + (mob->xRot - mob->xRotO) * a);
float yoffset = mob->heightOffset;
setupPosition(mob, x, y - yoffset, z);
float bob = getBob(mob, a);
setupRotations(mob, bob, bodyRot, a);
float ascale = 1 / 16.0f;
glScalef2(-1, -1, 1);
scale(mob, a);
glTranslatef2(0, -24 * ascale - 0.125f / 16.0f, 0);
float ws = mob->walkAnimSpeedO + (mob->walkAnimSpeed - mob->walkAnimSpeedO) * a;
float wp = mob->walkAnimPos - mob->walkAnimSpeed * (1 - a);
if (mob->isBaby()) {
wp *= 3.0f;
}
if (ws > 1) ws = 1;
bindTexture(mob->getTexture());
//glEnable2(GL_ALPHA_TEST);
model->prepareMobModel(mob, wp, ws, a);
model->render(e, wp, ws, bob, headRot - bodyRot, headRotx, ascale);
for (int i = 0; i < MAX_ARMOR_LAYERS; i++) {
if (prepareArmor(mob, i, a) < 0) continue;
armor->prepareMobModel(mob, wp, ws, a);
armor->render(e, wp, ws, bob, headRot - bodyRot, headRotx, ascale);
glDisable2(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
}
additionalRendering(mob, a);
float br = mob->getBrightness(a);
int overlayColor = getOverlayColor(mob, br, a);
bool renderOverlay = ((overlayColor >> 24) & 0xff) > 0;
bool renderHurt = (mob->hurtTime > 0) || (mob->deathTime > 0);
if (renderOverlay || renderHurt) {
glDisable2(GL_TEXTURE_2D);
glDisable2(GL_ALPHA_TEST);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_EQUAL);
if (renderHurt) {
glEnable(GL_COLOR_MATERIAL);
glColor4f2(br, 0, 0, 0.4f);
model->render(e, wp, ws, bob, headRot - bodyRot, headRotx, ascale);
for (int i = 0; i < MAX_ARMOR_LAYERS; i++) {
if (prepareArmor(mob, i, a) < 0) continue;
glColor4f2(br, 0, 0, 0.4f);
armor->prepareMobModel(mob, wp, ws, a);
armor->render(e, wp, ws, bob, headRot - bodyRot, headRotx, ascale);
}
}
if (renderOverlay) {
float r = ((overlayColor >> 16) & 0xff) / 255.0f;
float g = ((overlayColor >> 8) & 0xff) / 255.0f;
float b = ((overlayColor) & 0xff) / 255.0f;
float aa = ((overlayColor >> 24) & 0xff) / 255.0f;
glColor4f2(r, g, b, aa);
model->render(e, wp, ws, bob, headRot - bodyRot, headRotx, ascale);
for (int i = 0; i < MAX_ARMOR_LAYERS; i++) {
if (prepareArmor(mob, i, a) < 0) continue;
glColor4f2(r, g, b, aa);
armor->prepareMobModel(mob, wp, ws, a);
armor->render(e, wp, ws, bob, headRot - bodyRot, headRotx, ascale);
}
}
glDepthFunc(GL_LEQUAL);
glDisable2(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
glEnable2(GL_TEXTURE_2D);
}
glEnable2(GL_CULL_FACE);
//glEnable2(GL_DEPTH_TEST);
glPopMatrix2();
renderName(mob, x, y, z);
}
void MobRenderer::setupPosition(Entity* mob, float x, float y, float z) {
glTranslatef2((float) x, (float) y, (float) z);
}
void MobRenderer::setupRotations(Entity* mob_, float bob, float bodyRot, float a) {
glRotatef2(180 - bodyRot, 0, 1, 0);
Mob* mob = (Mob*)mob_;
if (mob->deathTime > 0) {
float fall = (mob->deathTime + a - 1) / 20.0f * 1.6f;
fall = Mth::sqrt(fall);
if (fall > 1) fall = 1;
glRotatef2(fall * getFlipDegrees(mob), 0, 0, 1);
}
}
float MobRenderer::getAttackAnim(Mob* mob, float a) {
return mob->getAttackAnim(a);
}
float MobRenderer::getBob(Mob* mob, float a) {
return (mob->tickCount + a);
}
void MobRenderer::additionalRendering(Mob* mob, float a) {
}
void MobRenderer::onGraphicsReset() {
if (model) model->onGraphicsReset();
if (armor) armor->onGraphicsReset();
}
int MobRenderer::prepareArmor(Mob* mob, int layer, float a) {
return -1;
}
float MobRenderer::getFlipDegrees(Mob* mob) {
return 90;
}
int MobRenderer::getOverlayColor(Mob* mob, float br, float a) {
return 0;
}
void MobRenderer::scale(Mob* mob, float a) {
}
void MobRenderer::renderName(Mob* mob, float x, float y, float z) {
/*
std::stringstream ss; ss << mob->entityId;
renderNameTag(mob, ss.str(), x, y, z, 64);
*/
}
void MobRenderer::renderNameTag(Mob* mob, const std::string& name, float x, float y, float z, int maxDist) {
float dist = mob->distanceToSqr(entityRenderDispatcher->cameraEntity);
if (dist > maxDist*maxDist)
return;
Font* font = getFont();
float size = 1.60f;
float s = 1 / 60.0f * size;
glPushMatrix2();
glTranslatef2((float) x + 0, (float) y + 1.0f /*2.3f*/, (float) z);
glRotatef2(-entityRenderDispatcher->playerRotY, 0, 1, 0);
glRotatef2(entityRenderDispatcher->playerRotX, 1, 0, 0);
glScalef2(-s, -s, s);
glDepthMask(false);
glDisable2(GL_DEPTH_TEST);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Tesselator& t = Tesselator::instance;
glDisable2(GL_TEXTURE_2D);
t.begin();
int w = font->width(name) / 2;
t.color(0.0f, 0.0f, 0.0f, 0.25f);
t.vertex(-(float)w - 1, -1, 0);
t.vertex(-(float)w - 1, +8, 0);
t.vertex(+(float)w + 1, +8, 0);
t.vertex(+(float)w + 1, -1, 0);
//t.end();
t.draw();
glEnable2(GL_TEXTURE_2D);
const float fnameWidth = (float)font->width(name) / -2;
font->draw(name, fnameWidth, 0, 0x20ffffff);
glEnable2(GL_DEPTH_TEST);
glDepthMask(true);
font->draw(name, (float) fnameWidth, 0, 0xffffffff);
glDisable2(GL_BLEND);
glColor4f2(1, 1, 1, 1);
glPopMatrix2();
}

View File

@@ -0,0 +1,51 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__MobRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__MobRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "EntityRenderer.h"
#include <string>
class Model;
class Entity;
class Mob;
class MobRenderer: public EntityRenderer
{
static const int MAX_ARMOR_LAYERS = 4;
public:
// @note: MobRenderer::model will be deleted automagically
// Armor models (setArmor(Model*)) is to be deleted by derived classes.
MobRenderer(Model* model, float shadow);
~MobRenderer();
virtual int prepareArmor(Mob* mob, int layer, float a);
virtual void setupPosition(Entity* mob, float x, float y, float z);
virtual void setupRotations(Entity* mob_, float bob, float bodyRot, float a);
virtual float getAttackAnim(Mob* mob, float a);
virtual float getBob(Mob* mob, float a);
virtual float getFlipDegrees(Mob* mob);
virtual int getOverlayColor(Mob* mob, float br, float a);
virtual void scale(Mob* mob, float a);
virtual void render(Entity* mob_, float x, float y, float z, float rot, float a);
virtual void renderName(Mob* mob, float x, float y, float z);
virtual void renderNameTag(Mob* mob, const std::string& name, float x, float y, float z, int maxDist);
virtual void additionalRendering(Mob* mob, float a);
virtual void onGraphicsReset();
protected:
void setArmor(Model* armor);
Model* getArmor();
private:
Model* model;
Model* armor;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__MobRenderer_H__*/

View File

@@ -0,0 +1,99 @@
#include "PaintingRenderer.h"
#include "../../../world/entity/Painting.h"
#include "../../../world/Direction.h"
#include "../Tesselator.h"
#include "../Textures.h"
#include "../gles.h"
void PaintingRenderer::render( Entity* entity, float x, float y, float z, float rot, float a ) {
glPushMatrix();
glTranslatef(float(x), float(y), float(z));
glRotatef(rot, 0, 1.0f, 0);
//glEnable(GL_RESCALE_NORMAL);
bindTexture("art/kz.png");
Painting* painting = (Painting*)entity;
const Motive* motive = painting->motive;
float s = 1.0f / 16.0f;
glScalef(s, s, s);
renderPainting(painting, motive->w, motive->h, motive->uo, motive->vo, a);
//glDisable(GL_RESCALE_NORMAL);
glPopMatrix();
}
void PaintingRenderer::renderPainting( Painting* painting, int w, int h, int uo, int vo, float a) {
float xx0 = -w / 2.0f;
float yy0 = -h / 2.0f;
float edgeWidth = 0.5f;
// Back
float bu0 = (12 * 16) / 256.0f;
float bu1 = (12 * 16 + 16) / 256.0f;
float bv0 = (0) / 256.0f;
float bv1 = (0 + 16) / 256.0f;
// Border
float uu0 = (12 * 16) / 256.0f;
float uu1 = (12 * 16 + 16) / 256.0f;
float uv0 = (0.5f) / 256.0f;
float uv1 = (0.5f) / 256.0f;
// Border
float su0 = (12 * 16 + 0.5f) / 256.0f;
float su1 = (12 * 16 + 0.5f) / 256.0f;
float sv0 = (0) / 256.0f;
float sv1 = (0 + 16) / 256.0f;
for (int xs = 0; xs < w / 16; xs++) {
for (int ys = 0; ys < h / 16; ys++) {
float x0 = xx0 + (xs + 1) * 16;
float x1 = xx0 + (xs) * 16;
float y0 = yy0 + (ys + 1) * 16;
float y1 = yy0 + (ys) * 16;
//setBrightness(painting, (x0 + x1) / 2, (y0 + y1) / 2);
// Painting
float fu0 = (uo + w - (xs) * 16) / 256.0f;
float fu1 = (uo + w - (xs + 1) * 16) / 256.0f;
float fv0 = (vo + h - (ys) * 16) / 256.0f;
float fv1 = (vo + h - (ys + 1) * 16) / 256.0f;
Tesselator& t = Tesselator::instance;
float br = painting->getBrightness(a);
t.color(br, br, br);
t.begin();
t.vertexUV(x0, y1, -edgeWidth, fu1, fv0);
t.vertexUV(x1, y1, -edgeWidth, fu0, fv0);
t.vertexUV(x1, y0, -edgeWidth, fu0, fv1);
t.vertexUV(x0, y0, -edgeWidth, fu1, fv1);
t.vertexUV(x0, y0, edgeWidth, bu0, bv0);
t.vertexUV(x1, y0, edgeWidth, bu1, bv0);
t.vertexUV(x1, y1, edgeWidth, bu1, bv1);
t.vertexUV(x0, y1, edgeWidth, bu0, bv1);
t.vertexUV(x0, y0, -edgeWidth, uu0, uv0);
t.vertexUV(x1, y0, -edgeWidth, uu1, uv0);
t.vertexUV(x1, y0, edgeWidth, uu1, uv1);
t.vertexUV(x0, y0, edgeWidth, uu0, uv1);
t.vertexUV(x0, y1, edgeWidth, uu0, uv0);
t.vertexUV(x1, y1, edgeWidth, uu1, uv0);
t.vertexUV(x1, y1, -edgeWidth, uu1, uv1);
t.vertexUV(x0, y1, -edgeWidth, uu0, uv1);
t.vertexUV(x0, y0, edgeWidth, su1, sv0);
t.vertexUV(x0, y1, edgeWidth, su1, sv1);
t.vertexUV(x0, y1, -edgeWidth, su0, sv1);
t.vertexUV(x0, y0, -edgeWidth, su0, sv0);
t.vertexUV(x1, y0, -edgeWidth, su1, sv0);
t.vertexUV(x1, y1, -edgeWidth, su1, sv1);
t.vertexUV(x1, y1, edgeWidth, su0, sv1);
t.vertexUV(x1, y0, edgeWidth, su0, sv0);
t.draw();
}
}
}

View File

@@ -0,0 +1,12 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PaintingRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PaintingRenderer_H__
#include "EntityRenderer.h"
class Painting;
class PaintingRenderer : public EntityRenderer {
public:
void render(Entity* entity, float x, float y, float z, float rot, float a);
private:
void renderPainting(Painting* painting, int w, int h, int uo, int vo, float a);
};
#endif /* NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PaintingRenderer_H__ */

View File

@@ -0,0 +1,29 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PigRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PigRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "../../model/Model.h"
#include "../../../world/entity/animal/Pig.h"
class PigRenderer: public MobRenderer
{
typedef MobRenderer super;
public:
PigRenderer(Model* model, Model* armor, float shadow)
: super(model, shadow)
{
// setArmor(armor);
}
//void render(Entity* mob, float x, float y, float z, float rot, float a) {
// super::render(mob, x, y, z, rot, a);
//}
protected:
//int prepareArmor(Entity* pig, int layer, float a) {
// bindTexture("/mob/saddle.png");
// return (layer == 0 && pig->hasSaddle()) ? 1 : -1;
//}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PigRenderer_H__*/

View File

@@ -0,0 +1,87 @@
#include "PlayerRenderer.h"
#include "EntityRenderDispatcher.h"
#include "../../../world/entity/player/Player.h"
#include "../../../world/level/Level.h"
#include "../../../world/item/ArmorItem.h"
static const std::string armorFilenames[10] = {
"armor/cloth_1.png", "armor/cloth_2.png",
"armor/chain_1.png", "armor/chain_2.png",
"armor/iron_1.png", "armor/iron_2.png",
"armor/diamond_1.png", "armor/diamond_2.png",
"armor/gold_1.png", "armor/gold_2.png",
};
PlayerRenderer::PlayerRenderer( HumanoidModel* humanoidModel, float shadow )
: super(humanoidModel, shadow),
armorParts1(new HumanoidModel(1.0f)),
armorParts2(new HumanoidModel(0.5f))
{
}
PlayerRenderer::~PlayerRenderer() {
delete armorParts1;
delete armorParts2;
}
void PlayerRenderer::setupPosition( Entity* mob, float x, float y, float z ) {
Player* player = (Player*) mob;
if(player->isAlive() && player->isSleeping()) {
return super::setupPosition(mob, x + player->bedOffsetX, y + player->bedOffsetY, z + player->bedOffsetZ);
}
return super::setupPosition(mob, x, y, z);
}
void PlayerRenderer::setupRotations( Entity* mob, float bob, float bodyRot, float a ) {
Player* player = (Player*) mob;
if(player->isAlive() && player->isSleeping()) {
glRotatef(player->getSleepRotation(), 0, 1, 0);
glRotatef(getFlipDegrees(player), 0, 0, 1);
glRotatef(270, 0, 1, 0);
return;
}
super::setupRotations(mob, bob, bodyRot, a);
}
void PlayerRenderer::renderName( Mob* mob, float x, float y, float z ){
//@todo: figure out how to handle HideGUI
if (mob != entityRenderDispatcher->cameraEntity && mob->level->adventureSettings.showNameTags) {
renderNameTag(mob, ((Player*)mob)->name, x, y, z, 32);
}
}
int PlayerRenderer::prepareArmor(Mob* mob, int layer, float a) {
Player* player = (Player*) mob;
ItemInstance* itemInstance = player->getArmor(layer);
if (!ItemInstance::isArmorItem(itemInstance))
return -1;
ArmorItem* armorItem = (ArmorItem*) itemInstance->getItem();
int fnIndex = (armorItem->modelIndex + armorItem->modelIndex) + (layer == 2 ? 1 : 0);
bindTexture(armorFilenames[fnIndex]);
HumanoidModel* armor = layer == 2 ? armorParts2 : armorParts1;
armor->head.visible = layer == 0;
//armor.hair.visible = layer == 0;
armor->body.visible = layer == 1 || layer == 2;
armor->arm0.visible = layer == 1;
armor->arm1.visible = layer == 1;
armor->leg0.visible = layer == 2 || layer == 3;
armor->leg1.visible = layer == 2 || layer == 3;
setArmor(armor);
/*if (itemInstance.isEnchanted())
return 15; */
return 1;
}
void PlayerRenderer::onGraphicsReset() {
super::onGraphicsReset();
if (armorParts1) armorParts1->onGraphicsReset();
if (armorParts2) armorParts2->onGraphicsReset();
}

View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PlayerRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PlayerRenderer_H__
#include "HumanoidMobRenderer.h"
class PlayerRenderer : public HumanoidMobRenderer
{
typedef HumanoidMobRenderer super;
public:
PlayerRenderer(HumanoidModel* humanoidModel, float shadow);
~PlayerRenderer();
virtual int prepareArmor(Mob* mob, int layer, float a);
virtual void setupPosition(Entity* mob, float x, float y, float z);
virtual void setupRotations(Entity* mob, float bob, float bodyRot, float a);
virtual void renderName(Mob* mob, float x, float y, float z);
virtual void onGraphicsReset();
private:
HumanoidModel* armorParts1;
HumanoidModel* armorParts2;
};
#endif /* NET_MINECRAFT_CLIENT_RENDERER_ENTITY__PlayerRenderer_H__ */

View File

@@ -0,0 +1,29 @@
#include "SheepRenderer.h"
#include "../../../world/entity/animal/Sheep.h"
#include "../gles.h"
SheepRenderer::SheepRenderer( Model* model, Model* armor, float shadow )
: super(model, shadow)
{
setArmor(armor);
}
SheepRenderer::~SheepRenderer() {
delete getArmor();
}
int SheepRenderer::prepareArmor(Mob* mob, int layer, float a) {
Sheep* sheep = (Sheep*) mob;
if (layer == 0 && !sheep->isSheared()) {
bindTexture("mob/sheep_fur.png");
float brightness = sheep->getBrightness(a);
int color = sheep->getColor();
glColor4f2( brightness * Sheep::COLOR[color][0],
brightness * Sheep::COLOR[color][1],
brightness * Sheep::COLOR[color][2], 1);
return 1;
}
return -1;
}

View File

@@ -0,0 +1,20 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__SheepRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__SheepRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "MobRenderer.h"
class Mob;
class SheepRenderer: public MobRenderer
{
typedef MobRenderer super;
public:
SheepRenderer(Model* model, Model* armor, float shadow);
~SheepRenderer();
protected:
int prepareArmor(Mob* sheep, int layer, float a);
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__SheepRenderer_H__*/

View File

@@ -0,0 +1,46 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__SpiderRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__SpiderRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "MobRenderer.h"
#include "../gles.h"
#include "../../model/SpiderModel.h"
#include "../../../world/entity/monster/Spider.h"
class SpiderRenderer: public MobRenderer
{
typedef MobRenderer super;
public:
SpiderRenderer()
: super(new SpiderModel(), 1.0f)
{
//this->setArmor(/*new*/ SpiderModel());
}
protected:
float getFlipDegrees(Mob* spider) {
return 180;
}
// int prepareArmor(Mob* spider, int layer, float a) {
// if (layer != 0) return -1;
// bindTexture("/mob/spider_eyes.png");
// float br = 1.0f;
// glEnable(GL_BLEND);
// glDisable(GL_ALPHA_TEST);
//// glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc2(GL_ONE, GL_ONE);
// glColor4f2(1, 1, 1, br);
// return 1;
// }
/*@Override*/
void scale(Mob* mob, float a) {
float scale = ((Spider*)mob)->getModelScale();
glScalef(scale, scale, scale);
}
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__SpiderRenderer_H__*/

View File

@@ -0,0 +1,47 @@
#include "TntRenderer.h"
#include "../Tesselator.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../world/entity/item/PrimedTnt.h"
TntRenderer::TntRenderer()
{
this->shadowRadius = 0.5f;
}
void TntRenderer::render( Entity* tnt_, float x, float y, float z, float rot, float a )
{
PrimedTnt* tnt = (PrimedTnt*)tnt_;
glPushMatrix2();
glTranslatef2((float) x, (float) y, (float) z);
if (tnt->life - a + 1 < 10) {
float g = 1 - ((tnt->life - a + 1) / 10.0f);
if (g < 0) g = 0;
if (g > 1) g = 1;
g = g * g;
g = g * g;
float s = 1.0f + g * 0.3f;
glScalef2(s, s, s);
}
float br = (1 - ((tnt->life - a + 1) / 100.0f)) * 0.8f;
bindTexture("terrain.png");
Tesselator& t = Tesselator::instance;
t.color(1.0f, 1.0f, 1.0f);
tileRenderer.renderTile(Tile::tnt, 0);
if (((tnt->life / 5) & 1) == 0) {
glDisable2(GL_TEXTURE_2D);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_DST_ALPHA);
glColor4f2(1, 1, 1, br);
//t.color(1.0f, 1.0f, 1.0f, br);
tileRenderer.renderTile(Tile::tnt, 0);
glColor4f2(1, 1, 1, 1);
glDisable2(GL_BLEND);
//glEnable2(GL_LIGHTING);
glEnable2(GL_TEXTURE_2D);
}
glPopMatrix2();
}

View File

@@ -0,0 +1,18 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__TntRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__TntRenderer_H__
//package net.minecraft.client.renderer.entity;
#include "EntityRenderer.h"
#include "../TileRenderer.h"
class TntRenderer: public EntityRenderer
{
public:
TntRenderer();
void render(Entity* tnt_, float x, float y, float z, float rot, float a);
TileRenderer tileRenderer;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__TntRenderer_H__*/

View File

@@ -0,0 +1,75 @@
#include "TripodCameraRenderer.h"
#include "EntityRenderDispatcher.h"
#include "../Tesselator.h"
#include "../../Minecraft.h"
#include "../../../world/entity/item/TripodCamera.h"
#include "../../../world/level/material/Material.h"
TripodCameraRenderer::TripodCameraRenderer()
: tripod(0, 15 * 16 + 3, Material::plant),
cameraCube(0, 0)
{
cameraCube.addBox(-4, -4, -6, 8, 8, 10);
cameraCube.y = 11;
this->shadowRadius = 0.5f;
}
float TripodCameraRenderer::getFlashTime(const TripodCamera* c, float a) {
if (c->life >= 8) return -1;
if (c->life < 0) return -1;
return (c->life - a) * 0.125f;
}
void TripodCameraRenderer::render(Entity* cam_, float x, float y, float z, float rot, float a) {
TripodCamera* cam = (TripodCamera*)cam_;
glPushMatrix2();
glTranslatef2((float) x, (float) y, (float) z);
cameraCube.xRot = Mth::DEGRAD * (180.0f + cam->xRot * 0.5f);
cameraCube.yRot = -Mth::DEGRAD * cam->yRot;
//float br = (1 - ((cam->life - a + 1) / 100.0f)) * 0.8f;
Tesselator& t = Tesselator::instance;
t.color(1.0f, 1.0f, 1.0f);
//printf("xyz: %f, %f, %f\n", x, y, z);
// Render tripod legs
bindTexture("gui/items.png");
t.begin();
tileRenderer.tesselateCrossTexture(&tripod, 0, -0.5f, -0.5f, -0.5f);//, y, z);
t.draw();
// Render tripod
bindTexture("item/camera.png");
cameraCube.render(1.0f / 16.0f);
bool isCurrentlyPicked = entityRenderDispatcher->minecraft->hitResult.entity == cam;
const float flashLife = getFlashTime(cam, a);
if (flashLife >= 0) {
const float flashStrength = ::sin(flashLife * 6.2830f);
// Flash
glColor4f2(1, 1, 1, flashStrength);
glColor4f2(1, 1, 1, 1);
}
// "red light" flashing when photo is about to go off
if (isCurrentlyPicked) {
glDisable2(GL_TEXTURE_2D);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_DST_ALPHA);
glColor4f2(0.5f,0.5f,0.5f,0.5f);
cameraCube.renderHorrible(1.0f / 16.0f);
glColor4f2(1,1,1,1);
glDisable2(GL_BLEND);
glEnable2(GL_TEXTURE_2D);
}
glPopMatrix2();
}

View File

@@ -0,0 +1,29 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_ENTITY__TripodCameraRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_ENTITY__TripodCameraRenderer_H__
#include "EntityRenderer.h"
#include "../TileRenderer.h"
#include "../../model/geom/ModelPart.h"
#include "../../../world/level/tile/Tile.h"
class TripodCamera;
class TripodCameraRenderer: public EntityRenderer
{
TileRenderer tileRenderer;
public:
TripodCameraRenderer();
void render(Entity* cam_, float x, float y, float z, float rot, float a);
//void render( Tesselator &t );
static float getFlashTime(const TripodCamera* c, float a);
private:
Tile tripod;
ModelPart cameraCube;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__TripodCameraRenderer_H__*/

382
src/client/renderer/gles.cpp Executable file
View File

@@ -0,0 +1,382 @@
#include "gles.h"
#include <cmath>
#include <cstdio>
static const float __glPi = 3.14159265358979323846f;
static void __gluMakeIdentityf(GLfloat m[16]);
void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) {
GLfloat m[4][4];
GLfloat sine, cotangent, deltaZ;
GLfloat radians=(GLfloat)(fovy/2.0f*__glPi/180.0f);
deltaZ=zFar-zNear;
sine=(GLfloat)sin(radians);
if ((deltaZ==0.0f) || (sine==0.0f) || (aspect==0.0f))
{
return;
}
cotangent=(GLfloat)(cos(radians)/sine);
__gluMakeIdentityf(&m[0][0]);
m[0][0] = cotangent / aspect;
m[1][1] = cotangent;
m[2][2] = -(zFar + zNear) / deltaZ;
m[2][3] = -1.0f;
m[3][2] = -2.0f * zNear * zFar / deltaZ;
m[3][3] = 0;
glMultMatrixf(&m[0][0]);
}
void __gluMakeIdentityf(GLfloat m[16]) {
m[0] = 1; m[4] = 0; m[8] = 0; m[12] = 0;
m[1] = 0; m[5] = 1; m[9] = 0; m[13] = 0;
m[2] = 0; m[6] = 0; m[10] = 1; m[14] = 0;
m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
}
void glInit()
{
#ifndef OPENGL_ES
GLenum err = glewInit();
printf("Err: %d\n", err);
#endif
}
void anGenBuffers(GLsizei n, GLuint* buffers) {
static GLuint k = 1;
for (int i = 0; i < n; ++i)
buffers[i] = ++k;
}
#ifdef USE_VBO
void drawArrayVT(int bufferId, int vertices, int vertexSize /* = 24 */, unsigned int mode /* = GL_TRIANGLES */) {
//if (Options::debugGl) LOGI("drawArray\n");
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
glTexCoordPointer2(2, GL_FLOAT, vertexSize, (GLvoid*) (3 * 4));
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
glVertexPointer2(3, GL_FLOAT, vertexSize, 0);
glEnableClientState2(GL_VERTEX_ARRAY);
glDrawArrays2(mode, 0, vertices);
glDisableClientState2(GL_VERTEX_ARRAY);
glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
}
#ifndef drawArrayVT_NoState
void drawArrayVT_NoState(int bufferId, int vertices, int vertexSize /* = 24 */) {
//if (Options::debugGl) LOGI("drawArray\n");
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
glTexCoordPointer2(2, GL_FLOAT, vertexSize, (GLvoid*) (3 * 4));
//glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
glVertexPointer2(3, GL_FLOAT, vertexSize, 0);
//glEnableClientState2(GL_VERTEX_ARRAY);
glDrawArrays2(GL_TRIANGLES, 0, vertices);
//glDisableClientState2(GL_VERTEX_ARRAY);
//glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
}
#endif
void drawArrayVTC(int bufferId, int vertices, int vertexSize /* = 24 */) {
//if (Options::debugGl) LOGI("drawArray\n");
//LOGI("draw-vtc: %d, %d, %d\n", bufferId, vertices, vertexSize);
glEnableClientState2(GL_VERTEX_ARRAY);
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
glEnableClientState2(GL_COLOR_ARRAY);
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
glVertexPointer2( 3, GL_FLOAT, vertexSize, 0);
glTexCoordPointer2(2, GL_FLOAT, vertexSize, (GLvoid*) (3 * 4));
glColorPointer2(4, GL_UNSIGNED_BYTE, vertexSize, (GLvoid*) (5*4));
glDrawArrays2(GL_TRIANGLES, 0, vertices);
glDisableClientState2(GL_VERTEX_ARRAY);
glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
glDisableClientState2(GL_COLOR_ARRAY);
}
#ifndef drawArrayVTC_NoState
void drawArrayVTC_NoState(int bufferId, int vertices, int vertexSize /* = 24 */) {
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
glVertexPointer2( 3, GL_FLOAT, vertexSize, 0);
glTexCoordPointer2(2, GL_FLOAT, vertexSize, (GLvoid*) (3 * 4));
glColorPointer2(4, GL_UNSIGNED_BYTE, vertexSize, (GLvoid*) (5*4));
glDrawArrays2(GL_TRIANGLES, 0, vertices);
}
#endif
#endif
//
// Code borrowed from OpenGL.org
// http://www.opengl.org/wiki/GluProject_and_gluUnProject_code
// The gluUnProject code in Android seems to be broken
//
void MultiplyMatrices4by4OpenGL_FLOAT(float *result, float *matrix1, float *matrix2)
{
result[0]=matrix1[0]*matrix2[0]+
matrix1[4]*matrix2[1]+
matrix1[8]*matrix2[2]+
matrix1[12]*matrix2[3];
result[4]=matrix1[0]*matrix2[4]+
matrix1[4]*matrix2[5]+
matrix1[8]*matrix2[6]+
matrix1[12]*matrix2[7];
result[8]=matrix1[0]*matrix2[8]+
matrix1[4]*matrix2[9]+
matrix1[8]*matrix2[10]+
matrix1[12]*matrix2[11];
result[12]=matrix1[0]*matrix2[12]+
matrix1[4]*matrix2[13]+
matrix1[8]*matrix2[14]+
matrix1[12]*matrix2[15];
result[1]=matrix1[1]*matrix2[0]+
matrix1[5]*matrix2[1]+
matrix1[9]*matrix2[2]+
matrix1[13]*matrix2[3];
result[5]=matrix1[1]*matrix2[4]+
matrix1[5]*matrix2[5]+
matrix1[9]*matrix2[6]+
matrix1[13]*matrix2[7];
result[9]=matrix1[1]*matrix2[8]+
matrix1[5]*matrix2[9]+
matrix1[9]*matrix2[10]+
matrix1[13]*matrix2[11];
result[13]=matrix1[1]*matrix2[12]+
matrix1[5]*matrix2[13]+
matrix1[9]*matrix2[14]+
matrix1[13]*matrix2[15];
result[2]=matrix1[2]*matrix2[0]+
matrix1[6]*matrix2[1]+
matrix1[10]*matrix2[2]+
matrix1[14]*matrix2[3];
result[6]=matrix1[2]*matrix2[4]+
matrix1[6]*matrix2[5]+
matrix1[10]*matrix2[6]+
matrix1[14]*matrix2[7];
result[10]=matrix1[2]*matrix2[8]+
matrix1[6]*matrix2[9]+
matrix1[10]*matrix2[10]+
matrix1[14]*matrix2[11];
result[14]=matrix1[2]*matrix2[12]+
matrix1[6]*matrix2[13]+
matrix1[10]*matrix2[14]+
matrix1[14]*matrix2[15];
result[3]=matrix1[3]*matrix2[0]+
matrix1[7]*matrix2[1]+
matrix1[11]*matrix2[2]+
matrix1[15]*matrix2[3];
result[7]=matrix1[3]*matrix2[4]+
matrix1[7]*matrix2[5]+
matrix1[11]*matrix2[6]+
matrix1[15]*matrix2[7];
result[11]=matrix1[3]*matrix2[8]+
matrix1[7]*matrix2[9]+
matrix1[11]*matrix2[10]+
matrix1[15]*matrix2[11];
result[15]=matrix1[3]*matrix2[12]+
matrix1[7]*matrix2[13]+
matrix1[11]*matrix2[14]+
matrix1[15]*matrix2[15];
}
void MultiplyMatrixByVector4by4OpenGL_FLOAT(float *resultvector, const float *matrix, const float *pvector)
{
resultvector[0]=matrix[0]*pvector[0]+matrix[4]*pvector[1]+matrix[8]*pvector[2]+matrix[12]*pvector[3];
resultvector[1]=matrix[1]*pvector[0]+matrix[5]*pvector[1]+matrix[9]*pvector[2]+matrix[13]*pvector[3];
resultvector[2]=matrix[2]*pvector[0]+matrix[6]*pvector[1]+matrix[10]*pvector[2]+matrix[14]*pvector[3];
resultvector[3]=matrix[3]*pvector[0]+matrix[7]*pvector[1]+matrix[11]*pvector[2]+matrix[15]*pvector[3];
}
#define SWAP_ROWS_DOUBLE(a, b) { double *_tmp = a; (a)=(b); (b)=_tmp; }
#define SWAP_ROWS_FLOAT(a, b) { float *_tmp = a; (a)=(b); (b)=_tmp; }
#define MAT(m,r,c) (m)[(c)*4+(r)]
//This code comes directly from GLU except that it is for float
int glhInvertMatrixf2(float *m, float *out)
{
float wtmp[4][8];
float m0, m1, m2, m3, s;
float *r0, *r1, *r2, *r3;
r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
r0[0] = MAT(m, 0, 0), r0[1] = MAT(m, 0, 1),
r0[2] = MAT(m, 0, 2), r0[3] = MAT(m, 0, 3),
r0[4] = 1.0f, r0[5] = r0[6] = r0[7] = 0.0f,
r1[0] = MAT(m, 1, 0), r1[1] = MAT(m, 1, 1),
r1[2] = MAT(m, 1, 2), r1[3] = MAT(m, 1, 3),
r1[5] = 1.0f, r1[4] = r1[6] = r1[7] = 0.0f,
r2[0] = MAT(m, 2, 0), r2[1] = MAT(m, 2, 1),
r2[2] = MAT(m, 2, 2), r2[3] = MAT(m, 2, 3),
r2[6] = 1.0f, r2[4] = r2[5] = r2[7] = 0.0f,
r3[0] = MAT(m, 3, 0), r3[1] = MAT(m, 3, 1),
r3[2] = MAT(m, 3, 2), r3[3] = MAT(m, 3, 3),
r3[7] = 1.0f, r3[4] = r3[5] = r3[6] = 0.0f;
/* choose pivot - or die */
if (fabsf(r3[0]) > fabsf(r2[0]))
SWAP_ROWS_FLOAT(r3, r2);
if (fabsf(r2[0]) > fabsf(r1[0]))
SWAP_ROWS_FLOAT(r2, r1);
if (fabsf(r1[0]) > fabsf(r0[0]))
SWAP_ROWS_FLOAT(r1, r0);
if (0.0f == r0[0])
return 0;
/* eliminate first variable */
m1 = r1[0] / r0[0];
m2 = r2[0] / r0[0];
m3 = r3[0] / r0[0];
s = r0[1];
r1[1] -= m1 * s;
r2[1] -= m2 * s;
r3[1] -= m3 * s;
s = r0[2];
r1[2] -= m1 * s;
r2[2] -= m2 * s;
r3[2] -= m3 * s;
s = r0[3];
r1[3] -= m1 * s;
r2[3] -= m2 * s;
r3[3] -= m3 * s;
s = r0[4];
if (s != 0.0f) {
r1[4] -= m1 * s;
r2[4] -= m2 * s;
r3[4] -= m3 * s;
}
s = r0[5];
if (s != 0.0f) {
r1[5] -= m1 * s;
r2[5] -= m2 * s;
r3[5] -= m3 * s;
}
s = r0[6];
if (s != 0.0f) {
r1[6] -= m1 * s;
r2[6] -= m2 * s;
r3[6] -= m3 * s;
}
s = r0[7];
if (s != 0.0f) {
r1[7] -= m1 * s;
r2[7] -= m2 * s;
r3[7] -= m3 * s;
}
/* choose pivot - or die */
if (fabsf(r3[1]) > fabsf(r2[1]))
SWAP_ROWS_FLOAT(r3, r2);
if (fabsf(r2[1]) > fabsf(r1[1]))
SWAP_ROWS_FLOAT(r2, r1);
if (0.0f == r1[1])
return 0;
/* eliminate second variable */
m2 = r2[1] / r1[1];
m3 = r3[1] / r1[1];
r2[2] -= m2 * r1[2];
r3[2] -= m3 * r1[2];
r2[3] -= m2 * r1[3];
r3[3] -= m3 * r1[3];
s = r1[4];
if (0.0f != s) {
r2[4] -= m2 * s;
r3[4] -= m3 * s;
}
s = r1[5];
if (0.0f != s) {
r2[5] -= m2 * s;
r3[5] -= m3 * s;
}
s = r1[6];
if (0.0f != s) {
r2[6] -= m2 * s;
r3[6] -= m3 * s;
}
s = r1[7];
if (0.0f != s) {
r2[7] -= m2 * s;
r3[7] -= m3 * s;
}
/* choose pivot - or die */
if (fabsf(r3[2]) > fabsf(r2[2]))
SWAP_ROWS_FLOAT(r3, r2);
if (0.0f == r2[2])
return 0;
/* eliminate third variable */
m3 = r3[2] / r2[2];
r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], r3[7] -= m3 * r2[7];
/* last check */
if (0.0f == r3[3])
return 0;
s = 1.0f / r3[3]; /* now back substitute row 3 */
r3[4] *= s;
r3[5] *= s;
r3[6] *= s;
r3[7] *= s;
m2 = r2[3]; /* now back substitute row 2 */
s = 1.0f / r2[2];
r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
m1 = r1[3];
r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
m0 = r0[3];
r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
m1 = r1[2]; /* now back substitute row 1 */
s = 1.0f / r1[1];
r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
m0 = r0[2];
r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
m0 = r0[1]; /* now back substitute row 0 */
s = 1.0f / r0[0];
r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
MAT(out, 0, 0) = r0[4];
MAT(out, 0, 1) = r0[5], MAT(out, 0, 2) = r0[6];
MAT(out, 0, 3) = r0[7], MAT(out, 1, 0) = r1[4];
MAT(out, 1, 1) = r1[5], MAT(out, 1, 2) = r1[6];
MAT(out, 1, 3) = r1[7], MAT(out, 2, 0) = r2[4];
MAT(out, 2, 1) = r2[5], MAT(out, 2, 2) = r2[6];
MAT(out, 2, 3) = r2[7], MAT(out, 3, 0) = r3[4];
MAT(out, 3, 1) = r3[5], MAT(out, 3, 2) = r3[6];
MAT(out, 3, 3) = r3[7];
return 1;
}
int glhUnProjectf( float winx, float winy, float winz,
float *modelview, float *projection,
int *viewport, float *objectCoordinate)
{
//Transformation matrices
float m[16], A[16];
float in[4], out[4];
//Calculation for inverting a matrix, compute projection x modelview
//and store in A[16]
MultiplyMatrices4by4OpenGL_FLOAT(A, projection, modelview);
//Now compute the inverse of matrix A
if(glhInvertMatrixf2(A, m)==0)
return 0;
//Transformation of normalized coordinates between -1 and 1
in[0]=(winx-(float)viewport[0])/(float)viewport[2]*2.0f-1.0f;
in[1]=(winy-(float)viewport[1])/(float)viewport[3]*2.0f-1.0f;
in[2]=2.0f*winz-1.0f;
in[3]=1.0f;
//Objects coordinates
MultiplyMatrixByVector4by4OpenGL_FLOAT(out, m, in);
if(out[3]==0.0f)
return 0;
out[3]=1.0f/out[3];
objectCoordinate[0]=out[0]*out[3];
objectCoordinate[1]=out[1]*out[3];
objectCoordinate[2]=out[2]*out[3];
return 1;
}

143
src/client/renderer/gles.h Executable file
View File

@@ -0,0 +1,143 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER__gles_H__
#define NET_MINECRAFT_CLIENT_RENDERER__gles_H__
#include "../../platform/log.h"
#include "../Options.h"
// Android should always run OPENGL_ES
#if defined(ANDROID) || defined(__APPLE__) || defined(RPI)
#define OPENGL_ES
#endif
// Other systems might run it, if they #define OPENGL_ES
#if defined(OPENGL_ES) // || defined(ANDROID)
#define USE_VBO
#define GL_QUADS 0x0007
#if defined(__APPLE__)
#import <OpenGLES/ES1/gl.height>
#import <OpenGLES/ES1/glext.height>
#else
// #include <GLES/gl.h>
#include <glad/glad.h>
#if defined(ANDROID)
#include<GLES/glext.h>
#endif
#endif
#else
// Uglyness to fix redeclaration issues
#ifdef WIN32
#include <WinSock2.h>
#include <Windows.h>
#endif
// #include <gl/glew.h>
// #include <gl/GL.h>
#define glFogx(a,b) glFogi(a,b)
#define glOrthof(a,b,c,d,e,f) glOrtho(a,b,c,d,e,f)
#endif
#define GLERRDEBUG 1
#if GLERRDEBUG
//#define GLERR(x) if((x) != 0) { LOGI("GLError: " #x "(%d)\n", __LINE__) }
#define GLERR(x) do { const int errCode = glGetError(); if (errCode != 0) LOGE("OpenGL ERROR @%d: #%d @ (%s : %d)\n", x, errCode, __FILE__, __LINE__); } while (0)
#else
#define GLERR(x) x
#endif
void anGenBuffers(GLsizei n, GLuint* buffer);
#ifdef USE_VBO
#define drawArrayVT_NoState drawArrayVT
#define drawArrayVTC_NoState drawArrayVTC
void drawArrayVT(int bufferId, int vertices, int vertexSize = 24, unsigned int mode = GL_TRIANGLES);
#ifndef drawArrayVT_NoState
//void drawArrayVT_NoState(int bufferId, int vertices, int vertexSize = 24);
#endif
void drawArrayVTC(int bufferId, int vertices, int vertexSize = 24);
#ifndef drawArrayVTC_NoState
void drawArrayVTC_NoState(int bufferId, int vertices, int vertexSize = 24);
#endif
#endif
void glInit();
void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
int glhUnProjectf( float winx, float winy, float winz,
float *modelview, float *projection,
int *viewport, float *objectCoordinate);
// Used for "debugging" (...). Obviously stupid dependency on Options (and ugly gl*2 calls).
#ifdef GLDEBUG
#define glTranslatef2(x, y, z) do{ if (Options::debugGl) LOGI("glTrans @ %s:%d: %f,%f,%f\n", __FILE__, __LINE__, x, y, z); glTranslatef(x, y, z); GLERR(0); } while(0)
#define glRotatef2(a, x, y, z) do{ if (Options::debugGl) LOGI("glRotat @ %s:%d: %f,%f,%f,%f\n", __FILE__, __LINE__, a, x, y, z); glRotatef(a, x, y, z); GLERR(1); } while(0)
#define glScalef2(x, y, z) do{ if (Options::debugGl) LOGI("glScale @ %s:%d: %f,%f,%f\n", __FILE__, __LINE__, x, y, z); glScalef(x, y, z); GLERR(2); } while(0)
#define glPushMatrix2() do{ if (Options::debugGl) LOGI("glPushM @ %s:%d\n", __FILE__, __LINE__); glPushMatrix(); GLERR(3); } while(0)
#define glPopMatrix2() do{ if (Options::debugGl) LOGI("glPopM @ %s:%d\n", __FILE__, __LINE__); glPopMatrix(); GLERR(4); } while(0)
#define glLoadIdentity2() do{ if (Options::debugGl) LOGI("glLoadI @ %s:%d\n", __FILE__, __LINE__); glLoadIdentity(); GLERR(5); } while(0)
#define glVertexPointer2(a, b, c, d) do{ if (Options::debugGl) LOGI("glVertexPtr @ %s:%d : %d\n", __FILE__, __LINE__, 0); glVertexPointer(a, b, c, d); GLERR(6); } while(0)
#define glColorPointer2(a, b, c, d) do{ if (Options::debugGl) LOGI("glColorPtr @ %s:%d : %d\n", __FILE__, __LINE__, 0); glColorPointer(a, b, c, d); GLERR(7); } while(0)
#define glTexCoordPointer2(a, b, c, d) do{ if (Options::debugGl) LOGI("glTexPtr @ %s:%d : %d\n", __FILE__, __LINE__, 0); glTexCoordPointer(a, b, c, d); GLERR(8); } while(0)
#define glEnableClientState2(s) do{ if (Options::debugGl) LOGI("glEnableClient @ %s:%d : %d\n", __FILE__, __LINE__, 0); glEnableClientState(s); GLERR(9); } while(0)
#define glDisableClientState2(s) do{ if (Options::debugGl) LOGI("glDisableClient @ %s:%d : %d\n", __FILE__, __LINE__, 0); glDisableClientState(s); GLERR(10); } while(0)
#define glDrawArrays2(m, o, v) do{ if (Options::debugGl) LOGI("glDrawA @ %s:%d : %d\n", __FILE__, __LINE__, 0); glDrawArrays(m,o,v); GLERR(11); } while(0)
#define glTexParameteri2(m, o, v) do{ if (Options::debugGl) LOGI("glTexParameteri @ %s:%d : %d\n", __FILE__, __LINE__, v); glTexParameteri(m,o,v); GLERR(12); } while(0)
#define glTexImage2D2(a,b,c,d,e,f,g,height,i) do{ if (Options::debugGl) LOGI("glTexImage2D @ %s:%d : %d\n", __FILE__, __LINE__, 0); glTexImage2D(a,b,c,d,e,f,g,height,i); GLERR(13); } while(0)
#define glTexSubImage2D2(a,b,c,d,e,f,g,height,i) do{ if (Options::debugGl) LOGI("glTexSubImage2D @ %s:%d : %d\n", __FILE__, __LINE__, 0); glTexSubImage2D(a,b,c,d,e,f,g,height,i); GLERR(14); } while(0)
#define glGenBuffers2(s, id) do{ if (Options::debugGl) LOGI("glGenBuffers @ %s:%d : %d\n", __FILE__, __LINE__, id); anGenBuffers(s, id); GLERR(15); } while(0)
#define glBindBuffer2(s, id) do{ if (Options::debugGl) LOGI("glBindBuffer @ %s:%d : %d\n", __FILE__, __LINE__, id); glBindBuffer(s, id); GLERR(16); } while(0)
#define glBufferData2(a, b, c, d) do{ if (Options::debugGl) LOGI("glBufferData @ %s:%d : %d\n", __FILE__, __LINE__, d); glBufferData(a, b, c, d); GLERR(17); } while(0)
#define glBindTexture2(m, z) do{ if (Options::debugGl) LOGI("glBindTexture @ %s:%d : %d\n", __FILE__, __LINE__, z); glBindTexture(m, z); GLERR(18); } while(0)
#define glEnable2(s) do{ if (Options::debugGl) LOGI("glEnable @ %s:%d : %d\n", __FILE__, __LINE__, s); glEnable(s); GLERR(19); } while(0)
#define glDisable2(s) do{ if (Options::debugGl) LOGI("glDisable @ %s:%d : %d\n", __FILE__, __LINE__, s); glDisable(s); GLERR(20); } while(0)
#define glColor4f2(r, g, b, a) do{ if (Options::debugGl) LOGI("glColor4f2 @ %s:%d : (%f,%f,%f,%f)\n", __FILE__, __LINE__, r,g,b,a); glColor4f(r,g,b,a); GLERR(21); } while(0)
//#define glBlendMode2(s) do{ if (Options::debugGl) LOGI("glEnable @ %s:%d : %d\n", __FILE__, __LINE__, s); glEnable(s); GLERR(19); } while(0)
#define glBlendFunc2(src, dst) do{ if (Options::debugGl) LOGI("glBlendFunc @ %s:%d : %d - %d\n", __FILE__, __LINE__, src, dst); glBlendFunc(src, dst); GLERR(23); } while(0)
#define glShadeModel2(s) do{ if (Options::debugGl) LOGI("glShadeModel @ %s:%d : %d\n", __FILE__, __LINE__, s); glShadeModel(s); GLERR(25); } while(0)
#else
#define glTranslatef2 glTranslatef
#define glRotatef2 glRotatef
#define glScalef2 glScalef
#define glPushMatrix2 glPushMatrix
#define glPopMatrix2 glPopMatrix
#define glLoadIdentity2 glLoadIdentity
#define glVertexPointer2 glVertexPointer
#define glColorPointer2 glColorPointer
#define glTexCoordPointer2 glTexCoordPointer
#define glEnableClientState2 glEnableClientState
#define glDisableClientState2 glDisableClientState
#define glDrawArrays2 glDrawArrays
#define glTexParameteri2 glTexParameteri
#define glTexImage2D2 glTexImage2D
#define glTexSubImage2D2 glTexSubImage2D
#define glGenBuffers2 anGenBuffers
#define glBindBuffer2 glBindBuffer
#define glBufferData2 glBufferData
#define glBindTexture2 glBindTexture
#define glEnable2 glEnable
#define glDisable2 glDisable
#define glColor4f2 glColor4f
#define glBlendFunc2 glBlendFunc
#define glShadeModel2 glShadeModel
#endif
//
// Extensions
//
#ifdef WIN32
#define glGetProcAddress(a) wglGetProcAddress(a)
#else
#define glGetProcAddress(a) (void*(0))
#endif
#endif /*NET_MINECRAFT_CLIENT_RENDERER__gles_H__ */

View File

@@ -0,0 +1,208 @@
#include "DynamicTexture.h"
#include <cstring>
#include "../Textures.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../util/Mth.h"
//
// DynamicTexture
//
DynamicTexture::DynamicTexture(int tex_)
: tex(tex_),
replicate(1)
{
memset(pixels, 0, 16*16*4);
}
void DynamicTexture::bindTexture(Textures* tex) {
tex->loadAndBindTexture("terrain.png");
}
//
// WaterTexture
// I was thinking of adding something simple (a simple frame copy from a
// "still water image sequence") every n:th tick for calm water, and shifting
// the rows of a texture for the running water. I might do that, but I got
// impressed over the java code, so I will try that first.. and I suspect they
// wont mix very good.
/*
WaterTexture::WaterTexture()
: super(Tile::water->tex),
_tick(0),
_frame(0)
{
}
void WaterTexture::tick() {
}
*/
WaterTexture::WaterTexture()
: super(Tile::water->tex),
_tick(0),
_frame(0)
{
current = new float[16*16];
next = new float[16*16];
heat = new float[16*16];
heata = new float[16*16];
for (int i = 0; i < 256; ++i) {
current[i] = 0;
next[i] = 0;
heat[i] = 0;
heata[i] = 0;
}
}
WaterTexture::~WaterTexture() {
delete[] current;
delete[] next;
delete[] heat;
delete[] heata;
}
void WaterTexture::tick()
{
for (int x = 0; x < 16; x++)
for (int y = 0; y < 16; y++) {
float pow = 0;
for (int xx = x - 1; xx <= x + 1; xx++) {
int xi = (xx) & 15;
int yi = (y) & 15;
pow += current[xi + yi * 16];
}
next[x + y * 16] = pow / 3.3f + heat[x + y * 16] * 0.8f;
}
for (int x = 0; x < 16; x++)
for (int y = 0; y < 16; y++) {
heat[x + y * 16] += heata[x + y * 16] * 0.05f;
if (heat[x + y * 16] < 0) heat[x + y * 16] = 0;
heata[x + y * 16] -= 0.1f;
if (Mth::random() < 0.05f) {
heata[x + y * 16] = 0.5f;
}
}
float* tmp = next;
next = current;
current = tmp;
for (int i = 0; i < 256; i++) {
float pow = current[i];
if (pow > 1) pow = 1;
if (pow < 0) pow = 0;
float pp = pow * pow;
int r = (int) (32 + pp * 32);
int g = (int) (50 + pp * 64);
int b = (int) (255);
int a = (int) (146 + pp * 50);
//if (anaglyph3d) {
// int rr = (r * 30 + g * 59 + b * 11) / 100;
// int gg = (r * 30 + g * 70) / (100);
// int bb = (r * 30 + b * 70) / (100);
// r = rr;
// g = gg;
// b = bb;
//}
pixels[i * 4 + 0] = r;
pixels[i * 4 + 1] = g;
pixels[i * 4 + 2] = b;
pixels[i * 4 + 3] = a;
}
}
//
// WaterSideTexture
//
WaterSideTexture::WaterSideTexture()
: super(Tile::water->tex + 1),
_tick(0),
_frame(0),
_tickCount(0)
{
replicate = 2;
current = new float[16*16];
next = new float[16*16];
heat = new float[16*16];
heata = new float[16*16];
for (int i = 0; i < 256; ++i) {
current[i] = 0;
next[i] = 0;
heat[i] = 0;
heata[i] = 0;
}
}
WaterSideTexture::~WaterSideTexture() {
delete[] current;
delete[] next;
delete[] heat;
delete[] heata;
}
void WaterSideTexture::tick() {
++_tickCount;
for (int x = 0; x < 16; x++)
for (int y = 0; y < 16; y++) {
float pow = 0;
for (int xx = y - 2; xx <= y; xx++) {
int xi = (x) & 15;
int yi = (xx) & 15;
pow += current[xi + yi * 16];
}
next[x + y * 16] = pow / 3.2f + heat[x + y * 16] * 0.8f;
}
for (int x = 0; x < 16; x++)
for (int y = 0; y < 16; y++) {
heat[x + y * 16] += heata[x + y * 16] * 0.05f;
if (heat[x + y * 16] < 0) heat[x + y * 16] = 0;
heata[x + y * 16] -= 0.3f;
if (Mth::random() < 0.2) {
heata[x + y * 16] = 0.5f;
}
}
float* tmp = next;
next = current;
current = tmp;
for (int i = 0; i < 256; i++) {
float pow = current[(i - _tickCount * 16) & 255];
if (pow > 1) pow = 1;
if (pow < 0) pow = 0;
float pp = pow * pow;
int r = (int) (32 + pp * 32);
int g = (int) (50 + pp * 64);
int b = (int) (255);
int a = (int) (146 + pp * 50);
//if (anaglyph3d) {
// int rr = (r * 30 + g * 59 + b * 11) / 100;
// int gg = (r * 30 + g * 70) / (100);
// int bb = (r * 30 + b * 70) / (100);
// r = rr;
// g = gg;
// b = bb;
//}
pixels[i * 4 + 0] = r;
pixels[i * 4 + 1] = g;
pixels[i * 4 + 2] = b;
pixels[i * 4 + 3] = a;
}
}

View File

@@ -0,0 +1,59 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_PTEXTURE__DynamicTexture_H__
#define NET_MINECRAFT_CLIENT_RENDERER_PTEXTURE__DynamicTexture_H__
#include <vector>
class Textures;
class DynamicTexture
{
public:
int tex;
int replicate;
unsigned char pixels[16*16*4];
DynamicTexture(int tex_);
virtual ~DynamicTexture() {}
virtual void tick() = 0;
virtual void bindTexture(Textures* tex);
};
class WaterTexture: public DynamicTexture
{
typedef DynamicTexture super;
int _tick;
int _frame;
float* current;
float* next;
float* heat;
float* heata;
public:
WaterTexture();
~WaterTexture();
void tick();
};
class WaterSideTexture: public DynamicTexture
{
typedef DynamicTexture super;
int _tick;
int _frame;
int _tickCount;
float* current;
float* next;
float* heat;
float* heata;
public:
WaterSideTexture();
~WaterSideTexture();
void tick();
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_PTEXTURE__DynamicTexture_H__*/

View File

@@ -0,0 +1,76 @@
#include "ChestRenderer.h"
#include "TileEntityRenderer.h"
#include "../gles.h"
#include "../../model/ChestModel.h"
#include "../../../world/level/tile/entity/ChestTileEntity.h"
#include "../../../world/level/tile/ChestTile.h"
#include "../../../util/Mth.h"
void ChestRenderer::render( TileEntity* entity, float x, float y, float z, float a )
{
ChestTileEntity* chest = (ChestTileEntity*) entity;
int data = 0;
if (chest->level) {
Tile* tile = chest->getTile();
data = chest->getData();
if (tile != NULL && data == 0) {
((ChestTile*)tile)->recalcLockDir(chest->level, chest->x, chest->y, chest->z);
data = chest->getData();
}
chest->checkNeighbors();
}
if (chest->n != NULL || chest->w != NULL) return;
ChestModel* model;
//if (chest->e != NULL || chest->s != NULL) {
// //model = &largeChestModel;
// bindTexture("item/largechest.png");
//} else
{
model = &chestModel;
bindTexture("item/chest.png");
}
glPushMatrix2();
glColor4f2(1, 1, 1, 1);
glTranslatef2(x, y + 1, z + 1);
glScalef2(1, -1, -1);
glTranslatef2(0.5f, 0.5f, 0.5f);
GLfloat rot = 0;
if (data == 2) rot = 180;
if (data == 3) rot = 0;
if (data == 4) rot = 90;
if (data == 5) rot = -90;
if (data == 2 && chest->e != NULL) {
glTranslatef2(1, 0, 0);
}
if (data == 5 && chest->s != NULL) {
glTranslatef2(0, 0, -1);
}
glRotatef2(rot, 0, 1, 0);
glTranslatef2(-0.5f, -0.5f, -0.5f);
float open = chest->oOpenness + (chest->openness - chest->oOpenness) * a;
if (chest->n != NULL) {
float open2 = chest->n->oOpenness + (chest->n->openness - chest->n->oOpenness) * a;
if (open2 > open) open = open2;
}
if (chest->w != NULL) {
float open2 = chest->w->oOpenness + (chest->w->openness - chest->w->oOpenness) * a;
if (open2 > open) open = open2;
}
open = 1 - open;
open = 1 - open * open * open;
model->lid.xRot = -(open * Mth::PI / 2);
model->render();
glPopMatrix2();
glColor4f2(1, 1, 1, 1);
}

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__ChestRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__ChestRenderer_H__
//package net.minecraft.client.renderer.tileentity;
#include "TileEntityRenderer.h"
#include "../../model/ChestModel.h"
class ChestTileEntity;
class ChestRenderer: public TileEntityRenderer
{
/*@Override*/
void render(TileEntity* chest, float x, float y, float z, float a);
private:
ChestModel chestModel;
//LargeChestModel* largeChestModel;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__ChestRenderer_H__*/

View File

@@ -0,0 +1,65 @@
#include "SignRenderer.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../world/level/tile/entity/SignTileEntity.h"
void SignRenderer::render( TileEntity* te, float x, float y, float z, float a )
{
SignTileEntity* sign = (SignTileEntity*) te;
Tile* tile = sign->getTile();
glPushMatrix();
float size = 16 / 24.0f;
if (tile == Tile::sign) {
glTranslatef(x + 0.5f, y + 0.75f * size, z + 0.5f);
float rot = sign->getData() * 360 / 16.0f;
glRotatef(-rot, 0, 1, 0);
signModel.cube2.visible = true;
} else {
int face = sign->getData();
float rot = 0;
if (face == 2) rot = 180;
if (face == 4) rot = 90;
if (face == 5) rot = -90;
glTranslatef(x + 0.5f, y + 0.75f * size, z + 0.5f);
glRotatef(-rot, 0, 1, 0);
glTranslatef(0, -5 / 16.0f, -7 / 16.0f);
signModel.cube2.visible = false;
}
bindTexture("item/sign.png");
glPushMatrix();
glScalef(size, -size, -size);
signModel.render();
glPopMatrix();
Font* font = getFont();
float s = 1 / 60.0f * size;
glTranslatef(0, 0.5f * size, 0.07f * size);
glScalef(s, -s, s);
glNormal3f(0, 0, -1 * s);
glDepthMask(false);
int col = 0;
float yy = (float)(SignTileEntity::NUM_LINES * -5);
for (int i = 0; i < SignTileEntity::NUM_LINES; i++) {
std::string& msg = sign->messages[i];
if (i == sign->selectedLine) {
std::string s = "> " + msg + " <";
font->draw(s, (float)-font->width(s) / 2, yy, col);
} else {
font->draw(msg, (float)-font->width(msg) / 2, yy, col);
}
yy += 10;
}
glDepthMask(true);
glColor4f(1, 1, 1, 1);
glPopMatrix();
}
void SignRenderer::onGraphicsReset() {
signModel.onGraphicsReset();
}

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__SignRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__SignRenderer_H__
//package net.minecraft.client.renderer.tileentity;
#include "TileEntityRenderer.h"
#include "../../gui/Font.h"
#include "../../model/SignModel.h"
class SignRenderer: public TileEntityRenderer
{
public:
/*@Override*/
void render(TileEntity* te, float x, float y, float z, float a);
void onGraphicsReset();
private:
SignModel signModel;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__SignRenderer_H__*/

View File

@@ -0,0 +1,136 @@
#include "TileEntityRenderDispatcher.h"
#include "ChestRenderer.h"
#include "../Textures.h"
#include "../../gui/Font.h"
#include "../../../SharedConstants.h"
#include "../../../world/entity/Mob.h"
#include "../../../world/level/Level.h"
#include "../../../world/level/tile/entity/TileEntity.h"
#include "SignRenderer.h"
/*static*/
TileEntityRenderDispatcher* TileEntityRenderDispatcher::instance = 0;
/*static*/
float TileEntityRenderDispatcher::xOff = 0,
TileEntityRenderDispatcher::yOff = 0,
TileEntityRenderDispatcher::zOff = 0;
TileEntityRenderDispatcher* TileEntityRenderDispatcher::getInstance()
{
if (!instance) instance = new TileEntityRenderDispatcher();
return instance;
}
TileEntityRenderDispatcher::~TileEntityRenderDispatcher()
{
std::set<TileEntityRenderer*> destroyed;
for (RendererCIterator cit = _renderers.begin(); cit != _renderers.end(); ++cit) {
if (destroyed.find(cit->second) == destroyed.end()) {
destroyed.insert(cit->second);
delete cit->second;
}
}
}
void TileEntityRenderDispatcher::destroy()
{
if (instance) {
delete instance;
instance = NULL;
}
}
void TileEntityRenderDispatcher::prepare( Level* level, Textures* textures, Font* font, Mob* player, float a )
{
if (this->level != level)
setLevel(level);
this->textures = textures;
this->cameraEntity = player;
this->_font = font;
playerRotY = player->yRotO + (player->yRot - player->yRotO) * a;
playerRotX = player->xRotO + (player->xRot - player->xRotO) * a;
xPlayer = player->xOld + (player->x - player->xOld) * a;
yPlayer = player->yOld + (player->y - player->yOld) * a;
zPlayer = player->zOld + (player->z - player->zOld) * a;
// xPlayer -= xPlayerOffs;
// yPlayer -= yPlayerOffs;
// zPlayer -= zPlayerOffs;
}
void TileEntityRenderDispatcher::render( TileEntity* e, float a )
{
if (e->distanceToSqr(xPlayer, yPlayer, zPlayer) < 64 * 64) {
float br = level->getBrightness(e->x, e->y, e->z);
glColor4f(br, br, br, 1);
render(e, e->x - xOff, e->y - yOff, e->z - zOff, a);
}
}
void TileEntityRenderDispatcher::render( TileEntity* entity, float x, float y, float z, float a )
{
TileEntityRenderer* renderer = getRenderer(entity);
if (renderer != NULL) {
renderer->render(entity, x, y, z, a);
}
}
void TileEntityRenderDispatcher::setLevel( Level* level )
{
this->level = level;
for (RendererCIterator cit = _renderers.begin(); cit != _renderers.end(); ++cit)
if (cit->second != NULL)
cit->second->onNewLevel(level);
}
float TileEntityRenderDispatcher::distanceToSqr( float x, float y, float z )
{
float xd = x - xPlayer;
float yd = y - yPlayer;
float zd = z - zPlayer;
return xd * xd + yd * yd + zd * zd;
}
Font* TileEntityRenderDispatcher::getFont()
{
return _font;
}
TileEntityRenderer* TileEntityRenderDispatcher::getRenderer( TileEntity* entity )
{
TileEntityRendererId rendererId = entity->rendererId;
//if (rendererId == TR_QUERY_RENDERER)
// rendererId = entity->queryEntityRenderer();
return getRenderer(rendererId);
}
TileEntityRenderer* TileEntityRenderDispatcher::getRenderer( TileEntityRendererId rendererId )
{
TileEntityRenderer* renderer = NULL;
RendererCIterator cit = _renderers.find(rendererId);
if (cit != _renderers.end()) {
renderer = cit->second;
}
return renderer;
}
TileEntityRenderDispatcher::TileEntityRenderDispatcher()
{
_renderers.insert(std::make_pair(TR_CHEST_RENDERER, new ChestRenderer()));
_renderers.insert(std::make_pair(TR_SIGN_RENDERER, new SignRenderer()));
for (RendererCIterator cit = _renderers.begin(); cit != _renderers.end(); ++cit)
cit->second->init(this);
}
void TileEntityRenderDispatcher::onGraphicsReset() {
for (RendererIterator it = _renderers.begin(); it != _renderers.end(); ++it) {
it->second->onGraphicsReset();
}
}

View File

@@ -0,0 +1,61 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__TileEntityRenderDispatcher_H__
#define NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__TileEntityRenderDispatcher_H__
//package net.minecraft.client.renderer.tileentity;
#include <map>
#include "../../../world/level/tile/entity/TileEntityRendererId.h"
class TileEntityRenderer;
class Level;
class Textures;
class TileEntity;
class Font;
class Mob;
class TileEntityRenderDispatcher
{
typedef std::map<TileEntityRendererId, TileEntityRenderer*> RendererMap;
typedef RendererMap::iterator RendererIterator;
typedef RendererMap::const_iterator RendererCIterator;
public:
~TileEntityRenderDispatcher();
static TileEntityRenderDispatcher* getInstance();
static void destroy();
void setLevel(Level* level);
void prepare(Level* level, Textures* textures, Font* font, Mob* player, float a);
void render(TileEntity* e, float a);
void render(TileEntity* entity, float x, float y, float z, float a);
float distanceToSqr(float x, float y, float z);
Font* getFont();
TileEntityRenderer* getRenderer( TileEntity* entity );
TileEntityRenderer* getRenderer( TileEntityRendererId rendererId );
void onGraphicsReset();
private:
TileEntityRenderDispatcher();
public:
static float xOff, yOff, zOff;
Textures* textures;
Level* level;
Mob* cameraEntity;
float playerRotY;
float playerRotX;
float xPlayer, yPlayer, zPlayer;
private:
static TileEntityRenderDispatcher* instance;
Font* _font;
RendererMap _renderers;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__TileEntityRenderDispatcher_H__*/

View File

@@ -0,0 +1,32 @@
#include "TileEntityRenderer.h"
#include "TileEntityRenderDispatcher.h"
#include "../Textures.h"
#include "../../gui/Font.h"
#include "../../../world/level/Level.h"
#include "../../../world/level/tile/entity/TileEntity.h"
TileEntityRenderer::TileEntityRenderer()
: tileEntityRenderDispatcher(NULL)
{
}
void TileEntityRenderer::bindTexture( const std::string& resourceName )
{
Textures* t = tileEntityRenderDispatcher->textures;
if (t != NULL) t->loadAndBindTexture(resourceName);
}
Level* TileEntityRenderer::getLevel()
{
return tileEntityRenderDispatcher->level;
}
void TileEntityRenderer::init( TileEntityRenderDispatcher* tileEntityRenderDispatcher )
{
this->tileEntityRenderDispatcher = tileEntityRenderDispatcher;
}
Font* TileEntityRenderer::getFont()
{
return tileEntityRenderDispatcher->getFont();
}

View File

@@ -0,0 +1,38 @@
#ifndef NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__TileEntityRenderer_H__
#define NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__TileEntityRenderer_H__
//package net.minecraft.client.renderer.tileentity;
#include <string>
class Level;
class TileEntity;
class TileEntityRenderDispatcher;
class Font;
class TileEntityRenderer
{
public:
TileEntityRenderer();
virtual ~TileEntityRenderer(){}
void init(TileEntityRenderDispatcher* tileEntityRenderDispatcher);
virtual void render(TileEntity* entity, float x, float y, float z, float a) = 0;
void bindTexture(const std::string& resourceName);
// /*protected*/ void bindTexture(const std::string& urlTexture, const std::string& backupTexture) {
// Textures t = tileEntityRenderDispatcher.textures;
// if (t != NULL) t.bind(t.loadHttpTexture(urlTexture, backupTexture));
// }
Level* getLevel();
Font* getFont();
virtual void onGraphicsReset() {}
virtual void onNewLevel(Level* level) {}
protected:
TileEntityRenderDispatcher* tileEntityRenderDispatcher;
};
#endif /*NET_MINECRAFT_CLIENT_RENDERER_TILEENTITY__TileEntityRenderer_H__*/