/* Minetest Copyright (C) 2013 celeron55, Perttu Ahola 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. */ extern "C" { #include "lua.h" #include "lauxlib.h" } #include "util/numeric.h" #include "util/serialize.h" #include "util/string.h" #include "common/c_converter.h" #include "common/c_internal.h" #include "constants.h" #define CHECK_TYPE(index, name, type) { \ int t = lua_type(L, (index)); \ if (t != (type)) { \ std::string traceback = script_get_backtrace(L); \ throw LuaError(std::string("Invalid ") + (name) + \ " (expected " + lua_typename(L, (type)) + \ " got " + lua_typename(L, t) + ").\n" + traceback); \ } \ } #define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER) #define CHECK_FLOAT_RANGE(value, name) \ if (value < F1000_MIN || value > F1000_MAX) { \ std::ostringstream error_text; \ error_text << "Invalid float vector dimension range '" name "' " << \ "(expected " << F1000_MIN << " < " name " < " << F1000_MAX << \ " got " << value << ")." << std::endl; \ throw LuaError(error_text.str()); \ } #define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE) void push_float_string(lua_State *L, float value) { std::stringstream ss; std::string str; ss << value; str = ss.str(); lua_pushstring(L, str.c_str()); } void push_v3f(lua_State *L, v3f p) { lua_newtable(L); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); lua_setfield(L, -2, "y"); lua_pushnumber(L, p.Z); lua_setfield(L, -2, "z"); } void push_v2f(lua_State *L, v2f p) { lua_newtable(L); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); lua_setfield(L, -2, "y"); } void push_v3_float_string(lua_State *L, v3f p) { lua_newtable(L); push_float_string(L, p.X); lua_setfield(L, -2, "x"); push_float_string(L, p.Y); lua_setfield(L, -2, "y"); push_float_string(L, p.Z); lua_setfield(L, -2, "z"); } void push_v2_float_string(lua_State *L, v2f p) { lua_newtable(L); push_float_string(L, p.X); lua_setfield(L, -2, "x"); push_float_string(L, p.Y); lua_setfield(L, -2, "y"); } v2s16 read_v2s16(lua_State *L, int index) { v2s16 p; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); p.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); p.Y = lua_tonumber(L, -1); lua_pop(L, 1); return p; } void push_v2s16(lua_State *L, v2s16 p) { lua_newtable(L); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); lua_setfield(L, -2, "y"); } void push_v2s32(lua_State *L, v2s32 p) { lua_newtable(L); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); lua_setfield(L, -2, "y"); } v2s32 read_v2s32(lua_State *L, int index) { v2s32 p; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); p.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); p.Y = lua_tonumber(L, -1); lua_pop(L, 1); return p; } v2f read_v2f(lua_State *L, int index) { v2f p; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); p.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); p.Y = lua_tonumber(L, -1); lua_pop(L, 1); return p; } v2f check_v2f(lua_State *L, int index) { v2f p; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); CHECK_POS_COORD("x"); p.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); CHECK_POS_COORD("y"); p.Y = lua_tonumber(L, -1); lua_pop(L, 1); return p; } v3f read_v3f(lua_State *L, int index) { v3f pos; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); pos.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); pos.Y = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "z"); pos.Z = lua_tonumber(L, -1); lua_pop(L, 1); return pos; } v3f check_v3f(lua_State *L, int index) { v3f pos; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); CHECK_POS_COORD("x"); pos.X = lua_tonumber(L, -1); CHECK_FLOAT_RANGE(pos.X, "x") lua_pop(L, 1); lua_getfield(L, index, "y"); CHECK_POS_COORD("y"); pos.Y = lua_tonumber(L, -1); CHECK_FLOAT_RANGE(pos.Y, "y") lua_pop(L, 1); lua_getfield(L, index, "z"); CHECK_POS_COORD("z"); pos.Z = lua_tonumber(L, -1); CHECK_FLOAT_RANGE(pos.Z, "z") lua_pop(L, 1); return pos; } v3d read_v3d(lua_State *L, int index) { v3d pos; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); pos.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); pos.Y = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "z"); pos.Z = lua_tonumber(L, -1); lua_pop(L, 1); return pos; } v3d check_v3d(lua_State *L, int index) { v3d pos; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); CHECK_POS_COORD("x"); pos.X = lua_tonumber(L, -1); CHECK_FLOAT_RANGE(pos.X, "x") lua_pop(L, 1); lua_getfield(L, index, "y"); CHECK_POS_COORD("y"); pos.Y = lua_tonumber(L, -1); CHECK_FLOAT_RANGE(pos.Y, "y") lua_pop(L, 1); lua_getfield(L, index, "z"); CHECK_POS_COORD("z"); pos.Z = lua_tonumber(L, -1); CHECK_FLOAT_RANGE(pos.Z, "z") lua_pop(L, 1); return pos; } void push_ARGB8(lua_State *L, video::SColor color) { lua_newtable(L); lua_pushnumber(L, color.getAlpha()); lua_setfield(L, -2, "a"); lua_pushnumber(L, color.getRed()); lua_setfield(L, -2, "r"); lua_pushnumber(L, color.getGreen()); lua_setfield(L, -2, "g"); lua_pushnumber(L, color.getBlue()); lua_setfield(L, -2, "b"); } void pushFloatPos(lua_State *L, v3f p) { p /= BS; push_v3f(L, p); } v3f checkFloatPos(lua_State *L, int index) { return check_v3f(L, index) * BS; } void push_v3s16(lua_State *L, v3s16 p) { lua_newtable(L); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); lua_setfield(L, -2, "y"); lua_pushnumber(L, p.Z); lua_setfield(L, -2, "z"); } v3s16 read_v3s16(lua_State *L, int index) { // Correct rounding at <0 v3d pf = read_v3d(L, index); return doubleToInt(pf, 1.0); } v3s16 check_v3s16(lua_State *L, int index) { // Correct rounding at <0 v3d pf = check_v3d(L, index); return doubleToInt(pf, 1.0); } bool read_color(lua_State *L, int index, video::SColor *color) { if (lua_istable(L, index)) { *color = read_ARGB8(L, index); } else if (lua_isnumber(L, index)) { color->set(lua_tonumber(L, index)); } else if (lua_isstring(L, index)) { video::SColor parsed_color; /* Minetest Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> Copyright (C) 2017 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru> 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. */ #include "interlaced.h" #include "client/client.h" #include "client/shader.h" #include "client/tile.h" RenderingCoreInterlaced::RenderingCoreInterlaced( IrrlichtDevice *_device, Client *_client, Hud *_hud) : RenderingCoreStereo(_device, _client, _hud) { initMaterial(); } void RenderingCoreInterlaced::initMaterial() { IShaderSource *s = client->getShaderSource(); mat.UseMipMaps = false; mat.ZBuffer = false; #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 mat.ZWriteEnable = video::EZW_OFF; #else mat.ZWriteEnable = false; #endif u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC); mat.MaterialType = s->getShaderInfo(shader).material; for (int k = 0; k < 3; ++k) { mat.TextureLayer[k].AnisotropicFilter = false; mat.TextureLayer[k].BilinearFilter = false; mat.TextureLayer[k].TrilinearFilter = false; mat.TextureLayer[k].TextureWrapU = video::ETC_CLAMP_TO_EDGE; mat.TextureLayer[k].TextureWrapV = video::ETC_CLAMP_TO_EDGE; } } void RenderingCoreInterlaced::initTextures() { v2u32 image_size{screensize.X, screensize.Y / 2};MYMIN(slice_offset.X + slice_size.X, data_size.X); } if (slice_offset.Y > 0) { slice_offset.Y--; pmin.Y = slice_offset.Y; pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y); } if (slice_offset.Z > 0) { slice_offset.Z--; pmin.Z = slice_offset.Z; pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z); } const u32 ystride = data_size.X; const u32 zstride = data_size.X * data_size.Y; u32 elem_index = 1; for (u32 z = pmin.Z; z != pmax.Z; z++) for (u32 y = pmin.Y; y != pmax.Y; y++) for (u32 x = pmin.X; x != pmax.X; x++) { u32 i = z * zstride + y * ystride + x; lua_pushnumber(L, data[i]); lua_rawseti(L, table_index, elem_index); elem_index++; } return elem_index - 1; } size_t write_array_slice_u16( lua_State *L, int table_index, u16 *data, v3u16 data_size, v3u16 slice_offset, v3u16 slice_size) { v3u16 pmin, pmax(data_size); if (slice_offset.X > 0) { slice_offset.X--; pmin.X = slice_offset.X; pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X); } if (slice_offset.Y > 0) { slice_offset.Y--; pmin.Y = slice_offset.Y; pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y); } if (slice_offset.Z > 0) { slice_offset.Z--; pmin.Z = slice_offset.Z; pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z); } const u32 ystride = data_size.X; const u32 zstride = data_size.X * data_size.Y; u32 elem_index = 1; for (u32 z = pmin.Z; z != pmax.Z; z++) for (u32 y = pmin.Y; y != pmax.Y; y++) for (u32 x = pmin.X; x != pmax.X; x++) { u32 i = z * zstride + y * ystride + x; lua_pushinteger(L, data[i]); lua_rawseti(L, table_index, elem_index); elem_index++; } return elem_index - 1; }