Files
minecraft-pe-0.6.1/src/client/renderer/ItemInHandRenderer.cpp
2026-03-02 22:04:18 +03:00

534 lines
15 KiB
C++
Executable File

#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];
}
}