Compare commits

...

5 Commits

Author SHA1 Message Date
Pierre-Yves Rollo d3d218940b
Fix #10349 game crashing if dropped an item with undefined light_source (#10351) 2020-08-30 15:34:28 +02:00
LoneWolfHT c18dbadcb8
Fix dropped craftitems/tools not using light_source values (#9438) 2020-08-30 00:02:21 +01:00
EvidenceB 5c4b560b68
Add compass HUD element (#9312)
Co-authored-by: Jean-Patrick Guerrero <jeanpatrick.guerrero@gmail.com>
Co-authored-by: Pierre-Yves Rollo <dev@pyrollo.com>
Co-authored-by: SmallJoker <SmallJoker@users.noreply.github.com>
2020-08-29 20:13:30 +02:00
HybridDog 386d5f778a
Document normalmap textures (#10096) 2020-08-29 16:43:09 +01:00
DS 28e87ce9d5
Add vector.offset (#10321) 2020-08-29 16:41:29 +01:00
8 changed files with 232 additions and 14 deletions

View File

@ -44,6 +44,10 @@ describe("vector", function()
assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 }))
end)
it("offset()", function()
assert.same({ x = 41, y = 52, z = 63 }, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
end)
-- This function is needed because of floating point imprecision.
local function almost_equal(a, b)
if type(a) == "number" then

View File

@ -137,6 +137,12 @@ function vector.divide(a, b)
end
end
function vector.offset(v, x, y, z)
return {x = v.x + x,
y = v.y + y,
z = v.z + z}
end
function vector.sort(a, b)
return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)},
{x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)}

View File

@ -54,8 +54,9 @@ core.register_entity(":__builtin:item", {
local max_count = stack:get_stack_max()
local count = math.min(stack:get_count(), max_count)
local size = 0.2 + 0.1 * (count / max_count) ^ (1 / 3)
local def = core.registered_nodes[itemname]
local glow = def and math.floor(def.light_source / 2 + 0.5)
local def = core.registered_items[itemname]
local glow = def and def.light_source and
math.floor(def.light_source / 2 + 0.5)
self.object:set_properties({
is_visible = true,

View File

@ -152,6 +152,7 @@ Mod directory structure
│   ├── models
│   ├── textures
│   │   ├── modname_stuff.png
│   │   ├── modname_stuff_normal.png
│   │   ├── modname_something_else.png
│   │   ├── subfolder_foo
│   │   │ ├── modname_more_stuff.png
@ -384,6 +385,36 @@ stripping out the file extension:
* e.g. `foomod_foothing.png`
* e.g. `foomod_foothing`
Normalmap Textures
------------------
If shaders and bumpmapping or parallax occlusion is enabled, Minetest tries
to load normalmaps.
Those image files have to end with `_normal.png` and start with the same name
as their corresponding texture.
For example a normalmap for `foomod_foothing.png` has to be called
`foomod_foothing_normal.png`.
The sRGB R, G and B colour values of a normalmap pixel are each directly
mapped from `{0, ..., 255}` to `[-1, 1]` and, taken together,
define the normal vector.
The alpha channel defines the heightmap for parallax occlusion.
To be safe, the alpha values should always be bigger than zero
because the colour values, which define the normal vector,
may be undefined for image formats where colour is discarded in fully
transparent pixels.
Bumpmapping and parallax occlusion are currently experimental features:
* Bumpmapping in Minetest happens in an obscure way; there are no light sources
defined in the shaders except the sunlight direction.
* Parallax occlusion with relief-mapping mode does not yet work correctly
together with Minetest's Fastfaces.
* The normalmap files must end with `.png`, so other image files are not
supported.
Texture modifiers
-----------------
@ -1420,7 +1451,23 @@ Same as `image`, but does not accept a `position`; the position is instead deter
* `world_pos`: World position of the waypoint.
* `offset`: offset in pixels from position.
### `compass`
Displays an image oriented or translated according to current heading direction.
* `size`: The size of this element. Negative values represent percentage
of the screen; e.g. `x=-100` means 100% (width).
* `scale`: Scale of the translated image (used only for dir = 2 or dir = 3).
* `text`: The name of the texture to use.
* `alignment`: The alignment of the image.
* `offset`: Offset in pixels from position.
* `dir`: How the image is rotated/translated:
* 0 - Rotate as heading direction
* 1 - Rotate in reverse direction
* 2 - Translate as landscape direction
* 3 - Translate in reverse direction
If translation is chosen, texture is repeated horizontally to fill the whole element.
Representations of simple things
================================
@ -3062,10 +3109,12 @@ For the following functions, `v`, `v1`, `v2` are vectors,
* Returns in order minp, maxp vectors of the cuboid defined by `v1`, `v2`.
* `vector.angle(v1, v2)`:
* Returns the angle between `v1` and `v2` in radians.
* `vector.dot(v1, v2)`
* Returns the dot product of `v1` and `v2`
* `vector.cross(v1, v2)`
* Returns the cross product of `v1` and `v2`
* `vector.dot(v1, v2)`:
* Returns the dot product of `v1` and `v2`.
* `vector.cross(v1, v2)`:
* Returns the cross product of `v1` and `v2`.
* `vector.offset(v, x, y, z)`:
* Returns the sum of the vectors `v` and `{x = x, y = y, z = z}`.
For the following functions `x` can be either a vector or a number:
@ -6977,6 +7026,13 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
liquids_pointable = false,
light_source = 0,
-- When used for nodes: Defines amount of light emitted by node.
-- Otherwise: Defines texture glow when viewed as a dropped item
-- To set the maximum (14), use the value 'minetest.LIGHT_MAX'.
-- A value outside the range 0 to minetest.LIGHT_MAX causes undefined
-- behavior.
-- See "Tools" section for an example including explanation
tool_capabilities = {
full_punch_interval = 1.0,
@ -7176,12 +7232,6 @@ Used by `minetest.register_node`.
drowning = 0,
-- Player will take this amount of damage if no bubbles are left
light_source = 0,
-- Amount of light emitted by node.
-- To set the maximum (14), use the value 'minetest.LIGHT_MAX'.
-- A value outside the range 0 to minetest.LIGHT_MAX causes undefined
-- behavior.
damage_per_second = 0,
-- If player is inside node, this damage is caused
@ -7935,7 +7985,7 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
{
hud_elem_type = "image", -- See HUD element types
-- Type of element, can be "image", "text", "statbar", or "inventory"
-- Type of element, can be "image", "text", "statbar", "inventory" or "compass"
position = {x=0.5, y=0.5},
-- Left corner position of element

View File

@ -114,6 +114,28 @@ Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
} else {
m_selection_material.MaterialType = video::EMT_SOLID;
}
// Prepare mesh for compass drawing
m_rotation_mesh_buffer.Vertices.set_used(4);
m_rotation_mesh_buffer.Indices.set_used(6);
video::SColor white(255, 255, 255, 255);
v3f normal(0.f, 0.f, 1.f);
m_rotation_mesh_buffer.Vertices[0] = video::S3DVertex(v3f(-1.f, -1.f, 0.f), normal, white, v2f(0.f, 1.f));
m_rotation_mesh_buffer.Vertices[1] = video::S3DVertex(v3f(-1.f, 1.f, 0.f), normal, white, v2f(0.f, 0.f));
m_rotation_mesh_buffer.Vertices[2] = video::S3DVertex(v3f( 1.f, 1.f, 0.f), normal, white, v2f(1.f, 0.f));
m_rotation_mesh_buffer.Vertices[3] = video::S3DVertex(v3f( 1.f, -1.f, 0.f), normal, white, v2f(1.f, 1.f));
m_rotation_mesh_buffer.Indices[0] = 0;
m_rotation_mesh_buffer.Indices[1] = 1;
m_rotation_mesh_buffer.Indices[2] = 2;
m_rotation_mesh_buffer.Indices[3] = 2;
m_rotation_mesh_buffer.Indices[4] = 3;
m_rotation_mesh_buffer.Indices[5] = 0;
m_rotation_mesh_buffer.getMaterial().Lighting = false;
m_rotation_mesh_buffer.getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
}
Hud::~Hud()
@ -423,6 +445,54 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
core::rect<s32>(core::position2d<s32>(0,0), imgsize),
NULL, colors, true);
break; }
case HUD_ELEM_COMPASS: {
video::ITexture *texture = tsrc->getTexture(e->text);
if (!texture)
continue;
// Positionning :
v2s32 dstsize(e->size.X, e->size.Y);
if (e->size.X < 0)
dstsize.X = m_screensize.X * (e->size.X * -0.01);
if (e->size.Y < 0)
dstsize.Y = m_screensize.Y * (e->size.Y * -0.01);
if (dstsize.X <= 0 || dstsize.Y <= 0)
return; // Avoid zero divides
// Angle according to camera view
v3f fore(0.f, 0.f, 1.f);
scene::ICameraSceneNode *cam = RenderingEngine::get_scene_manager()->getActiveCamera();
cam->getAbsoluteTransformation().rotateVect(fore);
int angle = - fore.getHorizontalAngle().Y;
// Limit angle and ajust with given offset
angle = (angle + (int)e->number) % 360;
core::rect<s32> dstrect(0, 0, dstsize.X, dstsize.Y);
dstrect += pos + v2s32(
(e->align.X - 1.0) * dstsize.X / 2,
(e->align.Y - 1.0) * dstsize.Y / 2) +
v2s32(e->offset.X * m_hud_scaling, e->offset.Y * m_hud_scaling);
switch (e->dir) {
case HUD_COMPASS_ROTATE:
drawCompassRotate(e, texture, dstrect, angle);
break;
case HUD_COMPASS_ROTATE_REVERSE:
drawCompassRotate(e, texture, dstrect, -angle);
break;
case HUD_COMPASS_TRANSLATE:
drawCompassTranslate(e, texture, dstrect, angle);
break;
case HUD_COMPASS_TRANSLATE_REVERSE:
drawCompassTranslate(e, texture, dstrect, -angle);
break;
default:
break;
}
break; }
default:
infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
" of hud element ID " << i << " due to unrecognized type" << std::endl;
@ -430,6 +500,76 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
}
}
void Hud::drawCompassTranslate(HudElement *e, video::ITexture *texture,
const core::rect<s32> &rect, int angle)
{
const video::SColor color(255, 255, 255, 255);
const video::SColor colors[] = {color, color, color, color};
// Compute source image scaling
core::dimension2di imgsize(texture->getOriginalSize());
core::rect<s32> srcrect(0, 0, imgsize.Width, imgsize.Height);
v2s32 dstsize(rect.getHeight() * e->scale.X * imgsize.Width / imgsize.Height,
rect.getHeight() * e->scale.Y);
// Avoid infinite loop
if (dstsize.X <= 0 || dstsize.Y <= 0)
return;
core::rect<s32> tgtrect(0, 0, dstsize.X, dstsize.Y);
tgtrect += v2s32(
(rect.getWidth() - dstsize.X) / 2,
(rect.getHeight() - dstsize.Y) / 2) +
rect.UpperLeftCorner;
int offset = angle * dstsize.X / 360;
tgtrect += v2s32(offset, 0);
// Repeat image as much as needed
while (tgtrect.UpperLeftCorner.X > rect.UpperLeftCorner.X)
tgtrect -= v2s32(dstsize.X, 0);
draw2DImageFilterScaled(driver, texture, tgtrect, srcrect, &rect, colors, true);
tgtrect += v2s32(dstsize.X, 0);
while (tgtrect.UpperLeftCorner.X < rect.LowerRightCorner.X) {
draw2DImageFilterScaled(driver, texture, tgtrect, srcrect, &rect, colors, true);
tgtrect += v2s32(dstsize.X, 0);
}
}
void Hud::drawCompassRotate(HudElement *e, video::ITexture *texture,
const core::rect<s32> &rect, int angle)
{
core::dimension2di imgsize(texture->getOriginalSize());
core::rect<s32> oldViewPort = driver->getViewPort();
core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
core::matrix4 Matrix;
Matrix.makeIdentity();
Matrix.setRotationDegrees(v3f(0.f, 0.f, angle));
driver->setViewPort(rect);
driver->setTransform(video::ETS_PROJECTION, core::matrix4());
driver->setTransform(video::ETS_VIEW, core::matrix4());
driver->setTransform(video::ETS_WORLD, Matrix);
video::SMaterial &material = m_rotation_mesh_buffer.getMaterial();
material.TextureLayer[0].Texture = texture;
driver->setMaterial(material);
driver->drawMeshBuffer(&m_rotation_mesh_buffer);
driver->setTransform(video::ETS_WORLD, core::matrix4());
driver->setTransform(video::ETS_VIEW, oldViewMat);
driver->setTransform(video::ETS_PROJECTION, oldProjMat);
// restore the view area
driver->setViewPort(oldViewPort);
}
void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
const std::string &texture, const std::string &bgtexture,

View File

@ -95,6 +95,12 @@ private:
void drawItem(const ItemStack &item, const core::rect<s32> &rect, bool selected);
void drawCompassTranslate(HudElement *e, video::ITexture *texture,
const core::rect<s32> &rect, int way);
void drawCompassRotate(HudElement *e, video::ITexture *texture,
const core::rect<s32> &rect, int way);
float m_hud_scaling; // cached minetest setting
float m_scale_factor;
v3s16 m_camera_offset;
@ -115,6 +121,8 @@ private:
video::SMaterial m_selection_material;
scene::SMeshBuffer m_rotation_mesh_buffer;
enum
{
HIGHLIGHT_BOX,

View File

@ -28,6 +28,7 @@ const struct EnumString es_HudElementType[] =
{HUD_ELEM_INVENTORY, "inventory"},
{HUD_ELEM_WAYPOINT, "waypoint"},
{HUD_ELEM_IMAGE_WAYPOINT, "image_waypoint"},
{HUD_ELEM_COMPASS, "compass"},
{0, NULL},
};

View File

@ -60,7 +60,8 @@ enum HudElementType {
HUD_ELEM_STATBAR = 2,
HUD_ELEM_INVENTORY = 3,
HUD_ELEM_WAYPOINT = 4,
HUD_ELEM_IMAGE_WAYPOINT = 5
HUD_ELEM_IMAGE_WAYPOINT = 5,
HUD_ELEM_COMPASS = 6
};
enum HudElementStat {
@ -79,6 +80,13 @@ enum HudElementStat {
HUD_STAT_TEXT2,
};
enum HudCompassDir {
HUD_COMPASS_ROTATE = 0,
HUD_COMPASS_ROTATE_REVERSE,
HUD_COMPASS_TRANSLATE,
HUD_COMPASS_TRANSLATE_REVERSE,
};
struct HudElement {
HudElementType type;
v2f pos;