aboutsummaryrefslogtreecommitdiff
path: root/src/client/mesh.h
blob: 1ed753c0134101eba9eb4c7579ced9722ee7278d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#pragma once

#include "irrlichttypes_extrabloated.h"
#include "nodedef.h"

/*!
 * Applies shading to a color based on the surface's
 * normal vector.
 */
void applyFacesShading(video::SColor &color, const v3f &normal);

/*
	Create a new cube mesh.
	Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).

	The resulting mesh has 6 materials (up, down, right, left, back, front)
	which must be defined by the caller.
*/
scene::IAnimatedMesh* createCubeMesh(v3f scale);

/*
	Multiplies each vertex coordinate by the specified scaling factors
	(componentwise vector multiplication).
*/
void scaleMesh(scene::IMesh *mesh, v3f scale);

/*
	Translate each vertex coordinate by the specified vector.
*/
void translateMesh(scene::IMesh *mesh, v3f vec);

/*!
 * Sets a constant color for all vertices in the mesh buffer.
 */
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color);

/*
	Set a constant color for all vertices in the mesh
*/
void setMeshColor(scene::IMesh *mesh, const video::SColor &color);


/*
	Sets texture coords for vertices in the mesh buffer.
	`uv[]` must have `count` elements
*/
void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count);

/*
	Set a constant color for an animated mesh
*/
void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SColor &color);

/*!
 * Overwrites the color of a mesh buffer.
 * The color is darkened based on the normal vector of the vertices.
 */
void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor);

/*
	Set the color of all vertices in the mesh.
	For each vertex, determine the largest absolute entry in
	the normal vector, and choose one of colorX, colorY or
	colorZ accordingly.
*/
void setMeshColorByNormalXYZ(scene::IMesh *mesh,
		const video::SColor &colorX,
		const video::SColor &colorY,
		const video::SColor &colorZ);

void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal,
		const video::SColor &color);

/*
	Rotate the mesh by 6d facedir value.
	Method only for meshnodes, not suitable for entities.
*/
void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir);

/*
	Rotate the mesh around the axis and given angle in degrees.
*/
void rotateMeshXYby (scene::IMesh *mesh, f64 degrees);
void rotateMeshXZby (scene::IMesh *mesh, f64 degrees);
void rotateMeshYZby (scene::IMesh *mesh, f64 degrees);

/*
 *  Clone the mesh buffer.
 *  The returned pointer should be dropped.
 */
scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer);

/*
	Clone the mesh.
*/
scene::SMesh* cloneMesh(scene::IMesh *src_mesh);

/*
	Convert nodeboxes to mesh. Each tile goes into a different buffer.
	boxes - set of nodeboxes to be converted into cuboids
	uv_coords[24] - table of texture uv coords for each cuboid face
	expand - factor by which cuboids will be resized
*/
scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
		const f32 *uv_coords = NULL, float expand = 0);

/*
	Update bounding box for a mesh.
*/
void recalculateBoundingBox(scene::IMesh *src_mesh);

/*
	Check if mesh has valid normals and return true if it does.
	We assume normal to be valid when it's 0 < length < Inf. and not NaN
 */
bool checkMeshNormals(scene::IMesh *mesh);
255); u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255); crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b); v3f selectionbox_color = g_settings->getV3F("selectionbox_color"); u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255); u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255); u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255); selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b); use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png"); } //NOTE: selectitem = 0 -> no selected; selectitem 1-based void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount, InventoryList *mainlist, u16 selectitem, u16 direction) { s32 padding = imgsize / 12; s32 height = imgsize + padding * 2; s32 width = itemcount * (imgsize + padding * 2); if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) { width = imgsize + padding * 2; height = itemcount * (imgsize + padding * 2); } s32 fullimglen = imgsize + padding * 2; // Position of upper left corner of bar v2s32 pos = upperleftpos; // Draw background color /*core::rect<s32> barrect(0,0,width,height); barrect += pos; video::SColor bgcolor(255,128,128,128); driver->draw2DRectangle(bgcolor, barrect, NULL);*/ core::rect<s32> imgrect(0, 0, imgsize, imgsize); for (s32 i = 0; i < itemcount; i++) { const ItemStack &item = mainlist->getItem(i); v2s32 steppos; switch (direction) { case HUD_DIR_RIGHT_LEFT: steppos = v2s32(-(padding + i * fullimglen), padding); break; case HUD_DIR_TOP_BOTTOM: steppos = v2s32(padding, padding + i * fullimglen); break; case HUD_DIR_BOTTOM_TOP: steppos = v2s32(padding, -(padding + i * fullimglen)); break; default: steppos = v2s32(padding + i * fullimglen, padding); } core::rect<s32> rect = imgrect + pos + steppos; if (selectitem == i + 1) { video::SColor c_outside(255,255,0,0); //video::SColor c_outside(255,0,0,0); //video::SColor c_inside(255,192,192,192); s32 x1 = rect.UpperLeftCorner.X; s32 y1 = rect.UpperLeftCorner.Y; s32 x2 = rect.LowerRightCorner.X; s32 y2 = rect.LowerRightCorner.Y; // Black base borders driver->draw2DRectangle(c_outside, core::rect<s32>( v2s32(x1 - padding, y1 - padding), v2s32(x2 + padding, y1) ), NULL); driver->draw2DRectangle(c_outside, core::rect<s32>( v2s32(x1 - padding, y2), v2s32(x2 + padding, y2 + padding) ), NULL); driver->draw2DRectangle(c_outside, core::rect<s32>( v2s32(x1 - padding, y1), v2s32(x1, y2) ), NULL); driver->draw2DRectangle(c_outside, core::rect<s32>( v2s32(x2, y1), v2s32(x2 + padding, y2) ), NULL); /*// Light inside borders driver->draw2DRectangle(c_inside, core::rect<s32>( v2s32(x1 - padding/2, y1 - padding/2), v2s32(x2 + padding/2, y1) ), NULL); driver->draw2DRectangle(c_inside, core::rect<s32>( v2s32(x1 - padding/2, y2), v2s32(x2 + padding/2, y2 + padding/2) ), NULL); driver->draw2DRectangle(c_inside, core::rect<s32>( v2s32(x1 - padding/2, y1), v2s32(x1, y2) ), NULL); driver->draw2DRectangle(c_inside, core::rect<s32>( v2s32(x2, y1), v2s32(x2 + padding/2, y2) ), NULL); */ } video::SColor bgcolor2(128, 0, 0, 0); driver->draw2DRectangle(bgcolor2, rect, NULL); drawItemStack(driver, font, item, rect, NULL, gamedef); } } void Hud::drawLuaElements() { for (size_t i = 0; i != player->hud.size(); i++) { HudElement *e = player->hud[i]; if (!e) continue; v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y); switch (e->type) { case HUD_ELEM_IMAGE: { video::ITexture *texture = tsrc->getTextureRaw(e->text); if (!texture) continue; const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; core::dimension2di imgsize(texture->getOriginalSize()); core::rect<s32> rect(0, 0, imgsize.Width * e->scale.X, imgsize.Height * e->scale.X); rect += pos; v2s32 offset((e->align.X - 1.0) * ((imgsize.Width * e->scale.X) / 2), (e->align.Y - 1.0) * ((imgsize.Height * e->scale.X) / 2)); rect += offset; rect += v2s32(e->offset.X, e->offset.Y); driver->draw2DImage(texture, rect, core::rect<s32>(core::position2d<s32>(0,0), imgsize), NULL, colors, true); break; } case HUD_ELEM_TEXT: { video::SColor color(255, (e->number >> 16) & 0xFF, (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y); std::wstring text = narrow_to_wide(e->text); core::dimension2d<u32> textsize = font->getDimension(text.c_str()); v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), (e->align.Y - 1.0) * (textsize.Height / 2)); v2s32 offs(e->offset.X, e->offset.Y); font->draw(text.c_str(), size + pos + offset + offs, color); break; } case HUD_ELEM_STATBAR: { v2s32 offs(e->offset.X, e->offset.Y); drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs); break; } case HUD_ELEM_INVENTORY: { InventoryList *inv = inventory->getList(e->text); drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir); break; } default: infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << "of hud element ID " << i << " due to unrecognized type" << std::endl; } } } void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset) { const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; video::ITexture *stat_texture = tsrc->getTextureRaw(texture); if (!stat_texture) return; core::dimension2di srcd(stat_texture->getOriginalSize()); v2s32 p = pos; if (corner & HUD_CORNER_LOWER) p -= srcd.Height; p += offset; v2s32 steppos; switch (drawdir) { case HUD_DIR_RIGHT_LEFT: steppos = v2s32(-1, 0); break; case HUD_DIR_TOP_BOTTOM: steppos = v2s32(0, 1); break; case HUD_DIR_BOTTOM_TOP: steppos = v2s32(0, -1); break; default: steppos = v2s32(1, 0); } steppos.X *= srcd.Width; steppos.Y *= srcd.Height; for (s32 i = 0; i < count / 2; i++) { core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height); core::rect<s32> dstrect(srcrect); dstrect += p; driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true); p += steppos; } if (count % 2 == 1) { core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height); core::rect<s32> dstrect(srcrect); dstrect += p; driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true); } } void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s32 breath) { InventoryList *mainlist = inventory->getList("main"); if (mainlist == NULL) { errorstream << "draw_hotbar(): mainlist == NULL" << std::endl; return; } s32 hotbar_itemcount = player->hud_hotbar_itemcount; s32 padding = hotbar_imagesize / 12; s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2); if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0); if (player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE) drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT, "heart.png", halfheartcount, v2s32(0, 0)); if (player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE && breath <= 10) drawStatbar(pos - v2s32(-180, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT, "bubble.png", breath*2, v2s32(0, 0)); } void Hud::drawCrosshair() { if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE)) return; if (use_crosshair_image) { video::ITexture *crosshair = tsrc->getTextureRaw("crosshair.png"); v2u32 size = crosshair->getOriginalSize(); v2s32 lsize = v2s32(displaycenter.X - (size.X / 2), displaycenter.Y - (size.Y / 2)); driver->draw2DImage(crosshair, lsize, core::rect<s32>(0, 0, size.X, size.Y), 0, crosshair_argb, true); } else { driver->draw2DLine(displaycenter - v2s32(10, 0), displaycenter + v2s32(10, 0), crosshair_argb); driver->draw2DLine(displaycenter - v2s32(0, 10), displaycenter + v2s32(0, 10), crosshair_argb); } } void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) { for (std::vector<aabb3f>::const_iterator i = hilightboxes.begin(); i != hilightboxes.end(); i++) { driver->draw3DBox(*i, selectionbox_argb); } } void Hud::resizeHotbar() { if (screensize.Y <= 800) hotbar_imagesize = 32; else if (screensize.Y <= 1280) hotbar_imagesize = 48; else hotbar_imagesize = 64; }