mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Add hardware node coloring. Includes:
- Increase ContentFeatures serialization version - Color property and palettes for nodes - paramtype2 = "color", "colored facedir" or "colored wallmounted"
This commit is contained in:
parent
43822de5c6
commit
d04d8aba70
@ -1,7 +1,8 @@
|
|||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mWorld;
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
// Color of the light emitted by the sun.
|
||||||
|
uniform vec3 dayLight;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ varying vec3 tsEyeVec;
|
|||||||
varying vec3 tsLightVec;
|
varying vec3 tsLightVec;
|
||||||
varying float area_enable_parallax;
|
varying float area_enable_parallax;
|
||||||
|
|
||||||
|
// Color of the light emitted by the light sources.
|
||||||
|
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
|
||||||
const float e = 2.718281828459;
|
const float e = 2.718281828459;
|
||||||
const float BS = 10.0;
|
const float BS = 10.0;
|
||||||
|
|
||||||
@ -119,31 +122,23 @@ float disp_z;
|
|||||||
v.z = dot(eyeVec, normal);
|
v.z = dot(eyeVec, normal);
|
||||||
tsEyeVec = normalize (v);
|
tsEyeVec = normalize (v);
|
||||||
|
|
||||||
|
// Calculate color.
|
||||||
|
// Red, green and blue components are pre-multiplied with
|
||||||
|
// the brightness, so now we have to multiply these
|
||||||
|
// colors with the color of the incoming light.
|
||||||
|
// The pre-baked colors are halved to prevent overflow.
|
||||||
vec4 color;
|
vec4 color;
|
||||||
float day = gl_Color.r;
|
// The alpha gives the ratio of sunlight in the incoming light.
|
||||||
float night = gl_Color.g;
|
float nightRatio = 1 - gl_Color.a;
|
||||||
float light_source = gl_Color.b;
|
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
|
||||||
|
nightRatio * artificialLight.rgb) * 2;
|
||||||
float rg = mix(night, day, dayNightRatio);
|
color.a = 1;
|
||||||
rg += light_source * 2.5; // Make light sources brighter
|
|
||||||
float b = rg;
|
|
||||||
|
|
||||||
// Moonlight is blue
|
|
||||||
b += (day - night) / 13.0;
|
|
||||||
rg -= (day - night) / 23.0;
|
|
||||||
|
|
||||||
// Emphase blue a bit in darker places
|
// Emphase blue a bit in darker places
|
||||||
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
b += max(0.0, (1.0 - abs(b - 0.13) / 0.17) * 0.025);
|
float brightness = (color.r + color.g + color.b) / 3;
|
||||||
|
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
|
||||||
// Artificial light is yellow-ish
|
0.07 * brightness);
|
||||||
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
|
||||||
rg += max(0.0, (1.0 - abs(rg - 0.85) / 0.15) * 0.065);
|
|
||||||
|
|
||||||
color.r = rg;
|
|
||||||
color.g = rg;
|
|
||||||
color.b = b;
|
|
||||||
|
|
||||||
color.a = gl_Color.a;
|
|
||||||
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
|
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mWorld;
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
// Color of the light emitted by the sun.
|
||||||
|
uniform vec3 dayLight;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
|
||||||
@ -13,6 +14,8 @@ varying vec3 lightVec;
|
|||||||
varying vec3 tsEyeVec;
|
varying vec3 tsEyeVec;
|
||||||
varying vec3 tsLightVec;
|
varying vec3 tsLightVec;
|
||||||
|
|
||||||
|
// Color of the light emitted by the light sources.
|
||||||
|
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
|
||||||
const float e = 2.718281828459;
|
const float e = 2.718281828459;
|
||||||
const float BS = 10.0;
|
const float BS = 10.0;
|
||||||
|
|
||||||
@ -112,31 +115,23 @@ void main(void)
|
|||||||
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
tsEyeVec = eyeVec * tbnMatrix;
|
tsEyeVec = eyeVec * tbnMatrix;
|
||||||
|
|
||||||
|
// Calculate color.
|
||||||
|
// Red, green and blue components are pre-multiplied with
|
||||||
|
// the brightness, so now we have to multiply these
|
||||||
|
// colors with the color of the incoming light.
|
||||||
|
// The pre-baked colors are halved to prevent overflow.
|
||||||
vec4 color;
|
vec4 color;
|
||||||
float day = gl_Color.r;
|
// The alpha gives the ratio of sunlight in the incoming light.
|
||||||
float night = gl_Color.g;
|
float nightRatio = 1 - gl_Color.a;
|
||||||
float light_source = gl_Color.b;
|
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
|
||||||
|
nightRatio * artificialLight.rgb) * 2;
|
||||||
float rg = mix(night, day, dayNightRatio);
|
color.a = 1;
|
||||||
rg += light_source * 2.5; // Make light sources brighter
|
|
||||||
float b = rg;
|
|
||||||
|
|
||||||
// Moonlight is blue
|
|
||||||
b += (day - night) / 13.0;
|
|
||||||
rg -= (day - night) / 23.0;
|
|
||||||
|
|
||||||
// Emphase blue a bit in darker places
|
// Emphase blue a bit in darker places
|
||||||
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
|
float brightness = (color.r + color.g + color.b) / 3;
|
||||||
|
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
|
||||||
// Artificial light is yellow-ish
|
0.07 * brightness);
|
||||||
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
|
||||||
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
|
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
|
||||||
|
|
||||||
color.r = rg;
|
|
||||||
color.g = rg;
|
|
||||||
color.b = b;
|
|
||||||
|
|
||||||
color.a = gl_Color.a;
|
|
||||||
gl_FrontColor = gl_BackColor = clamp(color,0.0,1.0);
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mWorld;
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
|
||||||
|
@ -638,6 +638,19 @@ node definition:
|
|||||||
bit 4 (0x10) - Makes the plant mesh 1.4x larger
|
bit 4 (0x10) - Makes the plant mesh 1.4x larger
|
||||||
bit 5 (0x20) - Moves each face randomly a small bit down (1/8 max)
|
bit 5 (0x20) - Moves each face randomly a small bit down (1/8 max)
|
||||||
bits 6-7 are reserved for future use.
|
bits 6-7 are reserved for future use.
|
||||||
|
paramtype2 == "color"
|
||||||
|
^ `param2` tells which color is picked from the palette.
|
||||||
|
The palette should have 256 pixels.
|
||||||
|
paramtype2 == "colorfacedir"
|
||||||
|
^ Same as `facedir`, but with colors.
|
||||||
|
The first three bits of `param2` tells which color
|
||||||
|
is picked from the palette.
|
||||||
|
The palette should have 8 pixels.
|
||||||
|
paramtype2 == "colorwallmounted"
|
||||||
|
^ Same as `wallmounted`, but with colors.
|
||||||
|
The first five bits of `param2` tells which color
|
||||||
|
is picked from the palette.
|
||||||
|
The palette should have 32 pixels.
|
||||||
collision_box = {
|
collision_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {
|
fixed = {
|
||||||
@ -3707,6 +3720,9 @@ Definition tables
|
|||||||
when displacement mapping is used
|
when displacement mapping is used
|
||||||
Directions are from the point of view of the tile texture,
|
Directions are from the point of view of the tile texture,
|
||||||
not the node it's on
|
not the node it's on
|
||||||
|
* `{name="image.png", color=ColorSpec}`
|
||||||
|
* the texture's color will be multiplied with this color.
|
||||||
|
* the tile's color overrides the owning node's color in all cases.
|
||||||
* deprecated, yet still supported field names:
|
* deprecated, yet still supported field names:
|
||||||
* `image` (name)
|
* `image` (name)
|
||||||
|
|
||||||
@ -3749,8 +3765,17 @@ Definition tables
|
|||||||
special_tiles = {tile definition 1, Tile definition 2}, --[[
|
special_tiles = {tile definition 1, Tile definition 2}, --[[
|
||||||
^ Special textures of node; used rarely (old field name: special_materials)
|
^ Special textures of node; used rarely (old field name: special_materials)
|
||||||
^ List can be shortened to needed length ]]
|
^ List can be shortened to needed length ]]
|
||||||
alpha = 255,
|
color = ColorSpec, --[[
|
||||||
|
^ The node's original color will be multiplied with this color.
|
||||||
|
^ If the node has a palette, then this setting only has an effect
|
||||||
|
^ in the inventory and on the wield item. ]]
|
||||||
use_texture_alpha = false, -- Use texture's alpha channel
|
use_texture_alpha = false, -- Use texture's alpha channel
|
||||||
|
palette = "palette.png", --[[
|
||||||
|
^ The node's `param2` is used to select a pixel from the image
|
||||||
|
^ (pixels are arranged from left to right and from top to bottom).
|
||||||
|
^ The node's color will be multiplied with the selected pixel's
|
||||||
|
^ color. Tiles can override this behavior.
|
||||||
|
^ Only when `paramtype2` supports palettes. ]]
|
||||||
post_effect_color = "green#0F", -- If player is inside node, see "ColorSpec"
|
post_effect_color = "green#0F", -- If player is inside node, see "ColorSpec"
|
||||||
paramtype = "none", -- See "Nodes" --[[
|
paramtype = "none", -- See "Nodes" --[[
|
||||||
^ paramtype = "light" allows light to propagate from or through the node with light value
|
^ paramtype = "light" allows light to propagate from or through the node with light value
|
||||||
|
@ -378,9 +378,6 @@ public:
|
|||||||
video::ITexture* generateTextureFromMesh(
|
video::ITexture* generateTextureFromMesh(
|
||||||
const TextureFromMeshParams ¶ms);
|
const TextureFromMeshParams ¶ms);
|
||||||
|
|
||||||
// Generates an image from a full string like
|
|
||||||
// "stone.png^mineral_coal.png^[crack:1:0".
|
|
||||||
// Shall be called from the main thread.
|
|
||||||
video::IImage* generateImage(const std::string &name);
|
video::IImage* generateImage(const std::string &name);
|
||||||
|
|
||||||
video::ITexture* getNormalTexture(const std::string &name);
|
video::ITexture* getNormalTexture(const std::string &name);
|
||||||
|
@ -108,6 +108,12 @@ public:
|
|||||||
const std::string &name, u32 *id = NULL) = 0;
|
const std::string &name, u32 *id = NULL) = 0;
|
||||||
virtual IrrlichtDevice* getDevice()=0;
|
virtual IrrlichtDevice* getDevice()=0;
|
||||||
virtual bool isKnownSourceImage(const std::string &name)=0;
|
virtual bool isKnownSourceImage(const std::string &name)=0;
|
||||||
|
/*! Generates an image from a full string like
|
||||||
|
* "stone.png^mineral_coal.png^[crack:1:0".
|
||||||
|
* Shall be called from the main thread.
|
||||||
|
* The returned Image should be dropped.
|
||||||
|
*/
|
||||||
|
virtual video::IImage* generateImage(const std::string &name)=0;
|
||||||
virtual video::ITexture* generateTextureFromMesh(
|
virtual video::ITexture* generateTextureFromMesh(
|
||||||
const TextureFromMeshParams ¶ms)=0;
|
const TextureFromMeshParams ¶ms)=0;
|
||||||
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
||||||
@ -192,7 +198,6 @@ struct TileSpec
|
|||||||
texture(NULL),
|
texture(NULL),
|
||||||
normal_texture(NULL),
|
normal_texture(NULL),
|
||||||
flags_texture(NULL),
|
flags_texture(NULL),
|
||||||
alpha(255),
|
|
||||||
material_type(TILE_MATERIAL_BASIC),
|
material_type(TILE_MATERIAL_BASIC),
|
||||||
material_flags(
|
material_flags(
|
||||||
//0 // <- DEBUG, Use the one below
|
//0 // <- DEBUG, Use the one below
|
||||||
@ -201,22 +206,30 @@ struct TileSpec
|
|||||||
shader_id(0),
|
shader_id(0),
|
||||||
animation_frame_count(1),
|
animation_frame_count(1),
|
||||||
animation_frame_length_ms(0),
|
animation_frame_length_ms(0),
|
||||||
rotation(0)
|
rotation(0),
|
||||||
|
has_color(false),
|
||||||
|
color(),
|
||||||
|
emissive_light(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Two tiles are equal if they can be appended to
|
||||||
|
* the same mesh buffer.
|
||||||
|
*/
|
||||||
bool operator==(const TileSpec &other) const
|
bool operator==(const TileSpec &other) const
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
texture_id == other.texture_id &&
|
texture_id == other.texture_id &&
|
||||||
/* texture == other.texture && */
|
|
||||||
alpha == other.alpha &&
|
|
||||||
material_type == other.material_type &&
|
material_type == other.material_type &&
|
||||||
material_flags == other.material_flags &&
|
material_flags == other.material_flags &&
|
||||||
rotation == other.rotation
|
rotation == other.rotation
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Two tiles are not equal if they must be in different mesh buffers.
|
||||||
|
*/
|
||||||
bool operator!=(const TileSpec &other) const
|
bool operator!=(const TileSpec &other) const
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
@ -233,7 +246,7 @@ struct TileSpec
|
|||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
break;
|
break;
|
||||||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
break;
|
break;
|
||||||
case TILE_MATERIAL_LIQUID_OPAQUE:
|
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||||
material.MaterialType = video::EMT_SOLID;
|
material.MaterialType = video::EMT_SOLID;
|
||||||
@ -274,8 +287,6 @@ struct TileSpec
|
|||||||
video::ITexture *normal_texture;
|
video::ITexture *normal_texture;
|
||||||
video::ITexture *flags_texture;
|
video::ITexture *flags_texture;
|
||||||
|
|
||||||
// Vertex alpha (when MATERIAL_ALPHA_VERTEX is used)
|
|
||||||
u8 alpha;
|
|
||||||
// Material parameters
|
// Material parameters
|
||||||
u8 material_type;
|
u8 material_type;
|
||||||
u8 material_flags;
|
u8 material_flags;
|
||||||
@ -286,5 +297,14 @@ struct TileSpec
|
|||||||
std::vector<FrameSpec> frames;
|
std::vector<FrameSpec> frames;
|
||||||
|
|
||||||
u8 rotation;
|
u8 rotation;
|
||||||
|
//! If true, the tile has its own color.
|
||||||
|
bool has_color;
|
||||||
|
/*!
|
||||||
|
* The color of the tile, or if the tile does not own
|
||||||
|
* a color then the color of the node owning this tile.
|
||||||
|
*/
|
||||||
|
video::SColor color;
|
||||||
|
//! This much light does the tile emit.
|
||||||
|
u8 emissive_light;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -334,9 +334,7 @@ void ClientEnvironment::step(float dtime)
|
|||||||
node_at_lplayer = m_map->getNodeNoEx(p);
|
node_at_lplayer = m_map->getNodeNoEx(p);
|
||||||
|
|
||||||
u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
|
u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
|
||||||
u8 day = light & 0xff;
|
final_color_blend(&lplayer->light_color, light, day_night_ratio);
|
||||||
u8 night = (light >> 8) & 0xff;
|
|
||||||
finalColorBlend(lplayer->light_color, day, night, day_night_ratio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -32,28 +32,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
|
|
||||||
// Create a cuboid.
|
// Create a cuboid.
|
||||||
// collector - the MeshCollector for the resulting polygons
|
// collector - the MeshCollector for the resulting polygons
|
||||||
// box - the position and size of the box
|
// box - the position and size of the box
|
||||||
// tiles - the tiles (materials) to use (for all 6 faces)
|
// tiles - the tiles (materials) to use (for all 6 faces)
|
||||||
// tilecount - number of entries in tiles, 1<=tilecount<=6
|
// tilecount - number of entries in tiles, 1<=tilecount<=6
|
||||||
// c - vertex colour - used for all
|
// c - colors of the cuboid's six sides
|
||||||
// txc - texture coordinates - this is a list of texture coordinates
|
// txc - texture coordinates - this is a list of texture coordinates
|
||||||
// for the opposite corners of each face - therefore, there
|
// for the opposite corners of each face - therefore, there
|
||||||
// should be (2+2)*6=24 values in the list. Alternatively, pass
|
// should be (2+2)*6=24 values in the list. Alternatively,
|
||||||
// NULL to use the entire texture for each face. The order of
|
// pass NULL to use the entire texture for each face. The
|
||||||
// the faces in the list is up-down-right-left-back-front
|
// order of the faces in the list is up-down-right-left-back-
|
||||||
// (compatible with ContentFeatures). If you specified 0,0,1,1
|
// front (compatible with ContentFeatures). If you specified
|
||||||
// for each face, that would be the same as passing NULL.
|
// 0,0,1,1 for each face, that would be the same as
|
||||||
|
// passing NULL.
|
||||||
|
// light source - if greater than zero, the box's faces will not be shaded
|
||||||
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||||
TileSpec *tiles, int tilecount, video::SColor &c, const f32* txc)
|
TileSpec *tiles, int tilecount, const video::SColor *c,
|
||||||
|
const f32* txc, const u8 light_source)
|
||||||
{
|
{
|
||||||
assert(tilecount >= 1 && tilecount <= 6); // pre-condition
|
assert(tilecount >= 1 && tilecount <= 6); // pre-condition
|
||||||
|
|
||||||
v3f min = box.MinEdge;
|
v3f min = box.MinEdge;
|
||||||
v3f max = box.MaxEdge;
|
v3f max = box.MaxEdge;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(txc == NULL) {
|
if(txc == NULL) {
|
||||||
static const f32 txc_default[24] = {
|
static const f32 txc_default[24] = {
|
||||||
0,0,1,1,
|
0,0,1,1,
|
||||||
@ -66,38 +67,53 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
|||||||
txc = txc_default;
|
txc = txc_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
video::SColor c1 = c[0];
|
||||||
|
video::SColor c2 = c[1];
|
||||||
|
video::SColor c3 = c[2];
|
||||||
|
video::SColor c4 = c[3];
|
||||||
|
video::SColor c5 = c[4];
|
||||||
|
video::SColor c6 = c[5];
|
||||||
|
if (!light_source) {
|
||||||
|
applyFacesShading(c1, v3f(0, 1, 0));
|
||||||
|
applyFacesShading(c2, v3f(0, -1, 0));
|
||||||
|
applyFacesShading(c3, v3f(1, 0, 0));
|
||||||
|
applyFacesShading(c4, v3f(-1, 0, 0));
|
||||||
|
applyFacesShading(c5, v3f(0, 0, 1));
|
||||||
|
applyFacesShading(c6, v3f(0, 0, -1));
|
||||||
|
}
|
||||||
|
|
||||||
video::S3DVertex vertices[24] =
|
video::S3DVertex vertices[24] =
|
||||||
{
|
{
|
||||||
// up
|
// up
|
||||||
video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]),
|
video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c1, txc[0],txc[1]),
|
||||||
video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]),
|
video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c1, txc[2],txc[1]),
|
||||||
video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]),
|
video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c1, txc[2],txc[3]),
|
||||||
video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]),
|
video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c1, txc[0],txc[3]),
|
||||||
// down
|
// down
|
||||||
video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]),
|
video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c2, txc[4],txc[5]),
|
||||||
video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]),
|
video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c2, txc[6],txc[5]),
|
||||||
video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]),
|
video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c2, txc[6],txc[7]),
|
||||||
video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]),
|
video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c2, txc[4],txc[7]),
|
||||||
// right
|
// right
|
||||||
video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]),
|
video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c3, txc[ 8],txc[9]),
|
||||||
video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]),
|
video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c3, txc[10],txc[9]),
|
||||||
video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]),
|
video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c3, txc[10],txc[11]),
|
||||||
video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]),
|
video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c3, txc[ 8],txc[11]),
|
||||||
// left
|
// left
|
||||||
video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]),
|
video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c4, txc[12],txc[13]),
|
||||||
video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]),
|
video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c4, txc[14],txc[13]),
|
||||||
video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]),
|
video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c4, txc[14],txc[15]),
|
||||||
video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]),
|
video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c4, txc[12],txc[15]),
|
||||||
// back
|
// back
|
||||||
video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]),
|
video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c5, txc[16],txc[17]),
|
||||||
video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]),
|
video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c5, txc[18],txc[17]),
|
||||||
video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]),
|
video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c5, txc[18],txc[19]),
|
||||||
video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[16],txc[19]),
|
video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c5, txc[16],txc[19]),
|
||||||
// front
|
// front
|
||||||
video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]),
|
video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c6, txc[20],txc[21]),
|
||||||
video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]),
|
video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c6, txc[22],txc[21]),
|
||||||
video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]),
|
video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c6, txc[22],txc[23]),
|
||||||
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
|
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c6, txc[20],txc[23]),
|
||||||
};
|
};
|
||||||
|
|
||||||
for(int i = 0; i < 6; i++)
|
for(int i = 0; i < 6; i++)
|
||||||
@ -164,6 +180,31 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a cuboid.
|
||||||
|
// collector - the MeshCollector for the resulting polygons
|
||||||
|
// box - the position and size of the box
|
||||||
|
// tiles - the tiles (materials) to use (for all 6 faces)
|
||||||
|
// tilecount - number of entries in tiles, 1<=tilecount<=6
|
||||||
|
// c - color of the cuboid
|
||||||
|
// txc - texture coordinates - this is a list of texture coordinates
|
||||||
|
// for the opposite corners of each face - therefore, there
|
||||||
|
// should be (2+2)*6=24 values in the list. Alternatively,
|
||||||
|
// pass NULL to use the entire texture for each face. The
|
||||||
|
// order of the faces in the list is up-down-right-left-back-
|
||||||
|
// front (compatible with ContentFeatures). If you specified
|
||||||
|
// 0,0,1,1 for each face, that would be the same as
|
||||||
|
// passing NULL.
|
||||||
|
// light source - if greater than zero, the box's faces will not be shaded
|
||||||
|
void makeCuboid(MeshCollector *collector, const aabb3f &box, TileSpec *tiles,
|
||||||
|
int tilecount, const video::SColor &c, const f32* txc,
|
||||||
|
const u8 light_source)
|
||||||
|
{
|
||||||
|
video::SColor color[6];
|
||||||
|
for (u8 i = 0; i < 6; i++)
|
||||||
|
color[i] = c;
|
||||||
|
makeCuboid(collector, box, tiles, tilecount, color, txc, light_source);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
|
static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
|
||||||
MeshMakeData *data, MapNode n, int v, int *neighbors)
|
MeshMakeData *data, MapNode n, int v, int *neighbors)
|
||||||
{
|
{
|
||||||
@ -181,6 +222,18 @@ static inline int NeighborToIndex(const v3s16 &pos)
|
|||||||
return 9 * pos.X + 3 * pos.Y + pos.Z + 13;
|
return 9 * pos.X + 3 * pos.Y + pos.Z + 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the i-th special tile for a map node.
|
||||||
|
*/
|
||||||
|
static TileSpec getSpecialTile(const ContentFeatures &f,
|
||||||
|
const MapNode &n, u8 i)
|
||||||
|
{
|
||||||
|
TileSpec copy = f.special_tiles[i];
|
||||||
|
if (!copy.has_color)
|
||||||
|
n.getColor(f, ©.color);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Fix alpha blending for special nodes
|
TODO: Fix alpha blending for special nodes
|
||||||
Currently only the last element rendered is blended correct
|
Currently only the last element rendered is blended correct
|
||||||
@ -227,8 +280,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
/*
|
/*
|
||||||
Add water sources to mesh if using new style
|
Add water sources to mesh if using new style
|
||||||
*/
|
*/
|
||||||
TileSpec tile_liquid = f.special_tiles[0];
|
TileSpec tile_liquid = getSpecialTile(f, n, 0);
|
||||||
TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data);
|
TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data);
|
||||||
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
|
video::SColor c1 = encode_light_and_color(l,
|
||||||
|
tile_liquid.color, f.light_source);
|
||||||
|
video::SColor c2 = encode_light_and_color(l,
|
||||||
|
tile_liquid_bfculled.color, f.light_source);
|
||||||
|
|
||||||
bool top_is_same_liquid = false;
|
bool top_is_same_liquid = false;
|
||||||
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
|
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
|
||||||
@ -237,9 +295,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
|
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
|
||||||
top_is_same_liquid = true;
|
top_is_same_liquid = true;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, nodedef);
|
|
||||||
video::SColor c = MapBlock_LightColor(f.alpha, l, f.light_source);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generate sides
|
Generate sides
|
||||||
*/
|
*/
|
||||||
@ -285,15 +340,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
// Use backface culled material if neighbor doesn't have a
|
// Use backface culled material if neighbor doesn't have a
|
||||||
// solidness of 0
|
// solidness of 0
|
||||||
const TileSpec *current_tile = &tile_liquid;
|
const TileSpec *current_tile = &tile_liquid;
|
||||||
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
|
video::SColor *c = &c1;
|
||||||
|
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0) {
|
||||||
current_tile = &tile_liquid_bfculled;
|
current_tile = &tile_liquid_bfculled;
|
||||||
|
c = &c2;
|
||||||
|
}
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,0,BS/2,0,0,0, c, 0,1),
|
video::S3DVertex(-BS/2,0,BS/2,0,0,0, *c, 0,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2,0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,BS/2,0,0,0, *c, 1,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, *c, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, *c, 0,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -359,10 +417,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c1, 0,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c1, 1,1),
|
||||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c1, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c1, 0,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
v3f offset(p.X * BS, (p.Y + 0.5) * BS, p.Z * BS);
|
v3f offset(p.X * BS, (p.Y + 0.5) * BS, p.Z * BS);
|
||||||
@ -380,8 +438,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
/*
|
/*
|
||||||
Add flowing liquid to mesh
|
Add flowing liquid to mesh
|
||||||
*/
|
*/
|
||||||
TileSpec tile_liquid = f.special_tiles[0];
|
TileSpec tile_liquid = getSpecialTile(f, n, 0);
|
||||||
TileSpec tile_liquid_bfculled = f.special_tiles[1];
|
TileSpec tile_liquid_bfculled = getSpecialTile(f, n, 1);
|
||||||
|
|
||||||
bool top_is_same_liquid = false;
|
bool top_is_same_liquid = false;
|
||||||
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
|
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
|
||||||
@ -404,7 +462,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
// Otherwise use the light of this node (the liquid)
|
// Otherwise use the light of this node (the liquid)
|
||||||
else
|
else
|
||||||
l = getInteriorLight(n, 0, nodedef);
|
l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(f.alpha, l, f.light_source);
|
video::SColor c1 = encode_light_and_color(l,
|
||||||
|
tile_liquid.color, f.light_source);
|
||||||
|
video::SColor c2 = encode_light_and_color(l,
|
||||||
|
tile_liquid_bfculled.color, f.light_source);
|
||||||
|
|
||||||
u8 range = rangelim(nodedef->get(c_flowing).liquid_range, 1, 8);
|
u8 range = rangelim(nodedef->get(c_flowing).liquid_range, 1, 8);
|
||||||
|
|
||||||
@ -552,7 +613,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
is liquid, don't draw side face
|
is liquid, don't draw side face
|
||||||
*/
|
*/
|
||||||
if (top_is_same_liquid &&
|
if (top_is_same_liquid &&
|
||||||
neighbor_data.flags & neighborflag_top_is_same_liquid)
|
(neighbor_data.flags & neighborflag_top_is_same_liquid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
content_t neighbor_content = neighbor_data.content;
|
content_t neighbor_content = neighbor_data.content;
|
||||||
@ -574,15 +635,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
// Use backface culled material if neighbor doesn't have a
|
// Use backface culled material if neighbor doesn't have a
|
||||||
// solidness of 0
|
// solidness of 0
|
||||||
const TileSpec *current_tile = &tile_liquid;
|
const TileSpec *current_tile = &tile_liquid;
|
||||||
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
|
video::SColor *c = &c1;
|
||||||
|
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0) {
|
||||||
current_tile = &tile_liquid_bfculled;
|
current_tile = &tile_liquid_bfculled;
|
||||||
|
c = &c2;
|
||||||
|
}
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, *c, 0,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, *c, 1,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, *c, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, *c, 0,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -656,10 +720,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
{
|
{
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c1, 0,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c1, 1,1),
|
||||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c1, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c1, 0,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// To get backface culling right, the vertices need to go
|
// To get backface culling right, the vertices need to go
|
||||||
@ -720,8 +784,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
|
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
for(u32 j=0; j<6; j++)
|
for(u32 j=0; j<6; j++)
|
||||||
{
|
{
|
||||||
// Check this neighbor
|
// Check this neighbor
|
||||||
@ -731,13 +795,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
// Don't make face if neighbor is of same type
|
// Don't make face if neighbor is of same type
|
||||||
if(n2.getContent() == n.getContent())
|
if(n2.getContent() == n.getContent())
|
||||||
continue;
|
continue;
|
||||||
|
video::SColor c2=c;
|
||||||
|
if(!f.light_source)
|
||||||
|
applyFacesShading(c2, v3f(dir.X, dir.Y, dir.Z));
|
||||||
|
|
||||||
|
|
||||||
// The face at Z+
|
// The face at Z+
|
||||||
video::S3DVertex vertices[4] = {
|
video::S3DVertex vertices[4] = {
|
||||||
video::S3DVertex(-BS/2,-BS/2,BS/2, dir.X,dir.Y,dir.Z, c, 1,1),
|
video::S3DVertex(-BS/2,-BS/2,BS/2, dir.X,dir.Y,dir.Z, c2, 1,1),
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, dir.X,dir.Y,dir.Z, c, 0,1),
|
video::S3DVertex(BS/2,-BS/2,BS/2, dir.X,dir.Y,dir.Z, c2, 0,1),
|
||||||
video::S3DVertex(BS/2,BS/2,BS/2, dir.X,dir.Y,dir.Z, c, 0,0),
|
video::S3DVertex(BS/2,BS/2,BS/2, dir.X,dir.Y,dir.Z, c2, 0,0),
|
||||||
video::S3DVertex(-BS/2,BS/2,BS/2, dir.X,dir.Y,dir.Z, c, 1,0),
|
video::S3DVertex(-BS/2,BS/2,BS/2, dir.X,dir.Y,dir.Z, c2, 1,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rotations in the g_6dirs format
|
// Rotations in the g_6dirs format
|
||||||
@ -784,12 +852,20 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
v3s16( 0, 0,-1)
|
v3s16( 0, 0,-1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
u8 i;
|
u8 i;
|
||||||
TileSpec tiles[6];
|
TileSpec tiles[6];
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
tiles[i] = getNodeTile(n, p, dirs[i], data);
|
tiles[i] = getNodeTile(n, p, dirs[i], data);
|
||||||
|
|
||||||
|
video::SColor tile0color = encode_light_and_color(l,
|
||||||
|
tiles[0].color, f.light_source);
|
||||||
|
video::SColor tile0colors[6];
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
tile0colors[i] = tile0color;
|
||||||
|
|
||||||
TileSpec glass_tiles[6];
|
TileSpec glass_tiles[6];
|
||||||
|
video::SColor glasscolor[6];
|
||||||
if (tiles[1].texture && tiles[2].texture && tiles[3].texture) {
|
if (tiles[1].texture && tiles[2].texture && tiles[3].texture) {
|
||||||
glass_tiles[0] = tiles[2];
|
glass_tiles[0] = tiles[2];
|
||||||
glass_tiles[1] = tiles[3];
|
glass_tiles[1] = tiles[3];
|
||||||
@ -801,14 +877,15 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
glass_tiles[i] = tiles[1];
|
glass_tiles[i] = tiles[1];
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
glasscolor[i] = encode_light_and_color(l, glass_tiles[i].color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
u8 param2 = n.getParam2();
|
u8 param2 = n.getParam2();
|
||||||
bool H_merge = ! bool(param2 & 128);
|
bool H_merge = ! bool(param2 & 128);
|
||||||
bool V_merge = ! bool(param2 & 64);
|
bool V_merge = ! bool(param2 & 64);
|
||||||
param2 = param2 & 63;
|
param2 = param2 & 63;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
static const float a = BS / 2;
|
static const float a = BS / 2;
|
||||||
static const float g = a - 0.003;
|
static const float g = a - 0.003;
|
||||||
@ -947,7 +1024,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
||||||
tx1, 1-ty2, tx2, 1-ty1,
|
tx1, 1-ty2, tx2, 1-ty1,
|
||||||
};
|
};
|
||||||
makeCuboid(&collector, box, &tiles[0], 1, c, txc1);
|
makeCuboid(&collector, box, &tiles[0], 1, tile0colors,
|
||||||
|
txc1, f.light_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < 6; i++)
|
for(i = 0; i < 6; i++)
|
||||||
@ -971,16 +1049,21 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
||||||
tx1, 1-ty2, tx2, 1-ty1,
|
tx1, 1-ty2, tx2, 1-ty1,
|
||||||
};
|
};
|
||||||
makeCuboid(&collector, box, &glass_tiles[i], 1, c, txc2);
|
makeCuboid(&collector, box, &glass_tiles[i], 1, glasscolor,
|
||||||
|
txc2, f.light_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param2 > 0 && f.special_tiles[0].texture) {
|
if (param2 > 0 && f.special_tiles[0].texture) {
|
||||||
// Interior volume level is in range 0 .. 63,
|
// Interior volume level is in range 0 .. 63,
|
||||||
// convert it to -0.5 .. 0.5
|
// convert it to -0.5 .. 0.5
|
||||||
float vlev = (((float)param2 / 63.0 ) * 2.0 - 1.0);
|
float vlev = (((float)param2 / 63.0 ) * 2.0 - 1.0);
|
||||||
|
TileSpec tile=getSpecialTile(f, n, 0);
|
||||||
|
video::SColor special_color = encode_light_and_color(l,
|
||||||
|
tile.color, f.light_source);
|
||||||
TileSpec interior_tiles[6];
|
TileSpec interior_tiles[6];
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
interior_tiles[i] = f.special_tiles[0];
|
interior_tiles[i] = tile;
|
||||||
|
|
||||||
float offset = 0.003;
|
float offset = 0.003;
|
||||||
box = aabb3f(visible_faces[3] ? -b : -a + offset,
|
box = aabb3f(visible_faces[3] ? -b : -a + offset,
|
||||||
visible_faces[1] ? -b : -a + offset,
|
visible_faces[1] ? -b : -a + offset,
|
||||||
@ -1004,22 +1087,24 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
||||||
tx1, 1-ty2, tx2, 1-ty1,
|
tx1, 1-ty2, tx2, 1-ty1,
|
||||||
};
|
};
|
||||||
makeCuboid(&collector, box, interior_tiles, 6, c, txc3);
|
makeCuboid(&collector, box, interior_tiles, 6, special_color,
|
||||||
|
txc3, f.light_source);
|
||||||
}
|
}
|
||||||
break;}
|
break;}
|
||||||
case NDT_ALLFACES:
|
case NDT_ALLFACES:
|
||||||
{
|
{
|
||||||
TileSpec tile_leaves = getNodeTile(n, p,
|
TileSpec tile_leaves = getNodeTile(n, p,
|
||||||
v3s16(0,0,0), data);
|
v3s16(0,0,0), data);
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l,
|
||||||
|
tile_leaves.color, f.light_source);
|
||||||
|
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
|
aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
|
||||||
box.MinEdge += pos;
|
box.MinEdge += pos;
|
||||||
box.MaxEdge += pos;
|
box.MaxEdge += pos;
|
||||||
makeCuboid(&collector, box, &tile_leaves, 1, c, NULL);
|
makeCuboid(&collector, box, &tile_leaves, 1, c, NULL,
|
||||||
|
f.light_source);
|
||||||
break;}
|
break;}
|
||||||
case NDT_ALLFACES_OPTIONAL:
|
case NDT_ALLFACES_OPTIONAL:
|
||||||
// This is always pre-converted to something else
|
// This is always pre-converted to something else
|
||||||
@ -1046,7 +1131,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
float s = BS/2*f.visual_scale;
|
float s = BS/2*f.visual_scale;
|
||||||
// Wall at X+ of node
|
// Wall at X+ of node
|
||||||
@ -1087,7 +1173,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, nodedef);
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
float d = (float)BS/16;
|
float d = (float)BS/16;
|
||||||
float s = BS/2*f.visual_scale;
|
float s = BS/2*f.visual_scale;
|
||||||
@ -1132,7 +1219,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
float s = BS / 2 * f.visual_scale;
|
float s = BS / 2 * f.visual_scale;
|
||||||
// add sqrt(2) visual scale
|
// add sqrt(2) visual scale
|
||||||
@ -1302,7 +1390,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
float s = BS / 2 * f.visual_scale;
|
float s = BS / 2 * f.visual_scale;
|
||||||
|
|
||||||
@ -1437,7 +1526,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
tile_rot.rotation = 1;
|
tile_rot.rotation = 1;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
const f32 post_rad=(f32)BS/8;
|
const f32 post_rad=(f32)BS/8;
|
||||||
const f32 bar_rad=(f32)BS/16;
|
const f32 bar_rad=(f32)BS/16;
|
||||||
@ -1456,7 +1546,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
4/16.,0,8/16.,1,
|
4/16.,0,8/16.,1,
|
||||||
8/16.,0,12/16.,1,
|
8/16.,0,12/16.,1,
|
||||||
12/16.,0,16/16.,1};
|
12/16.,0,16/16.,1};
|
||||||
makeCuboid(&collector, post, &tile_rot, 1, c, postuv);
|
makeCuboid(&collector, post, &tile_rot, 1, c, postuv,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
// Now a section of fence, +X, if there's a post there
|
// Now a section of fence, +X, if there's a post there
|
||||||
v3s16 p2 = p;
|
v3s16 p2 = p;
|
||||||
@ -1477,11 +1568,11 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
0/16.,8/16.,16/16.,10/16.,
|
0/16.,8/16.,16/16.,10/16.,
|
||||||
0/16.,14/16.,16/16.,16/16.};
|
0/16.,14/16.,16/16.,16/16.};
|
||||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||||
c, xrailuv);
|
c, xrailuv, f.light_source);
|
||||||
bar.MinEdge.Y -= BS/2;
|
bar.MinEdge.Y -= BS/2;
|
||||||
bar.MaxEdge.Y -= BS/2;
|
bar.MaxEdge.Y -= BS/2;
|
||||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||||
c, xrailuv);
|
c, xrailuv, f.light_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now a section of fence, +Z, if there's a post there
|
// Now a section of fence, +Z, if there's a post there
|
||||||
@ -1503,11 +1594,11 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
6/16.,6/16.,8/16.,8/16.,
|
6/16.,6/16.,8/16.,8/16.,
|
||||||
10/16.,10/16.,12/16.,12/16.};
|
10/16.,10/16.,12/16.,12/16.};
|
||||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||||
c, zrailuv);
|
c, zrailuv, f.light_source);
|
||||||
bar.MinEdge.Y -= BS/2;
|
bar.MinEdge.Y -= BS/2;
|
||||||
bar.MaxEdge.Y -= BS/2;
|
bar.MaxEdge.Y -= BS/2;
|
||||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||||
c, zrailuv);
|
c, zrailuv, f.light_source);
|
||||||
}
|
}
|
||||||
break;}
|
break;}
|
||||||
case NDT_RAILLIKE:
|
case NDT_RAILLIKE:
|
||||||
@ -1616,7 +1707,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, nodedef);
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
video::SColor c = encode_light_and_color(l, tile.color,
|
||||||
|
f.light_source);
|
||||||
|
|
||||||
float d = (float)BS/64;
|
float d = (float)BS/64;
|
||||||
float s = BS/2;
|
float s = BS/2;
|
||||||
@ -1627,10 +1719,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-s, -s+d,-s, 0,0,0, c,0,1),
|
video::S3DVertex(-s, -s+d, -s, 0, 0, 0, c, 0, 1),
|
||||||
video::S3DVertex( s, -s+d,-s, 0,0,0, c,1,1),
|
video::S3DVertex( s, -s+d, -s, 0, 0, 0, c, 1, 1),
|
||||||
video::S3DVertex( s, g*s+d, s, 0,0,0, c,1,0),
|
video::S3DVertex( s, g*s+d, s, 0, 0, 0, c, 1, 0),
|
||||||
video::S3DVertex(-s, g*s+d, s, 0,0,0, c,0,0),
|
video::S3DVertex(-s, g*s+d, s, 0, 0, 0, c, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
for(s32 i=0; i<4; i++)
|
for(s32 i=0; i<4; i++)
|
||||||
@ -1653,10 +1745,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
v3s16(0, 0, 1),
|
v3s16(0, 0, 1),
|
||||||
v3s16(0, 0, -1)
|
v3s16(0, 0, -1)
|
||||||
};
|
};
|
||||||
TileSpec tiles[6];
|
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, nodedef);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
|
TileSpec tiles[6];
|
||||||
|
video::SColor colors[6];
|
||||||
|
for(int j = 0; j < 6; j++) {
|
||||||
|
// Handles facedir rotation for textures
|
||||||
|
tiles[j] = getNodeTile(n, p, tile_dirs[j], data);
|
||||||
|
colors[j]= encode_light_and_color(l, tiles[j].color,
|
||||||
|
f.light_source);
|
||||||
|
}
|
||||||
|
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
|
|
||||||
@ -1696,11 +1794,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
i = boxes.begin();
|
i = boxes.begin();
|
||||||
i != boxes.end(); ++i)
|
i != boxes.end(); ++i)
|
||||||
{
|
{
|
||||||
for(int j = 0; j < 6; j++)
|
|
||||||
{
|
|
||||||
// Handles facedir rotation for textures
|
|
||||||
tiles[j] = getNodeTile(n, p, tile_dirs[j], data);
|
|
||||||
}
|
|
||||||
aabb3f box = *i;
|
aabb3f box = *i;
|
||||||
box.MinEdge += pos;
|
box.MinEdge += pos;
|
||||||
box.MaxEdge += pos;
|
box.MaxEdge += pos;
|
||||||
@ -1747,18 +1840,19 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
// front
|
// front
|
||||||
tx1, 1-ty2, tx2, 1-ty1,
|
tx1, 1-ty2, tx2, 1-ty1,
|
||||||
};
|
};
|
||||||
makeCuboid(&collector, box, tiles, 6, c, txc);
|
makeCuboid(&collector, box, tiles, 6, colors, txc, f.light_source);
|
||||||
}
|
}
|
||||||
break;}
|
break;}
|
||||||
case NDT_MESH:
|
case NDT_MESH:
|
||||||
{
|
{
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
video::SColor c = MapBlock_LightColor(255, getInteriorLight(n, 1, nodedef), f.light_source);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
|
|
||||||
u8 facedir = 0;
|
u8 facedir = 0;
|
||||||
if (f.param_type_2 == CPT2_FACEDIR) {
|
if (f.param_type_2 == CPT2_FACEDIR ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
facedir = n.getFaceDir(nodedef);
|
facedir = n.getFaceDir(nodedef);
|
||||||
} else if (f.param_type_2 == CPT2_WALLMOUNTED) {
|
} else if (f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
//convert wallmounted to 6dfacedir.
|
//convert wallmounted to 6dfacedir.
|
||||||
//when cache enabled, it is already converted
|
//when cache enabled, it is already converted
|
||||||
facedir = n.getWallMounted(nodedef);
|
facedir = n.getWallMounted(nodedef);
|
||||||
@ -1771,10 +1865,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
if (f.mesh_ptr[facedir]) {
|
if (f.mesh_ptr[facedir]) {
|
||||||
// use cached meshes
|
// use cached meshes
|
||||||
for(u16 j = 0; j < f.mesh_ptr[0]->getMeshBufferCount(); j++) {
|
for(u16 j = 0; j < f.mesh_ptr[0]->getMeshBufferCount(); j++) {
|
||||||
|
const TileSpec &tile = getNodeTileN(n, p, j, data);
|
||||||
scene::IMeshBuffer *buf = f.mesh_ptr[facedir]->getMeshBuffer(j);
|
scene::IMeshBuffer *buf = f.mesh_ptr[facedir]->getMeshBuffer(j);
|
||||||
collector.append(getNodeTileN(n, p, j, data),
|
collector.append(tile, (video::S3DVertex *)
|
||||||
(video::S3DVertex *)buf->getVertices(), buf->getVertexCount(),
|
buf->getVertices(), buf->getVertexCount(),
|
||||||
buf->getIndices(), buf->getIndexCount(), pos, c);
|
buf->getIndices(), buf->getIndexCount(), pos,
|
||||||
|
encode_light_and_color(l, tile.color, f.light_source),
|
||||||
|
f.light_source);
|
||||||
}
|
}
|
||||||
} else if (f.mesh_ptr[0]) {
|
} else if (f.mesh_ptr[0]) {
|
||||||
// no cache, clone and rotate mesh
|
// no cache, clone and rotate mesh
|
||||||
@ -1783,10 +1880,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
recalculateBoundingBox(mesh);
|
recalculateBoundingBox(mesh);
|
||||||
meshmanip->recalculateNormals(mesh, true, false);
|
meshmanip->recalculateNormals(mesh, true, false);
|
||||||
for(u16 j = 0; j < mesh->getMeshBufferCount(); j++) {
|
for(u16 j = 0; j < mesh->getMeshBufferCount(); j++) {
|
||||||
|
const TileSpec &tile = getNodeTileN(n, p, j, data);
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
collector.append(getNodeTileN(n, p, j, data),
|
collector.append(tile, (video::S3DVertex *)
|
||||||
(video::S3DVertex *)buf->getVertices(), buf->getVertexCount(),
|
buf->getVertices(), buf->getVertexCount(),
|
||||||
buf->getIndices(), buf->getIndexCount(), pos, c);
|
buf->getIndices(), buf->getIndexCount(), pos,
|
||||||
|
encode_light_and_color(l, tile.color, f.light_source),
|
||||||
|
f.light_source);
|
||||||
}
|
}
|
||||||
mesh->drop();
|
mesh->drop();
|
||||||
}
|
}
|
||||||
|
30
src/game.cpp
30
src/game.cpp
@ -642,7 +642,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
|||||||
CachedPixelShaderSetting<float> m_fog_distance;
|
CachedPixelShaderSetting<float> m_fog_distance;
|
||||||
CachedVertexShaderSetting<float> m_animation_timer_vertex;
|
CachedVertexShaderSetting<float> m_animation_timer_vertex;
|
||||||
CachedPixelShaderSetting<float> m_animation_timer_pixel;
|
CachedPixelShaderSetting<float> m_animation_timer_pixel;
|
||||||
CachedPixelShaderSetting<float> m_day_night_ratio;
|
CachedPixelShaderSetting<float, 3> m_day_light;
|
||||||
CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
|
CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
|
||||||
CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
|
CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
|
||||||
CachedPixelShaderSetting<float, 3> m_minimap_yaw;
|
CachedPixelShaderSetting<float, 3> m_minimap_yaw;
|
||||||
@ -674,7 +674,7 @@ public:
|
|||||||
m_fog_distance("fogDistance"),
|
m_fog_distance("fogDistance"),
|
||||||
m_animation_timer_vertex("animationTimer"),
|
m_animation_timer_vertex("animationTimer"),
|
||||||
m_animation_timer_pixel("animationTimer"),
|
m_animation_timer_pixel("animationTimer"),
|
||||||
m_day_night_ratio("dayNightRatio"),
|
m_day_light("dayLight"),
|
||||||
m_eye_position_pixel("eyePosition"),
|
m_eye_position_pixel("eyePosition"),
|
||||||
m_eye_position_vertex("eyePosition"),
|
m_eye_position_vertex("eyePosition"),
|
||||||
m_minimap_yaw("yawVec"),
|
m_minimap_yaw("yawVec"),
|
||||||
@ -717,8 +717,14 @@ public:
|
|||||||
|
|
||||||
m_fog_distance.set(&fog_distance, services);
|
m_fog_distance.set(&fog_distance, services);
|
||||||
|
|
||||||
float daynight_ratio = (float)m_client->getEnv().getDayNightRatio() / 1000.f;
|
u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
|
||||||
m_day_night_ratio.set(&daynight_ratio, services);
|
video::SColorf sunlight;
|
||||||
|
get_sunlight_color(&sunlight, daynight_ratio);
|
||||||
|
float dnc[3] = {
|
||||||
|
sunlight.r,
|
||||||
|
sunlight.g,
|
||||||
|
sunlight.b };
|
||||||
|
m_day_light.set(dnc, services);
|
||||||
|
|
||||||
u32 animation_timer = porting::getTimeMs() % 100000;
|
u32 animation_timer = porting::getTimeMs() % 100000;
|
||||||
float animation_timer_f = (float)animation_timer / 100000.f;
|
float animation_timer_f = (float)animation_timer / 100000.f;
|
||||||
@ -840,7 +846,8 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
// Predict param2 for facedir and wallmounted nodes
|
// Predict param2 for facedir and wallmounted nodes
|
||||||
u8 param2 = 0;
|
u8 param2 = 0;
|
||||||
|
|
||||||
if (nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED) {
|
if (nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
|
nodedef->get(id).param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
v3s16 dir = nodepos - neighbourpos;
|
v3s16 dir = nodepos - neighbourpos;
|
||||||
|
|
||||||
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
|
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
|
||||||
@ -852,7 +859,8 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodedef->get(id).param_type_2 == CPT2_FACEDIR) {
|
if (nodedef->get(id).param_type_2 == CPT2_FACEDIR ||
|
||||||
|
nodedef->get(id).param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
v3s16 dir = nodepos - floatToInt(client.getEnv().getLocalPlayer()->getPosition(), BS);
|
v3s16 dir = nodepos - floatToInt(client.getEnv().getLocalPlayer()->getPosition(), BS);
|
||||||
|
|
||||||
if (abs(dir.X) > abs(dir.Z)) {
|
if (abs(dir.X) > abs(dir.Z)) {
|
||||||
@ -3749,11 +3757,9 @@ PointedThing Game::updatePointedThing(
|
|||||||
light_level = node_light;
|
light_level = node_light;
|
||||||
}
|
}
|
||||||
|
|
||||||
video::SColor c = MapBlock_LightColor(255, light_level, 0);
|
|
||||||
u8 day = c.getRed();
|
|
||||||
u8 night = c.getGreen();
|
|
||||||
u32 daynight_ratio = client->getEnv().getDayNightRatio();
|
u32 daynight_ratio = client->getEnv().getDayNightRatio();
|
||||||
finalColorBlend(c, day, night, daynight_ratio);
|
video::SColor c;
|
||||||
|
final_color_blend(&c, light_level, daynight_ratio);
|
||||||
|
|
||||||
// Modify final color a bit with time
|
// Modify final color a bit with time
|
||||||
u32 timer = porting::getTimeMs() % 5000;
|
u32 timer = porting::getTimeMs() % 5000;
|
||||||
@ -3964,7 +3970,7 @@ void Game::handleDigging(GameRunData *runData,
|
|||||||
const ContentFeatures &features =
|
const ContentFeatures &features =
|
||||||
client->getNodeDefManager()->get(n);
|
client->getNodeDefManager()->get(n);
|
||||||
client->getParticleManager()->addPunchingParticles(client, smgr,
|
client->getParticleManager()->addPunchingParticles(client, smgr,
|
||||||
player, nodepos, features.tiles);
|
player, nodepos, n, features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4011,7 +4017,7 @@ void Game::handleDigging(GameRunData *runData,
|
|||||||
const ContentFeatures &features =
|
const ContentFeatures &features =
|
||||||
client->getNodeDefManager()->get(wasnode);
|
client->getNodeDefManager()->get(wasnode);
|
||||||
client->getParticleManager()->addDiggingParticles(client, smgr,
|
client->getParticleManager()->addDiggingParticles(client, smgr,
|
||||||
player, nodepos, features.tiles);
|
player, nodepos, wasnode, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
runData->dig_time = 0;
|
runData->dig_time = 0;
|
||||||
|
@ -32,12 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
#include <IMeshManipulator.h>
|
#include <IMeshManipulator.h>
|
||||||
|
|
||||||
static void applyFacesShading(video::SColor &color, const float factor)
|
|
||||||
{
|
|
||||||
color.setRed(core::clamp(core::round32(color.getRed() * factor), 0, 255));
|
|
||||||
color.setGreen(core::clamp(core::round32(color.getGreen() * factor), 0, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MeshMakeData
|
MeshMakeData
|
||||||
*/
|
*/
|
||||||
@ -321,19 +315,34 @@ u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data)
|
|||||||
return getSmoothLightCombined(p, data);
|
return getSmoothLightCombined(p, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){
|
||||||
Converts from day + night color values (0..255)
|
f32 rg = daynight_ratio / 1000.0f - 0.04f;
|
||||||
and a given daynight_ratio to the final SColor shown on screen.
|
f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f;
|
||||||
*/
|
sunlight->r = rg;
|
||||||
void finalColorBlend(video::SColor& result,
|
sunlight->g = rg;
|
||||||
u8 day, u8 night, u32 daynight_ratio)
|
sunlight->b = b;
|
||||||
{
|
}
|
||||||
s32 rg = (day * daynight_ratio + night * (1000-daynight_ratio)) / 1000;
|
|
||||||
s32 b = rg;
|
|
||||||
|
|
||||||
// Moonlight is blue
|
void final_color_blend(video::SColor *result,
|
||||||
b += (day - night) / 13;
|
u16 light, u32 daynight_ratio)
|
||||||
rg -= (day - night) / 23;
|
{
|
||||||
|
video::SColorf dayLight;
|
||||||
|
get_sunlight_color(&dayLight, daynight_ratio);
|
||||||
|
final_color_blend(result,
|
||||||
|
encode_light_and_color(light, video::SColor(0xFFFFFFFF), 0), dayLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void final_color_blend(video::SColor *result,
|
||||||
|
const video::SColor &data, const video::SColorf &dayLight)
|
||||||
|
{
|
||||||
|
static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f);
|
||||||
|
|
||||||
|
video::SColorf c(data);
|
||||||
|
f32 n = 1 - c.a;
|
||||||
|
|
||||||
|
f32 r = c.r * (c.a * dayLight.r + n * artificialColor.r) * 2.0f;
|
||||||
|
f32 g = c.g * (c.a * dayLight.g + n * artificialColor.g) * 2.0f;
|
||||||
|
f32 b = c.b * (c.a * dayLight.b + n * artificialColor.b) * 2.0f;
|
||||||
|
|
||||||
// Emphase blue a bit in darker places
|
// Emphase blue a bit in darker places
|
||||||
// Each entry of this array represents a range of 8 blue levels
|
// Each entry of this array represents a range of 8 blue levels
|
||||||
@ -341,19 +350,13 @@ void finalColorBlend(video::SColor& result,
|
|||||||
1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
|
1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
};
|
};
|
||||||
b += emphase_blue_when_dark[irr::core::clamp(b, 0, 255) / 8];
|
|
||||||
b = irr::core::clamp(b, 0, 255);
|
|
||||||
|
|
||||||
// Artificial light is yellow-ish
|
b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255),
|
||||||
static const u8 emphase_yellow_when_artificial[16] = {
|
0, 255) / 8] / 255.0f;
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 15, 15, 15
|
|
||||||
};
|
|
||||||
rg += emphase_yellow_when_artificial[night/16];
|
|
||||||
rg = irr::core::clamp(rg, 0, 255);
|
|
||||||
|
|
||||||
result.setRed(rg);
|
result->setRed(core::clamp((s32) (r * 255.0f), 0, 255));
|
||||||
result.setGreen(rg);
|
result->setGreen(core::clamp((s32) (g * 255.0f), 0, 255));
|
||||||
result.setBlue(b);
|
result->setBlue(core::clamp((s32) (b * 255.0f), 0, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -430,7 +433,7 @@ struct FastFace
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
||||||
v3f p, v3s16 dir, v3f scale, u8 light_source, std::vector<FastFace> &dest)
|
v3f p, v3s16 dir, v3f scale, std::vector<FastFace> &dest)
|
||||||
{
|
{
|
||||||
// Position is at the center of the cube.
|
// Position is at the center of the cube.
|
||||||
v3f pos = p * BS;
|
v3f pos = p * BS;
|
||||||
@ -580,24 +583,25 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
|||||||
|
|
||||||
v3f normal(dir.X, dir.Y, dir.Z);
|
v3f normal(dir.X, dir.Y, dir.Z);
|
||||||
|
|
||||||
u8 alpha = tile.alpha;
|
|
||||||
|
|
||||||
dest.push_back(FastFace());
|
dest.push_back(FastFace());
|
||||||
|
|
||||||
FastFace& face = *dest.rbegin();
|
FastFace& face = *dest.rbegin();
|
||||||
|
|
||||||
face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
|
u16 li[4] = { li0, li1, li2, li3 };
|
||||||
MapBlock_LightColor(alpha, li0, light_source),
|
v2f32 f[4] = {
|
||||||
core::vector2d<f32>(x0+w*abs_scale, y0+h));
|
core::vector2d<f32>(x0 + w * abs_scale, y0 + h),
|
||||||
face.vertices[1] = video::S3DVertex(vertex_pos[1], normal,
|
core::vector2d<f32>(x0, y0 + h),
|
||||||
MapBlock_LightColor(alpha, li1, light_source),
|
core::vector2d<f32>(x0, y0),
|
||||||
core::vector2d<f32>(x0, y0+h));
|
core::vector2d<f32>(x0 + w * abs_scale, y0) };
|
||||||
face.vertices[2] = video::S3DVertex(vertex_pos[2], normal,
|
|
||||||
MapBlock_LightColor(alpha, li2, light_source),
|
for (u8 i = 0; i < 4; i++) {
|
||||||
core::vector2d<f32>(x0, y0));
|
video::SColor c = encode_light_and_color(li[i], tile.color,
|
||||||
face.vertices[3] = video::S3DVertex(vertex_pos[3], normal,
|
tile.emissive_light);
|
||||||
MapBlock_LightColor(alpha, li3, light_source),
|
if (!tile.emissive_light)
|
||||||
core::vector2d<f32>(x0+w*abs_scale, y0));
|
applyFacesShading(c, normal);
|
||||||
|
|
||||||
|
face.vertices[i] = video::S3DVertex(vertex_pos[i], normal, c, f[i]);
|
||||||
|
}
|
||||||
|
|
||||||
face.tile = tile;
|
face.tile = tile;
|
||||||
}
|
}
|
||||||
@ -664,7 +668,10 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
|
|||||||
TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
|
TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
|
||||||
{
|
{
|
||||||
INodeDefManager *ndef = data->m_client->ndef();
|
INodeDefManager *ndef = data->m_client->ndef();
|
||||||
TileSpec spec = ndef->get(mn).tiles[tileindex];
|
const ContentFeatures &f = ndef->get(mn);
|
||||||
|
TileSpec spec = f.tiles[tileindex];
|
||||||
|
if (!spec.has_color)
|
||||||
|
mn.getColor(f, &spec.color);
|
||||||
// Apply temporary crack
|
// Apply temporary crack
|
||||||
if (p == data->m_crack_pos_relative)
|
if (p == data->m_crack_pos_relative)
|
||||||
spec.material_flags |= MATERIAL_FLAG_CRACK;
|
spec.material_flags |= MATERIAL_FLAG_CRACK;
|
||||||
@ -747,8 +754,7 @@ static void getTileInfo(
|
|||||||
v3s16 &p_corrected,
|
v3s16 &p_corrected,
|
||||||
v3s16 &face_dir_corrected,
|
v3s16 &face_dir_corrected,
|
||||||
u16 *lights,
|
u16 *lights,
|
||||||
TileSpec &tile,
|
TileSpec &tile
|
||||||
u8 &light_source
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
VoxelManipulator &vmanip = data->m_vmanip;
|
VoxelManipulator &vmanip = data->m_vmanip;
|
||||||
@ -763,7 +769,8 @@ static void getTileInfo(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir);
|
const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(
|
||||||
|
blockpos_nodes + p + face_dir);
|
||||||
|
|
||||||
if (n1.getContent() == CONTENT_IGNORE) {
|
if (n1.getContent() == CONTENT_IGNORE) {
|
||||||
makes_face = false;
|
makes_face = false;
|
||||||
@ -783,26 +790,25 @@ static void getTileInfo(
|
|||||||
|
|
||||||
makes_face = true;
|
makes_face = true;
|
||||||
|
|
||||||
if(mf == 1)
|
MapNode n = n0;
|
||||||
{
|
|
||||||
tile = getNodeTile(n0, p, face_dir, data);
|
if (mf == 1) {
|
||||||
p_corrected = p;
|
p_corrected = p;
|
||||||
face_dir_corrected = face_dir;
|
face_dir_corrected = face_dir;
|
||||||
light_source = ndef->get(n0).light_source;
|
} else {
|
||||||
}
|
n = n1;
|
||||||
else
|
|
||||||
{
|
|
||||||
tile = getNodeTile(n1, p + face_dir, -face_dir, data);
|
|
||||||
p_corrected = p + face_dir;
|
p_corrected = p + face_dir;
|
||||||
face_dir_corrected = -face_dir;
|
face_dir_corrected = -face_dir;
|
||||||
light_source = ndef->get(n1).light_source;
|
|
||||||
}
|
}
|
||||||
|
tile = getNodeTile(n, p_corrected, face_dir_corrected, data);
|
||||||
|
const ContentFeatures &f = ndef->get(n);
|
||||||
|
tile.emissive_light = f.light_source;
|
||||||
|
|
||||||
// eg. water and glass
|
// eg. water and glass
|
||||||
if(equivalent)
|
if (equivalent)
|
||||||
tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
|
|
||||||
if(data->m_smooth_lighting == false)
|
if (data->m_smooth_lighting == false)
|
||||||
{
|
{
|
||||||
lights[0] = lights[1] = lights[2] = lights[3] =
|
lights[0] = lights[1] = lights[2] = lights[3] =
|
||||||
getFaceLight(n0, n1, face_dir, ndef);
|
getFaceLight(n0, n1, face_dir, ndef);
|
||||||
@ -845,10 +851,9 @@ static void updateFastFaceRow(
|
|||||||
v3s16 face_dir_corrected;
|
v3s16 face_dir_corrected;
|
||||||
u16 lights[4] = {0,0,0,0};
|
u16 lights[4] = {0,0,0,0};
|
||||||
TileSpec tile;
|
TileSpec tile;
|
||||||
u8 light_source = 0;
|
|
||||||
getTileInfo(data, p, face_dir,
|
getTileInfo(data, p, face_dir,
|
||||||
makes_face, p_corrected, face_dir_corrected,
|
makes_face, p_corrected, face_dir_corrected,
|
||||||
lights, tile, light_source);
|
lights, tile);
|
||||||
|
|
||||||
for(u16 j=0; j<MAP_BLOCKSIZE; j++)
|
for(u16 j=0; j<MAP_BLOCKSIZE; j++)
|
||||||
{
|
{
|
||||||
@ -862,7 +867,6 @@ static void updateFastFaceRow(
|
|||||||
v3s16 next_face_dir_corrected;
|
v3s16 next_face_dir_corrected;
|
||||||
u16 next_lights[4] = {0,0,0,0};
|
u16 next_lights[4] = {0,0,0,0};
|
||||||
TileSpec next_tile;
|
TileSpec next_tile;
|
||||||
u8 next_light_source = 0;
|
|
||||||
|
|
||||||
// If at last position, there is nothing to compare to and
|
// If at last position, there is nothing to compare to and
|
||||||
// the face must be drawn anyway
|
// the face must be drawn anyway
|
||||||
@ -873,7 +877,7 @@ static void updateFastFaceRow(
|
|||||||
getTileInfo(data, p_next, face_dir,
|
getTileInfo(data, p_next, face_dir,
|
||||||
next_makes_face, next_p_corrected,
|
next_makes_face, next_p_corrected,
|
||||||
next_face_dir_corrected, next_lights,
|
next_face_dir_corrected, next_lights,
|
||||||
next_tile, next_light_source);
|
next_tile);
|
||||||
|
|
||||||
if(next_makes_face == makes_face
|
if(next_makes_face == makes_face
|
||||||
&& next_p_corrected == p_corrected + translate_dir
|
&& next_p_corrected == p_corrected + translate_dir
|
||||||
@ -884,9 +888,10 @@ static void updateFastFaceRow(
|
|||||||
&& next_lights[3] == lights[3]
|
&& next_lights[3] == lights[3]
|
||||||
&& next_tile == tile
|
&& next_tile == tile
|
||||||
&& tile.rotation == 0
|
&& tile.rotation == 0
|
||||||
&& next_light_source == light_source
|
|
||||||
&& (tile.material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)
|
&& (tile.material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)
|
||||||
&& (tile.material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) {
|
&& (tile.material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)
|
||||||
|
&& tile.color == next_tile.color
|
||||||
|
&& tile.emissive_light == next_tile.emissive_light) {
|
||||||
next_is_different = false;
|
next_is_different = false;
|
||||||
continuous_tiles_count++;
|
continuous_tiles_count++;
|
||||||
} else {
|
} else {
|
||||||
@ -938,8 +943,7 @@ static void updateFastFaceRow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
|
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
|
||||||
sp, face_dir_corrected, scale, light_source,
|
sp, face_dir_corrected, scale, dest);
|
||||||
dest);
|
|
||||||
|
|
||||||
g_profiler->avg("Meshgen: faces drawn by tiling", 0);
|
g_profiler->avg("Meshgen: faces drawn by tiling", 0);
|
||||||
for(int i = 1; i < continuous_tiles_count; i++){
|
for(int i = 1; i < continuous_tiles_count; i++){
|
||||||
@ -958,7 +962,6 @@ static void updateFastFaceRow(
|
|||||||
lights[2] = next_lights[2];
|
lights[2] = next_lights[2];
|
||||||
lights[3] = next_lights[3];
|
lights[3] = next_lights[3];
|
||||||
tile = next_tile;
|
tile = next_tile;
|
||||||
light_source = next_light_source;
|
|
||||||
p = p_next;
|
p = p_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1083,12 +1086,14 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
|||||||
const u16 *indices_p = indices;
|
const u16 *indices_p = indices;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Revert triangles for nicer looking gradient if vertices
|
Revert triangles for nicer looking gradient if the
|
||||||
1 and 3 have same color or 0 and 2 have different color.
|
brightness of vertices 1 and 3 differ less than
|
||||||
getRed() is the day color.
|
the brightness of vertices 0 and 2.
|
||||||
*/
|
*/
|
||||||
if(f.vertices[0].Color.getRed() != f.vertices[2].Color.getRed()
|
if (abs(f.vertices[0].Color.getAverage()
|
||||||
|| f.vertices[1].Color.getRed() == f.vertices[3].Color.getRed())
|
- f.vertices[2].Color.getAverage())
|
||||||
|
> abs(f.vertices[1].Color.getAverage()
|
||||||
|
- f.vertices[3].Color.getAverage()))
|
||||||
indices_p = indices_alternate;
|
indices_p = indices_alternate;
|
||||||
|
|
||||||
collector.append(f.tile, f.vertices, 4, indices_p, 6);
|
collector.append(f.tile, f.vertices, 4, indices_p, 6);
|
||||||
@ -1148,43 +1153,30 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
|||||||
p.tile.texture = animation_frame.texture;
|
p.tile.texture = animation_frame.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 vertex_count = m_use_tangent_vertices ?
|
if (!m_enable_shaders) {
|
||||||
p.tangent_vertices.size() : p.vertices.size();
|
// Extract colors for day-night animation
|
||||||
for (u32 j = 0; j < vertex_count; j++) {
|
// Dummy sunlight to handle non-sunlit areas
|
||||||
v3f *Normal;
|
video::SColorf sunlight;
|
||||||
video::SColor *vc;
|
get_sunlight_color(&sunlight, 0);
|
||||||
if (m_use_tangent_vertices) {
|
u32 vertex_count =
|
||||||
vc = &p.tangent_vertices[j].Color;
|
m_use_tangent_vertices ?
|
||||||
Normal = &p.tangent_vertices[j].Normal;
|
p.tangent_vertices.size() : p.vertices.size();
|
||||||
} else {
|
for (u32 j = 0; j < vertex_count; j++) {
|
||||||
vc = &p.vertices[j].Color;
|
video::SColor *vc;
|
||||||
Normal = &p.vertices[j].Normal;
|
if (m_use_tangent_vertices) {
|
||||||
}
|
vc = &p.tangent_vertices[j].Color;
|
||||||
// Note applyFacesShading second parameter is precalculated sqrt
|
} else {
|
||||||
// value for speed improvement
|
vc = &p.vertices[j].Color;
|
||||||
// Skip it for lightsources and top faces.
|
|
||||||
if (!vc->getBlue()) {
|
|
||||||
if (Normal->Y < -0.5) {
|
|
||||||
applyFacesShading(*vc, 0.447213);
|
|
||||||
} else if (Normal->X > 0.5) {
|
|
||||||
applyFacesShading(*vc, 0.670820);
|
|
||||||
} else if (Normal->X < -0.5) {
|
|
||||||
applyFacesShading(*vc, 0.670820);
|
|
||||||
} else if (Normal->Z > 0.5) {
|
|
||||||
applyFacesShading(*vc, 0.836660);
|
|
||||||
} else if (Normal->Z < -0.5) {
|
|
||||||
applyFacesShading(*vc, 0.836660);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!m_enable_shaders) {
|
|
||||||
// - Classic lighting (shaders handle this by themselves)
|
|
||||||
// Set initial real color and store for later updates
|
|
||||||
u8 day = vc->getRed();
|
|
||||||
u8 night = vc->getGreen();
|
|
||||||
finalColorBlend(*vc, day, night, 1000);
|
|
||||||
if (day != night) {
|
|
||||||
m_daynight_diffs[i][j] = std::make_pair(day, night);
|
|
||||||
}
|
}
|
||||||
|
video::SColor copy(*vc);
|
||||||
|
if (vc->getAlpha() == 0) // No sunlight - no need to animate
|
||||||
|
final_color_blend(vc, copy, sunlight); // Finalize color
|
||||||
|
else // Record color to animate
|
||||||
|
m_daynight_diffs[i][j] = copy;
|
||||||
|
|
||||||
|
// The sunlight ratio has been stored,
|
||||||
|
// delete alpha (for the final rendering).
|
||||||
|
vc->setAlpha(255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,19 +1350,19 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
|
|||||||
if (m_enable_vbo) {
|
if (m_enable_vbo) {
|
||||||
m_mesh->setDirty();
|
m_mesh->setDirty();
|
||||||
}
|
}
|
||||||
for(std::map<u32, std::map<u32, std::pair<u8, u8> > >::iterator
|
video::SColorf day_color;
|
||||||
|
get_sunlight_color(&day_color, daynight_ratio);
|
||||||
|
for(std::map<u32, std::map<u32, video::SColor > >::iterator
|
||||||
i = m_daynight_diffs.begin();
|
i = m_daynight_diffs.begin();
|
||||||
i != m_daynight_diffs.end(); ++i)
|
i != m_daynight_diffs.end(); ++i)
|
||||||
{
|
{
|
||||||
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
|
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
|
||||||
video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
|
video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
|
||||||
for(std::map<u32, std::pair<u8, u8 > >::iterator
|
for(std::map<u32, video::SColor >::iterator
|
||||||
j = i->second.begin();
|
j = i->second.begin();
|
||||||
j != i->second.end(); ++j)
|
j != i->second.end(); ++j)
|
||||||
{
|
{
|
||||||
u8 day = j->second.first;
|
final_color_blend(&(vertices[j->first].Color), j->second, day_color);
|
||||||
u8 night = j->second.second;
|
|
||||||
finalColorBlend(vertices[j->first].Color, day, night, daynight_ratio);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_last_daynight_ratio = daynight_ratio;
|
m_last_daynight_ratio = daynight_ratio;
|
||||||
@ -1452,7 +1444,7 @@ void MeshCollector::append(const TileSpec &tile,
|
|||||||
void MeshCollector::append(const TileSpec &tile,
|
void MeshCollector::append(const TileSpec &tile,
|
||||||
const video::S3DVertex *vertices, u32 numVertices,
|
const video::S3DVertex *vertices, u32 numVertices,
|
||||||
const u16 *indices, u32 numIndices,
|
const u16 *indices, u32 numIndices,
|
||||||
v3f pos, video::SColor c)
|
v3f pos, video::SColor c, u8 light_source)
|
||||||
{
|
{
|
||||||
if (numIndices > 65535) {
|
if (numIndices > 65535) {
|
||||||
dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
|
dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
|
||||||
@ -1478,10 +1470,15 @@ void MeshCollector::append(const TileSpec &tile,
|
|||||||
p = &prebuffers[prebuffers.size() - 1];
|
p = &prebuffers[prebuffers.size() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
video::SColor original_c = c;
|
||||||
u32 vertex_count;
|
u32 vertex_count;
|
||||||
if (m_use_tangent_vertices) {
|
if (m_use_tangent_vertices) {
|
||||||
vertex_count = p->tangent_vertices.size();
|
vertex_count = p->tangent_vertices.size();
|
||||||
for (u32 i = 0; i < numVertices; i++) {
|
for (u32 i = 0; i < numVertices; i++) {
|
||||||
|
if (!light_source) {
|
||||||
|
c = original_c;
|
||||||
|
applyFacesShading(c, vertices[i].Normal);
|
||||||
|
}
|
||||||
video::S3DVertexTangents vert(vertices[i].Pos + pos,
|
video::S3DVertexTangents vert(vertices[i].Pos + pos,
|
||||||
vertices[i].Normal, c, vertices[i].TCoords);
|
vertices[i].Normal, c, vertices[i].TCoords);
|
||||||
p->tangent_vertices.push_back(vert);
|
p->tangent_vertices.push_back(vert);
|
||||||
@ -1489,8 +1486,12 @@ void MeshCollector::append(const TileSpec &tile,
|
|||||||
} else {
|
} else {
|
||||||
vertex_count = p->vertices.size();
|
vertex_count = p->vertices.size();
|
||||||
for (u32 i = 0; i < numVertices; i++) {
|
for (u32 i = 0; i < numVertices; i++) {
|
||||||
video::S3DVertex vert(vertices[i].Pos + pos,
|
if (!light_source) {
|
||||||
vertices[i].Normal, c, vertices[i].TCoords);
|
c = original_c;
|
||||||
|
applyFacesShading(c, vertices[i].Normal);
|
||||||
|
}
|
||||||
|
video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, c,
|
||||||
|
vertices[i].TCoords);
|
||||||
p->vertices.push_back(vert);
|
p->vertices.push_back(vert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1500,3 +1501,33 @@ void MeshCollector::append(const TileSpec &tile,
|
|||||||
p->indices.push_back(j);
|
p->indices.push_back(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
video::SColor encode_light_and_color(u16 light, const video::SColor &color,
|
||||||
|
u8 emissive_light)
|
||||||
|
{
|
||||||
|
// Get components
|
||||||
|
f32 day = (light & 0xff) / 255.0f;
|
||||||
|
f32 night = (light >> 8) / 255.0f;
|
||||||
|
// Add emissive light
|
||||||
|
night += emissive_light * 0.01f;
|
||||||
|
if (night > 255)
|
||||||
|
night = 255;
|
||||||
|
// Since we don't know if the day light is sunlight or
|
||||||
|
// artificial light, assume it is artificial when the night
|
||||||
|
// light bank is also lit.
|
||||||
|
if (day < night)
|
||||||
|
day = 0;
|
||||||
|
else
|
||||||
|
day = day - night;
|
||||||
|
f32 sum = day + night;
|
||||||
|
// Ratio of sunlight:
|
||||||
|
float r;
|
||||||
|
if (sum > 0)
|
||||||
|
r = day / sum;
|
||||||
|
else
|
||||||
|
r = 0;
|
||||||
|
// Average light:
|
||||||
|
float b = (day + night) / 2;
|
||||||
|
return video::SColor(r * 255, b * color.getRed(), b * color.getGreen(),
|
||||||
|
b * color.getBlue());
|
||||||
|
}
|
||||||
|
@ -156,8 +156,8 @@ private:
|
|||||||
// Animation info: day/night transitions
|
// Animation info: day/night transitions
|
||||||
// Last daynight_ratio value passed to animate()
|
// Last daynight_ratio value passed to animate()
|
||||||
u32 m_last_daynight_ratio;
|
u32 m_last_daynight_ratio;
|
||||||
// For each meshbuffer, maps vertex indices to (day,night) pairs
|
// For each meshbuffer, stores pre-baked colors of sunlit vertices
|
||||||
std::map<u32, std::map<u32, std::pair<u8, u8> > > m_daynight_diffs;
|
std::map<u32, std::map<u32, video::SColor > > m_daynight_diffs;
|
||||||
|
|
||||||
// Camera offset info -> do we have to translate the mesh?
|
// Camera offset info -> do we have to translate the mesh?
|
||||||
v3s16 m_camera_offset;
|
v3s16 m_camera_offset;
|
||||||
@ -192,28 +192,53 @@ struct MeshCollector
|
|||||||
void append(const TileSpec &material,
|
void append(const TileSpec &material,
|
||||||
const video::S3DVertex *vertices, u32 numVertices,
|
const video::S3DVertex *vertices, u32 numVertices,
|
||||||
const u16 *indices, u32 numIndices,
|
const u16 *indices, u32 numIndices,
|
||||||
v3f pos, video::SColor c);
|
v3f pos, video::SColor c, u8 light_source);
|
||||||
};
|
};
|
||||||
|
|
||||||
// This encodes
|
/*!
|
||||||
// alpha in the A channel of the returned SColor
|
* Encodes light and color of a node.
|
||||||
// day light (0-255) in the R channel of the returned SColor
|
* The result is not the final color, but a
|
||||||
// night light (0-255) in the G channel of the returned SColor
|
* half-baked vertex color.
|
||||||
// light source (0-255) in the B channel of the returned SColor
|
*
|
||||||
inline video::SColor MapBlock_LightColor(u8 alpha, u16 light, u8 light_source=0)
|
* \param light the first 8 bits are day light,
|
||||||
{
|
* the last 8 bits are night light
|
||||||
return video::SColor(alpha, (light & 0xff), (light >> 8), light_source);
|
* \param color the node's color
|
||||||
}
|
* \param emissive_light amount of light the surface emits,
|
||||||
|
* from 0 to LIGHT_SUN.
|
||||||
|
*/
|
||||||
|
video::SColor encode_light_and_color(u16 light, const video::SColor &color,
|
||||||
|
u8 emissive_light);
|
||||||
|
|
||||||
// Compute light at node
|
// Compute light at node
|
||||||
u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef);
|
u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef);
|
||||||
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef);
|
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef);
|
||||||
u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data);
|
u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data);
|
||||||
|
|
||||||
// Converts from day + night color values (0..255)
|
/*!
|
||||||
// and a given daynight_ratio to the final SColor shown on screen.
|
* Returns the sunlight's color from the current
|
||||||
void finalColorBlend(video::SColor& result,
|
* day-night ratio.
|
||||||
u8 day, u8 night, u32 daynight_ratio);
|
*/
|
||||||
|
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Gives the final SColor shown on screen.
|
||||||
|
*
|
||||||
|
* \param result output color
|
||||||
|
* \param light first 8 bits are day light, second 8 bits are
|
||||||
|
* night light
|
||||||
|
*/
|
||||||
|
void final_color_blend(video::SColor *result,
|
||||||
|
u16 light, u32 daynight_ratio);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Gives the final SColor shown on screen.
|
||||||
|
*
|
||||||
|
* \param result output color
|
||||||
|
* \param data the half-baked vertex color
|
||||||
|
* \param dayLight color of the sunlight
|
||||||
|
*/
|
||||||
|
void final_color_blend(video::SColor *result,
|
||||||
|
const video::SColor &data, const video::SColorf &dayLight);
|
||||||
|
|
||||||
// Retrieves the TileSpec of a face of a node
|
// Retrieves the TileSpec of a face of a node
|
||||||
// Adds MATERIAL_FLAG_CRACK if the node is cracked
|
// Adds MATERIAL_FLAG_CRACK if the node is cracked
|
||||||
|
@ -55,6 +55,15 @@ MapNode::MapNode(INodeDefManager *ndef, const std::string &name,
|
|||||||
param2 = a_param2;
|
param2 = a_param2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapNode::getColor(const ContentFeatures &f, video::SColor *color) const
|
||||||
|
{
|
||||||
|
if (f.palette) {
|
||||||
|
*color = (*f.palette)[param2];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*color = f.color;
|
||||||
|
}
|
||||||
|
|
||||||
void MapNode::setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f)
|
void MapNode::setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f)
|
||||||
{
|
{
|
||||||
// If node doesn't contain light data, ignore this
|
// If node doesn't contain light data, ignore this
|
||||||
@ -146,7 +155,8 @@ bool MapNode::getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodem
|
|||||||
u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
|
u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
|
||||||
{
|
{
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
if(f.param_type_2 == CPT2_FACEDIR)
|
if (f.param_type_2 == CPT2_FACEDIR ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_FACEDIR)
|
||||||
return (getParam2() & 0x1F) % 24;
|
return (getParam2() & 0x1F) % 24;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -154,7 +164,8 @@ u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
|
|||||||
u8 MapNode::getWallMounted(INodeDefManager *nodemgr) const
|
u8 MapNode::getWallMounted(INodeDefManager *nodemgr) const
|
||||||
{
|
{
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
if(f.param_type_2 == CPT2_WALLMOUNTED)
|
if (f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
||||||
return getParam2() & 0x07;
|
return getParam2() & 0x07;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -176,7 +187,7 @@ void MapNode::rotateAlongYAxis(INodeDefManager *nodemgr, Rotation rot)
|
|||||||
{
|
{
|
||||||
ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2;
|
ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2;
|
||||||
|
|
||||||
if (cpt2 == CPT2_FACEDIR) {
|
if (cpt2 == CPT2_FACEDIR || cpt2 == CPT2_COLORED_FACEDIR) {
|
||||||
static const u8 rotate_facedir[24 * 4] = {
|
static const u8 rotate_facedir[24 * 4] = {
|
||||||
// Table value = rotated facedir
|
// Table value = rotated facedir
|
||||||
// Columns: 0, 90, 180, 270 degrees rotation around vertical axis
|
// Columns: 0, 90, 180, 270 degrees rotation around vertical axis
|
||||||
@ -216,7 +227,8 @@ void MapNode::rotateAlongYAxis(INodeDefManager *nodemgr, Rotation rot)
|
|||||||
u8 index = facedir * 4 + rot;
|
u8 index = facedir * 4 + rot;
|
||||||
param2 &= ~31;
|
param2 &= ~31;
|
||||||
param2 |= rotate_facedir[index];
|
param2 |= rotate_facedir[index];
|
||||||
} else if (cpt2 == CPT2_WALLMOUNTED) {
|
} else if (cpt2 == CPT2_WALLMOUNTED ||
|
||||||
|
cpt2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
u8 wmountface = (param2 & 7);
|
u8 wmountface = (param2 & 7);
|
||||||
if (wmountface <= 1)
|
if (wmountface <= 1)
|
||||||
return;
|
return;
|
||||||
|
@ -20,9 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#ifndef MAPNODE_HEADER
|
#ifndef MAPNODE_HEADER
|
||||||
#define MAPNODE_HEADER
|
#define MAPNODE_HEADER
|
||||||
|
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes_bloated.h"
|
||||||
#include "irr_v3d.h"
|
|
||||||
#include "irr_aabb3d.h"
|
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -187,6 +185,14 @@ struct MapNode
|
|||||||
param2 = p;
|
param2 = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the color of the node.
|
||||||
|
*
|
||||||
|
* \param f content features of this node
|
||||||
|
* \param color output, contains the node's color.
|
||||||
|
*/
|
||||||
|
void getColor(const ContentFeatures &f, video::SColor *color) const;
|
||||||
|
|
||||||
void setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f);
|
void setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f);
|
||||||
|
|
||||||
void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr);
|
void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr);
|
||||||
|
47
src/mesh.cpp
47
src/mesh.cpp
@ -33,13 +33,25 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
|
#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void applyFacesShading(video::SColor& color, float factor)
|
inline static void applyShadeFactor(video::SColor& color, float factor)
|
||||||
{
|
{
|
||||||
color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
|
color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
|
||||||
color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
|
color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
|
||||||
color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
|
color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void applyFacesShading(video::SColor &color, const v3f &normal)
|
||||||
|
{
|
||||||
|
// Many special drawtypes have normals set to 0,0,0 and this
|
||||||
|
// must result in maximum brightness (no face shadng).
|
||||||
|
if (normal.Y < -0.5f)
|
||||||
|
applyShadeFactor (color, 0.447213f);
|
||||||
|
else if (normal.X > 0.5f || normal.X < -0.5f)
|
||||||
|
applyShadeFactor (color, 0.670820f);
|
||||||
|
else if (normal.Z > 0.5f || normal.Z < -0.5f)
|
||||||
|
applyShadeFactor (color, 0.836660f);
|
||||||
|
}
|
||||||
|
|
||||||
scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||||
{
|
{
|
||||||
video::SColor c(255,255,255,255);
|
video::SColor c(255,255,255,255);
|
||||||
@ -172,29 +184,18 @@ void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shadeMeshFaces(scene::IMesh *mesh)
|
void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor)
|
||||||
{
|
{
|
||||||
if (mesh == NULL)
|
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||||
return;
|
u32 vertex_count = buf->getVertexCount();
|
||||||
|
u8 *vertices = (u8 *) buf->getVertices();
|
||||||
u32 mc = mesh->getMeshBufferCount();
|
for (u32 i = 0; i < vertex_count; i++) {
|
||||||
for (u32 j = 0; j < mc; j++) {
|
video::S3DVertex *vertex = (video::S3DVertex *) (vertices + i * stride);
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
video::SColor *vc = &(vertex->Color);
|
||||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
// Reset color
|
||||||
u32 vertex_count = buf->getVertexCount();
|
*vc = *buffercolor;
|
||||||
u8 *vertices = (u8 *)buf->getVertices();
|
// Apply shading
|
||||||
for (u32 i = 0; i < vertex_count; i++) {
|
applyFacesShading(*vc, vertex->Normal);
|
||||||
video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
|
|
||||||
video::SColor &vc = vertex->Color;
|
|
||||||
// Many special drawtypes have normals set to 0,0,0 and this
|
|
||||||
// must result in maximum brightness (no face shadng).
|
|
||||||
if (vertex->Normal.Y < -0.5f)
|
|
||||||
applyFacesShading (vc, 0.447213f);
|
|
||||||
else if (vertex->Normal.X > 0.5f || vertex->Normal.X < -0.5f)
|
|
||||||
applyFacesShading (vc, 0.670820f);
|
|
||||||
else if (vertex->Normal.Z > 0.5f || vertex->Normal.Z < -0.5f)
|
|
||||||
applyFacesShading (vc, 0.836660f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/mesh.h
14
src/mesh.h
@ -23,6 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "nodedef.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.
|
Create a new cube mesh.
|
||||||
Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).
|
Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).
|
||||||
@ -48,11 +54,7 @@ void translateMesh(scene::IMesh *mesh, v3f vec);
|
|||||||
*/
|
*/
|
||||||
void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
|
void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
|
||||||
|
|
||||||
/*
|
void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor);
|
||||||
Shade mesh faces according to their normals
|
|
||||||
*/
|
|
||||||
|
|
||||||
void shadeMeshFaces(scene::IMesh *mesh);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set the color of all vertices in the mesh.
|
Set the color of all vertices in the mesh.
|
||||||
@ -87,7 +89,7 @@ void rotateMeshYZby (scene::IMesh *mesh, f64 degrees);
|
|||||||
scene::IMesh* cloneMesh(scene::IMesh *src_mesh);
|
scene::IMesh* cloneMesh(scene::IMesh *src_mesh);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert nodeboxes to mesh.
|
Convert nodeboxes to mesh. Each tile goes into a different buffer.
|
||||||
boxes - set of nodeboxes to be converted into cuboids
|
boxes - set of nodeboxes to be converted into cuboids
|
||||||
uv_coords[24] - table of texture uv coords for each cuboid face
|
uv_coords[24] - table of texture uv coords for each cuboid face
|
||||||
expand - factor by which cuboids will be resized
|
expand - factor by which cuboids will be resized
|
||||||
|
@ -144,7 +144,7 @@ MinimapPixel *MinimapUpdateThread::getMinimapPixel(v3s16 pos,
|
|||||||
if (it != m_blocks_cache.end()) {
|
if (it != m_blocks_cache.end()) {
|
||||||
MinimapMapblock *mmblock = it->second;
|
MinimapMapblock *mmblock = it->second;
|
||||||
MinimapPixel *pixel = &mmblock->data[relpos.Z * MAP_BLOCKSIZE + relpos.X];
|
MinimapPixel *pixel = &mmblock->data[relpos.Z * MAP_BLOCKSIZE + relpos.X];
|
||||||
if (pixel->id != CONTENT_AIR) {
|
if (pixel->n.param0 != CONTENT_AIR) {
|
||||||
*pixel_height = height + pixel->height;
|
*pixel_height = height + pixel->height;
|
||||||
return pixel;
|
return pixel;
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ void MinimapUpdateThread::getMap(v3s16 pos, s16 size, s16 height, bool is_radar)
|
|||||||
|
|
||||||
for (s16 x = 0; x < size; x++)
|
for (s16 x = 0; x < size; x++)
|
||||||
for (s16 z = 0; z < size; z++) {
|
for (s16 z = 0; z < size; z++) {
|
||||||
u16 id = CONTENT_AIR;
|
MapNode n(CONTENT_AIR);
|
||||||
MinimapPixel *mmpixel = &data->minimap_scan[x + z * size];
|
MinimapPixel *mmpixel = &data->minimap_scan[x + z * size];
|
||||||
|
|
||||||
if (!is_radar) {
|
if (!is_radar) {
|
||||||
@ -195,14 +195,14 @@ void MinimapUpdateThread::getMap(v3s16 pos, s16 size, s16 height, bool is_radar)
|
|||||||
MinimapPixel *cached_pixel =
|
MinimapPixel *cached_pixel =
|
||||||
getMinimapPixel(v3s16(p.X + x, p.Y, p.Z + z), height, &pixel_height);
|
getMinimapPixel(v3s16(p.X + x, p.Y, p.Z + z), height, &pixel_height);
|
||||||
if (cached_pixel) {
|
if (cached_pixel) {
|
||||||
id = cached_pixel->id;
|
n = cached_pixel->n;
|
||||||
mmpixel->height = pixel_height;
|
mmpixel->height = pixel_height;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mmpixel->air_count = getAirCount(v3s16(p.X + x, p.Y, p.Z + z), height);
|
mmpixel->air_count = getAirCount(v3s16(p.X + x, p.Y, p.Z + z), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
mmpixel->id = id;
|
mmpixel->n = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,10 +372,21 @@ void Mapper::blitMinimapPixelsToImageSurface(
|
|||||||
for (s16 z = 0; z < data->map_size; z++) {
|
for (s16 z = 0; z < data->map_size; z++) {
|
||||||
MinimapPixel *mmpixel = &data->minimap_scan[x + z * data->map_size];
|
MinimapPixel *mmpixel = &data->minimap_scan[x + z * data->map_size];
|
||||||
|
|
||||||
video::SColor c = m_ndef->get(mmpixel->id).minimap_color;
|
const ContentFeatures &f = m_ndef->get(mmpixel->n);
|
||||||
c.setAlpha(240);
|
const TileDef *tile = &f.tiledef[0];
|
||||||
|
// Color of the 0th tile (mostly this is the topmost)
|
||||||
|
video::SColor tilecolor;
|
||||||
|
if(tile->has_color)
|
||||||
|
tilecolor = tile->color;
|
||||||
|
else
|
||||||
|
mmpixel->n.getColor(f, &tilecolor);
|
||||||
|
tilecolor.setRed(tilecolor.getRed() * f.minimap_color.getRed() / 255);
|
||||||
|
tilecolor.setGreen(tilecolor.getGreen() * f.minimap_color.getGreen()
|
||||||
|
/ 255);
|
||||||
|
tilecolor.setBlue(tilecolor.getBlue() * f.minimap_color.getBlue() / 255);
|
||||||
|
tilecolor.setAlpha(240);
|
||||||
|
|
||||||
map_image->setPixel(x, data->map_size - z - 1, c);
|
map_image->setPixel(x, data->map_size - z - 1, tilecolor);
|
||||||
|
|
||||||
u32 h = mmpixel->height;
|
u32 h = mmpixel->height;
|
||||||
heightmap_image->setPixel(x,data->map_size - z - 1,
|
heightmap_image->setPixel(x,data->map_size - z - 1,
|
||||||
@ -617,7 +628,7 @@ void MinimapMapblock::getMinimapNodes(VoxelManipulator *vmanip, v3s16 pos)
|
|||||||
MapNode n = vmanip->getNodeNoEx(pos + p);
|
MapNode n = vmanip->getNodeNoEx(pos + p);
|
||||||
if (!surface_found && n.getContent() != CONTENT_AIR) {
|
if (!surface_found && n.getContent() != CONTENT_AIR) {
|
||||||
mmpixel->height = y;
|
mmpixel->height = y;
|
||||||
mmpixel->id = n.getContent();
|
mmpixel->n = n;
|
||||||
surface_found = true;
|
surface_found = true;
|
||||||
} else if (n.getContent() == CONTENT_AIR) {
|
} else if (n.getContent() == CONTENT_AIR) {
|
||||||
air_count++;
|
air_count++;
|
||||||
@ -625,7 +636,7 @@ void MinimapMapblock::getMinimapNodes(VoxelManipulator *vmanip, v3s16 pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!surface_found)
|
if (!surface_found)
|
||||||
mmpixel->id = CONTENT_AIR;
|
mmpixel->n = MapNode(CONTENT_AIR);
|
||||||
|
|
||||||
mmpixel->air_count = air_count;
|
mmpixel->air_count = air_count;
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,10 @@ struct MinimapModeDef {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MinimapPixel {
|
struct MinimapPixel {
|
||||||
u16 id;
|
//! The topmost node that the minimap displays.
|
||||||
|
MapNode n;
|
||||||
u16 height;
|
u16 height;
|
||||||
u16 air_count;
|
u16 air_count;
|
||||||
u16 light;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MinimapMapblock {
|
struct MinimapMapblock {
|
||||||
|
@ -143,9 +143,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
serialization of TileAnimation params changed
|
serialization of TileAnimation params changed
|
||||||
TAT_SHEET_2D
|
TAT_SHEET_2D
|
||||||
Removed client-sided chat perdiction
|
Removed client-sided chat perdiction
|
||||||
|
PROTOCOL VERSION 30:
|
||||||
|
New ContentFeatures serialization version
|
||||||
|
Add node and tile color and palette
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LATEST_PROTOCOL_VERSION 29
|
#define LATEST_PROTOCOL_VERSION 30
|
||||||
|
|
||||||
// Server's supported network protocol range
|
// Server's supported network protocol range
|
||||||
#define SERVER_PROTOCOL_VERSION_MIN 13
|
#define SERVER_PROTOCOL_VERSION_MIN 13
|
||||||
|
513
src/nodedef.cpp
513
src/nodedef.cpp
@ -189,7 +189,9 @@ void NodeBox::deSerialize(std::istream &is)
|
|||||||
|
|
||||||
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
||||||
{
|
{
|
||||||
if (protocol_version >= 29)
|
if (protocol_version >= 30)
|
||||||
|
writeU8(os, 4);
|
||||||
|
else if (protocol_version >= 29)
|
||||||
writeU8(os, 3);
|
writeU8(os, 3);
|
||||||
else if (protocol_version >= 26)
|
else if (protocol_version >= 26)
|
||||||
writeU8(os, 2);
|
writeU8(os, 2);
|
||||||
@ -205,6 +207,14 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
|||||||
writeU8(os, tileable_horizontal);
|
writeU8(os, tileable_horizontal);
|
||||||
writeU8(os, tileable_vertical);
|
writeU8(os, tileable_vertical);
|
||||||
}
|
}
|
||||||
|
if (protocol_version >= 30) {
|
||||||
|
writeU8(os, has_color);
|
||||||
|
if (has_color) {
|
||||||
|
writeU8(os, color.getRed());
|
||||||
|
writeU8(os, color.getGreen());
|
||||||
|
writeU8(os, color.getBlue());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileDef::deSerialize(std::istream &is, const u8 contenfeatures_version, const NodeDrawType drawtype)
|
void TileDef::deSerialize(std::istream &is, const u8 contenfeatures_version, const NodeDrawType drawtype)
|
||||||
@ -218,6 +228,14 @@ void TileDef::deSerialize(std::istream &is, const u8 contenfeatures_version, con
|
|||||||
tileable_horizontal = readU8(is);
|
tileable_horizontal = readU8(is);
|
||||||
tileable_vertical = readU8(is);
|
tileable_vertical = readU8(is);
|
||||||
}
|
}
|
||||||
|
if (version >= 4) {
|
||||||
|
has_color = readU8(is);
|
||||||
|
if (has_color) {
|
||||||
|
color.setRed(readU8(is));
|
||||||
|
color.setGreen(readU8(is));
|
||||||
|
color.setBlue(readU8(is));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((contenfeatures_version < 8) &&
|
if ((contenfeatures_version < 8) &&
|
||||||
((drawtype == NDT_MESH) ||
|
((drawtype == NDT_MESH) ||
|
||||||
@ -351,172 +369,222 @@ void ContentFeatures::reset()
|
|||||||
connects_to.clear();
|
connects_to.clear();
|
||||||
connects_to_ids.clear();
|
connects_to_ids.clear();
|
||||||
connect_sides = 0;
|
connect_sides = 0;
|
||||||
|
color = video::SColor(0xFFFFFFFF);
|
||||||
|
palette_name = "";
|
||||||
|
palette = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
||||||
{
|
{
|
||||||
if(protocol_version < 24){
|
if (protocol_version < 30) {
|
||||||
serializeOld(os, protocol_version);
|
serializeOld(os, protocol_version);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeU8(os, protocol_version < 27 ? 7 : 8);
|
// version
|
||||||
|
writeU8(os, 9);
|
||||||
|
|
||||||
os<<serializeString(name);
|
// general
|
||||||
|
os << serializeString(name);
|
||||||
writeU16(os, groups.size());
|
writeU16(os, groups.size());
|
||||||
for(ItemGroupList::const_iterator
|
for (ItemGroupList::const_iterator i = groups.begin(); i != groups.end();
|
||||||
i = groups.begin(); i != groups.end(); ++i){
|
++i) {
|
||||||
os<<serializeString(i->first);
|
os << serializeString(i->first);
|
||||||
writeS16(os, i->second);
|
writeS16(os, i->second);
|
||||||
}
|
}
|
||||||
|
writeU8(os, param_type);
|
||||||
|
writeU8(os, param_type_2);
|
||||||
|
|
||||||
|
// visual
|
||||||
writeU8(os, drawtype);
|
writeU8(os, drawtype);
|
||||||
|
os << serializeString(mesh);
|
||||||
writeF1000(os, visual_scale);
|
writeF1000(os, visual_scale);
|
||||||
writeU8(os, 6);
|
writeU8(os, 6);
|
||||||
for(u32 i = 0; i < 6; i++)
|
for (u32 i = 0; i < 6; i++)
|
||||||
tiledef[i].serialize(os, protocol_version);
|
tiledef[i].serialize(os, protocol_version);
|
||||||
writeU8(os, CF_SPECIAL_COUNT);
|
writeU8(os, CF_SPECIAL_COUNT);
|
||||||
for(u32 i = 0; i < CF_SPECIAL_COUNT; i++){
|
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++) {
|
||||||
tiledef_special[i].serialize(os, protocol_version);
|
tiledef_special[i].serialize(os, protocol_version);
|
||||||
}
|
}
|
||||||
writeU8(os, alpha);
|
writeU8(os, alpha);
|
||||||
|
writeU8(os, color.getRed());
|
||||||
|
writeU8(os, color.getGreen());
|
||||||
|
writeU8(os, color.getBlue());
|
||||||
|
os << serializeString(palette_name);
|
||||||
|
writeU8(os, waving);
|
||||||
|
writeU8(os, connect_sides);
|
||||||
|
writeU16(os, connects_to_ids.size());
|
||||||
|
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
|
||||||
|
i != connects_to_ids.end(); ++i)
|
||||||
|
writeU16(os, *i);
|
||||||
writeU8(os, post_effect_color.getAlpha());
|
writeU8(os, post_effect_color.getAlpha());
|
||||||
writeU8(os, post_effect_color.getRed());
|
writeU8(os, post_effect_color.getRed());
|
||||||
writeU8(os, post_effect_color.getGreen());
|
writeU8(os, post_effect_color.getGreen());
|
||||||
writeU8(os, post_effect_color.getBlue());
|
writeU8(os, post_effect_color.getBlue());
|
||||||
writeU8(os, param_type);
|
writeU8(os, leveled);
|
||||||
if ((protocol_version < 28) && (param_type_2 == CPT2_MESHOPTIONS))
|
|
||||||
writeU8(os, CPT2_NONE);
|
// lighting
|
||||||
else
|
|
||||||
writeU8(os, param_type_2);
|
|
||||||
writeU8(os, is_ground_content);
|
|
||||||
writeU8(os, light_propagates);
|
writeU8(os, light_propagates);
|
||||||
writeU8(os, sunlight_propagates);
|
writeU8(os, sunlight_propagates);
|
||||||
|
writeU8(os, light_source);
|
||||||
|
|
||||||
|
// map generation
|
||||||
|
writeU8(os, is_ground_content);
|
||||||
|
|
||||||
|
// interaction
|
||||||
writeU8(os, walkable);
|
writeU8(os, walkable);
|
||||||
writeU8(os, pointable);
|
writeU8(os, pointable);
|
||||||
writeU8(os, diggable);
|
writeU8(os, diggable);
|
||||||
writeU8(os, climbable);
|
writeU8(os, climbable);
|
||||||
writeU8(os, buildable_to);
|
writeU8(os, buildable_to);
|
||||||
os<<serializeString(""); // legacy: used to be metadata_name
|
writeU8(os, rightclickable);
|
||||||
|
writeU32(os, damage_per_second);
|
||||||
|
|
||||||
|
// liquid
|
||||||
writeU8(os, liquid_type);
|
writeU8(os, liquid_type);
|
||||||
os<<serializeString(liquid_alternative_flowing);
|
os << serializeString(liquid_alternative_flowing);
|
||||||
os<<serializeString(liquid_alternative_source);
|
os << serializeString(liquid_alternative_source);
|
||||||
writeU8(os, liquid_viscosity);
|
writeU8(os, liquid_viscosity);
|
||||||
writeU8(os, liquid_renewable);
|
writeU8(os, liquid_renewable);
|
||||||
writeU8(os, light_source);
|
writeU8(os, liquid_range);
|
||||||
writeU32(os, damage_per_second);
|
writeU8(os, drowning);
|
||||||
|
writeU8(os, floodable);
|
||||||
|
|
||||||
|
// node boxes
|
||||||
node_box.serialize(os, protocol_version);
|
node_box.serialize(os, protocol_version);
|
||||||
selection_box.serialize(os, protocol_version);
|
selection_box.serialize(os, protocol_version);
|
||||||
writeU8(os, legacy_facedir_simple);
|
collision_box.serialize(os, protocol_version);
|
||||||
writeU8(os, legacy_wallmounted);
|
|
||||||
|
// sound
|
||||||
serializeSimpleSoundSpec(sound_footstep, os);
|
serializeSimpleSoundSpec(sound_footstep, os);
|
||||||
serializeSimpleSoundSpec(sound_dig, os);
|
serializeSimpleSoundSpec(sound_dig, os);
|
||||||
serializeSimpleSoundSpec(sound_dug, os);
|
serializeSimpleSoundSpec(sound_dug, os);
|
||||||
writeU8(os, rightclickable);
|
|
||||||
writeU8(os, drowning);
|
// legacy
|
||||||
writeU8(os, leveled);
|
writeU8(os, legacy_facedir_simple);
|
||||||
writeU8(os, liquid_range);
|
writeU8(os, legacy_wallmounted);
|
||||||
writeU8(os, waving);
|
}
|
||||||
// Stuff below should be moved to correct place in a version that otherwise changes
|
|
||||||
// the protocol version
|
void ContentFeatures::correctAlpha()
|
||||||
os<<serializeString(mesh);
|
{
|
||||||
collision_box.serialize(os, protocol_version);
|
if (alpha == 0 || alpha == 255)
|
||||||
writeU8(os, floodable);
|
return;
|
||||||
writeU16(os, connects_to_ids.size());
|
|
||||||
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
|
for (u32 i = 0; i < 6; i++) {
|
||||||
i != connects_to_ids.end(); ++i)
|
std::stringstream s;
|
||||||
writeU16(os, *i);
|
s << tiledef[i].name << "^[noalpha^[opacity:" << ((int)alpha);
|
||||||
writeU8(os, connect_sides);
|
tiledef[i].name = s.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++) {
|
||||||
|
std::stringstream s;
|
||||||
|
s << tiledef_special[i].name << "^[noalpha^[opacity:" << ((int)alpha);
|
||||||
|
tiledef_special[i].name = s.str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentFeatures::deSerialize(std::istream &is)
|
void ContentFeatures::deSerialize(std::istream &is)
|
||||||
{
|
{
|
||||||
|
// version detection
|
||||||
int version = readU8(is);
|
int version = readU8(is);
|
||||||
if (version < 7) {
|
if (version < 9) {
|
||||||
deSerializeOld(is, version);
|
deSerializeOld(is, version);
|
||||||
return;
|
return;
|
||||||
} else if (version > 8) {
|
} else if (version > 9) {
|
||||||
throw SerializationError("unsupported ContentFeatures version");
|
throw SerializationError("unsupported ContentFeatures version");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// general
|
||||||
name = deSerializeString(is);
|
name = deSerializeString(is);
|
||||||
groups.clear();
|
groups.clear();
|
||||||
u32 groups_size = readU16(is);
|
u32 groups_size = readU16(is);
|
||||||
for(u32 i = 0; i < groups_size; i++){
|
for (u32 i = 0; i < groups_size; i++) {
|
||||||
std::string name = deSerializeString(is);
|
std::string name = deSerializeString(is);
|
||||||
int value = readS16(is);
|
int value = readS16(is);
|
||||||
groups[name] = value;
|
groups[name] = value;
|
||||||
}
|
}
|
||||||
drawtype = (enum NodeDrawType)readU8(is);
|
param_type = (enum ContentParamType) readU8(is);
|
||||||
|
param_type_2 = (enum ContentParamType2) readU8(is);
|
||||||
|
|
||||||
|
// visual
|
||||||
|
drawtype = (enum NodeDrawType) readU8(is);
|
||||||
|
mesh = deSerializeString(is);
|
||||||
visual_scale = readF1000(is);
|
visual_scale = readF1000(is);
|
||||||
if(readU8(is) != 6)
|
if (readU8(is) != 6)
|
||||||
throw SerializationError("unsupported tile count");
|
throw SerializationError("unsupported tile count");
|
||||||
for(u32 i = 0; i < 6; i++)
|
for (u32 i = 0; i < 6; i++)
|
||||||
tiledef[i].deSerialize(is, version, drawtype);
|
tiledef[i].deSerialize(is, version, drawtype);
|
||||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
if (readU8(is) != CF_SPECIAL_COUNT)
|
||||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||||
for(u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||||
tiledef_special[i].deSerialize(is, version, drawtype);
|
tiledef_special[i].deSerialize(is, version, drawtype);
|
||||||
alpha = readU8(is);
|
alpha = readU8(is);
|
||||||
|
color.setRed(readU8(is));
|
||||||
|
color.setGreen(readU8(is));
|
||||||
|
color.setBlue(readU8(is));
|
||||||
|
palette_name = deSerializeString(is);
|
||||||
|
waving = readU8(is);
|
||||||
|
connect_sides = readU8(is);
|
||||||
|
u16 connects_to_size = readU16(is);
|
||||||
|
connects_to_ids.clear();
|
||||||
|
for (u16 i = 0; i < connects_to_size; i++)
|
||||||
|
connects_to_ids.insert(readU16(is));
|
||||||
post_effect_color.setAlpha(readU8(is));
|
post_effect_color.setAlpha(readU8(is));
|
||||||
post_effect_color.setRed(readU8(is));
|
post_effect_color.setRed(readU8(is));
|
||||||
post_effect_color.setGreen(readU8(is));
|
post_effect_color.setGreen(readU8(is));
|
||||||
post_effect_color.setBlue(readU8(is));
|
post_effect_color.setBlue(readU8(is));
|
||||||
param_type = (enum ContentParamType)readU8(is);
|
leveled = readU8(is);
|
||||||
param_type_2 = (enum ContentParamType2)readU8(is);
|
|
||||||
is_ground_content = readU8(is);
|
// lighting-related
|
||||||
light_propagates = readU8(is);
|
light_propagates = readU8(is);
|
||||||
sunlight_propagates = readU8(is);
|
sunlight_propagates = readU8(is);
|
||||||
|
light_source = readU8(is);
|
||||||
|
light_source = MYMIN(light_source, LIGHT_MAX);
|
||||||
|
|
||||||
|
// map generation
|
||||||
|
is_ground_content = readU8(is);
|
||||||
|
|
||||||
|
// interaction
|
||||||
walkable = readU8(is);
|
walkable = readU8(is);
|
||||||
pointable = readU8(is);
|
pointable = readU8(is);
|
||||||
diggable = readU8(is);
|
diggable = readU8(is);
|
||||||
climbable = readU8(is);
|
climbable = readU8(is);
|
||||||
buildable_to = readU8(is);
|
buildable_to = readU8(is);
|
||||||
deSerializeString(is); // legacy: used to be metadata_name
|
rightclickable = readU8(is);
|
||||||
liquid_type = (enum LiquidType)readU8(is);
|
damage_per_second = readU32(is);
|
||||||
|
|
||||||
|
// liquid
|
||||||
|
liquid_type = (enum LiquidType) readU8(is);
|
||||||
liquid_alternative_flowing = deSerializeString(is);
|
liquid_alternative_flowing = deSerializeString(is);
|
||||||
liquid_alternative_source = deSerializeString(is);
|
liquid_alternative_source = deSerializeString(is);
|
||||||
liquid_viscosity = readU8(is);
|
liquid_viscosity = readU8(is);
|
||||||
liquid_renewable = readU8(is);
|
liquid_renewable = readU8(is);
|
||||||
light_source = readU8(is);
|
liquid_range = readU8(is);
|
||||||
light_source = MYMIN(light_source, LIGHT_MAX);
|
drowning = readU8(is);
|
||||||
damage_per_second = readU32(is);
|
floodable = readU8(is);
|
||||||
|
|
||||||
|
// node boxes
|
||||||
node_box.deSerialize(is);
|
node_box.deSerialize(is);
|
||||||
selection_box.deSerialize(is);
|
selection_box.deSerialize(is);
|
||||||
legacy_facedir_simple = readU8(is);
|
collision_box.deSerialize(is);
|
||||||
legacy_wallmounted = readU8(is);
|
|
||||||
|
// sounds
|
||||||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||||
rightclickable = readU8(is);
|
|
||||||
drowning = readU8(is);
|
// read legacy properties
|
||||||
leveled = readU8(is);
|
legacy_facedir_simple = readU8(is);
|
||||||
liquid_range = readU8(is);
|
legacy_wallmounted = readU8(is);
|
||||||
waving = readU8(is);
|
|
||||||
// If you add anything here, insert it primarily inside the try-catch
|
|
||||||
// block to not need to increase the version.
|
|
||||||
try{
|
|
||||||
// Stuff below should be moved to correct place in a version that
|
|
||||||
// otherwise changes the protocol version
|
|
||||||
mesh = deSerializeString(is);
|
|
||||||
collision_box.deSerialize(is);
|
|
||||||
floodable = readU8(is);
|
|
||||||
u16 connects_to_size = readU16(is);
|
|
||||||
connects_to_ids.clear();
|
|
||||||
for (u16 i = 0; i < connects_to_size; i++)
|
|
||||||
connects_to_ids.insert(readU16(is));
|
|
||||||
connect_sides = readU8(is);
|
|
||||||
}catch(SerializationError &e) {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
|
void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
|
||||||
TileDef *tiledef, u32 shader_id, bool use_normal_texture,
|
TileDef *tiledef, u32 shader_id, bool use_normal_texture,
|
||||||
bool backface_culling, u8 alpha, u8 material_type)
|
bool backface_culling, u8 material_type)
|
||||||
{
|
{
|
||||||
tile->shader_id = shader_id;
|
tile->shader_id = shader_id;
|
||||||
tile->texture = tsrc->getTextureForMesh(tiledef->name, &tile->texture_id);
|
tile->texture = tsrc->getTextureForMesh(tiledef->name, &tile->texture_id);
|
||||||
tile->alpha = alpha;
|
|
||||||
tile->material_type = material_type;
|
tile->material_type = material_type;
|
||||||
|
|
||||||
// Normal texture and shader flags texture
|
// Normal texture and shader flags texture
|
||||||
@ -536,6 +604,13 @@ void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
|
|||||||
if (tiledef->tileable_vertical)
|
if (tiledef->tileable_vertical)
|
||||||
tile->material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;
|
tile->material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;
|
||||||
|
|
||||||
|
// Color
|
||||||
|
tile->has_color = tiledef->has_color;
|
||||||
|
if (tiledef->has_color)
|
||||||
|
tile->color = tiledef->color;
|
||||||
|
else
|
||||||
|
tile->color = color;
|
||||||
|
|
||||||
// Animation parameters
|
// Animation parameters
|
||||||
int frame_count = 1;
|
int frame_count = 1;
|
||||||
if (tile->material_flags & MATERIAL_FLAG_ANIMATION) {
|
if (tile->material_flags & MATERIAL_FLAG_ANIMATION) {
|
||||||
@ -681,6 +756,9 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
is_water_surface = true;
|
is_water_surface = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vertex alpha is no longer supported, correct if necessary.
|
||||||
|
correctAlpha();
|
||||||
|
|
||||||
u32 tile_shader[6];
|
u32 tile_shader[6];
|
||||||
for (u16 j = 0; j < 6; j++) {
|
for (u16 j = 0; j < 6; j++) {
|
||||||
tile_shader[j] = shdsrc->getShader("nodes_shader",
|
tile_shader[j] = shdsrc->getShader("nodes_shader",
|
||||||
@ -696,14 +774,14 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
for (u16 j = 0; j < 6; j++) {
|
for (u16 j = 0; j < 6; j++) {
|
||||||
fillTileAttribs(tsrc, &tiles[j], &tdef[j], tile_shader[j],
|
fillTileAttribs(tsrc, &tiles[j], &tdef[j], tile_shader[j],
|
||||||
tsettings.use_normal_texture,
|
tsettings.use_normal_texture,
|
||||||
tiledef[j].backface_culling, alpha, material_type);
|
tiledef[j].backface_culling, material_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special tiles (fill in f->special_tiles[])
|
// Special tiles (fill in f->special_tiles[])
|
||||||
for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
|
for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
|
||||||
fillTileAttribs(tsrc, &special_tiles[j], &tiledef_special[j],
|
fillTileAttribs(tsrc, &special_tiles[j], &tiledef_special[j],
|
||||||
tile_shader[j], tsettings.use_normal_texture,
|
tile_shader[j], tsettings.use_normal_texture,
|
||||||
tiledef_special[j].backface_culling, alpha, material_type);
|
tiledef_special[j].backface_culling, material_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((drawtype == NDT_MESH) && (mesh != "")) {
|
if ((drawtype == NDT_MESH) && (mesh != "")) {
|
||||||
@ -731,15 +809,19 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Cache 6dfacedir and wallmounted rotated clones of meshes
|
//Cache 6dfacedir and wallmounted rotated clones of meshes
|
||||||
if (tsettings.enable_mesh_cache && mesh_ptr[0] && (param_type_2 == CPT2_FACEDIR)) {
|
if (tsettings.enable_mesh_cache && mesh_ptr[0] &&
|
||||||
|
(param_type_2 == CPT2_FACEDIR
|
||||||
|
|| param_type_2 == CPT2_COLORED_FACEDIR)) {
|
||||||
for (u16 j = 1; j < 24; j++) {
|
for (u16 j = 1; j < 24; j++) {
|
||||||
mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
|
mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
|
||||||
rotateMeshBy6dFacedir(mesh_ptr[j], j);
|
rotateMeshBy6dFacedir(mesh_ptr[j], j);
|
||||||
recalculateBoundingBox(mesh_ptr[j]);
|
recalculateBoundingBox(mesh_ptr[j]);
|
||||||
meshmanip->recalculateNormals(mesh_ptr[j], true, false);
|
meshmanip->recalculateNormals(mesh_ptr[j], true, false);
|
||||||
}
|
}
|
||||||
} else if (tsettings.enable_mesh_cache && mesh_ptr[0] && (param_type_2 == CPT2_WALLMOUNTED)) {
|
} else if (tsettings.enable_mesh_cache && mesh_ptr[0]
|
||||||
static const u8 wm_to_6d[6] = {20, 0, 16+1, 12+3, 8, 4+2};
|
&& (param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
|
param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
|
||||||
|
static const u8 wm_to_6d[6] = { 20, 0, 16 + 1, 12 + 3, 8, 4 + 2 };
|
||||||
for (u16 j = 1; j < 6; j++) {
|
for (u16 j = 1; j < 6; j++) {
|
||||||
mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
|
mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
|
||||||
rotateMeshBy6dFacedir(mesh_ptr[j], wm_to_6d[j]);
|
rotateMeshBy6dFacedir(mesh_ptr[j], wm_to_6d[j]);
|
||||||
@ -775,6 +857,9 @@ public:
|
|||||||
virtual void removeNode(const std::string &name);
|
virtual void removeNode(const std::string &name);
|
||||||
virtual void updateAliases(IItemDefManager *idef);
|
virtual void updateAliases(IItemDefManager *idef);
|
||||||
virtual void applyTextureOverrides(const std::string &override_filepath);
|
virtual void applyTextureOverrides(const std::string &override_filepath);
|
||||||
|
//! Returns a palette or NULL if not found. Only on client.
|
||||||
|
std::vector<video::SColor> *getPalette(const ContentFeatures &f,
|
||||||
|
const IGameDef *gamedef);
|
||||||
virtual void updateTextures(IGameDef *gamedef,
|
virtual void updateTextures(IGameDef *gamedef,
|
||||||
void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
|
void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
|
||||||
void *progress_cbk_args);
|
void *progress_cbk_args);
|
||||||
@ -823,6 +908,9 @@ private:
|
|||||||
// Next possibly free id
|
// Next possibly free id
|
||||||
content_t m_next_id;
|
content_t m_next_id;
|
||||||
|
|
||||||
|
// Maps image file names to loaded palettes.
|
||||||
|
UNORDERED_MAP<std::string, std::vector<video::SColor> > m_palettes;
|
||||||
|
|
||||||
// NodeResolvers to callback once node registration has ended
|
// NodeResolvers to callback once node registration has ended
|
||||||
std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
||||||
|
|
||||||
@ -1062,7 +1150,8 @@ void getNodeBoxUnion(const NodeBox &nodebox, const ContentFeatures &features,
|
|||||||
if (nodebox.type == NODEBOX_LEVELED) {
|
if (nodebox.type == NODEBOX_LEVELED) {
|
||||||
half_processed.MaxEdge.Y = +BS / 2;
|
half_processed.MaxEdge.Y = +BS / 2;
|
||||||
}
|
}
|
||||||
if (features.param_type_2 == CPT2_FACEDIR) {
|
if (features.param_type_2 == CPT2_FACEDIR ||
|
||||||
|
features.param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
// Get maximal coordinate
|
// Get maximal coordinate
|
||||||
f32 coords[] = {
|
f32 coords[] = {
|
||||||
fabsf(half_processed.MinEdge.X),
|
fabsf(half_processed.MinEdge.X),
|
||||||
@ -1309,6 +1398,78 @@ void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<video::SColor> *CNodeDefManager::getPalette(
|
||||||
|
const ContentFeatures &f, const IGameDef *gamedef)
|
||||||
|
{
|
||||||
|
#ifndef SERVER
|
||||||
|
// This works because colors always use the most significant bits
|
||||||
|
// of param2. If you add a new colored type which uses param2
|
||||||
|
// in a more advanced way, you should change this code, too.
|
||||||
|
u32 palette_pixels = 0;
|
||||||
|
switch (f.param_type_2) {
|
||||||
|
case CPT2_COLOR:
|
||||||
|
palette_pixels = 256;
|
||||||
|
break;
|
||||||
|
case CPT2_COLORED_FACEDIR:
|
||||||
|
palette_pixels = 8;
|
||||||
|
break;
|
||||||
|
case CPT2_COLORED_WALLMOUNTED:
|
||||||
|
palette_pixels = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// This many param2 values will have the same color
|
||||||
|
u32 step = 256 / palette_pixels;
|
||||||
|
const std::string &name = f.palette_name;
|
||||||
|
if (name == "")
|
||||||
|
return NULL;
|
||||||
|
Client *client = (Client *) gamedef;
|
||||||
|
ITextureSource *tsrc = client->tsrc();
|
||||||
|
|
||||||
|
UNORDERED_MAP<std::string, std::vector<video::SColor> >::iterator it =
|
||||||
|
m_palettes.find(name);
|
||||||
|
if (it == m_palettes.end()) {
|
||||||
|
// Create palette
|
||||||
|
if (!tsrc->isKnownSourceImage(name)) {
|
||||||
|
warningstream << "CNodeDefManager::getPalette(): palette \"" << name
|
||||||
|
<< "\" could not be loaded." << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
video::IImage *img = tsrc->generateImage(name);
|
||||||
|
std::vector<video::SColor> new_palette;
|
||||||
|
u32 w = img->getDimension().Width;
|
||||||
|
u32 h = img->getDimension().Height;
|
||||||
|
// Real area of the image
|
||||||
|
u32 area = h * w;
|
||||||
|
if (area != palette_pixels)
|
||||||
|
warningstream << "CNodeDefManager::getPalette(): the "
|
||||||
|
<< "specified palette image \"" << name << "\" does not "
|
||||||
|
<< "contain exactly " << palette_pixels
|
||||||
|
<< " pixels." << std::endl;
|
||||||
|
if (area > palette_pixels)
|
||||||
|
area = palette_pixels;
|
||||||
|
// For each pixel in the image
|
||||||
|
for (u32 i = 0; i < area; i++) {
|
||||||
|
video::SColor c = img->getPixel(i % w, i / w);
|
||||||
|
// Fill in palette with 'step' colors
|
||||||
|
for (u32 j = 0; j < step; j++)
|
||||||
|
new_palette.push_back(c);
|
||||||
|
}
|
||||||
|
img->drop();
|
||||||
|
// Fill in remaining elements
|
||||||
|
while (new_palette.size() < 256)
|
||||||
|
new_palette.push_back(video::SColor(0xFFFFFFFF));
|
||||||
|
m_palettes[name] = new_palette;
|
||||||
|
it = m_palettes.find(name);
|
||||||
|
}
|
||||||
|
if (it != m_palettes.end())
|
||||||
|
return &((*it).second);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
||||||
void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
|
void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
|
||||||
void *progress_callback_args)
|
void *progress_callback_args)
|
||||||
@ -1325,10 +1486,13 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
|||||||
TextureSettings tsettings;
|
TextureSettings tsettings;
|
||||||
tsettings.readSettings();
|
tsettings.readSettings();
|
||||||
|
|
||||||
|
m_palettes.clear();
|
||||||
u32 size = m_content_features.size();
|
u32 size = m_content_features.size();
|
||||||
|
|
||||||
for (u32 i = 0; i < size; i++) {
|
for (u32 i = 0; i < size; i++) {
|
||||||
m_content_features[i].updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
|
ContentFeatures *f = &(m_content_features[i]);
|
||||||
|
f->palette = getPalette(*f, gamedef);
|
||||||
|
f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
|
||||||
progress_callback(progress_callback_args, i, size);
|
progress_callback(progress_callback_args, i, size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1429,6 +1593,19 @@ IWritableNodeDefManager *createNodeDefManager()
|
|||||||
//// Serialization of old ContentFeatures formats
|
//// Serialization of old ContentFeatures formats
|
||||||
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
||||||
{
|
{
|
||||||
|
u8 compatible_param_type_2 = param_type_2;
|
||||||
|
if ((protocol_version < 28)
|
||||||
|
&& (compatible_param_type_2 == CPT2_MESHOPTIONS))
|
||||||
|
compatible_param_type_2 = CPT2_NONE;
|
||||||
|
else if (protocol_version < 30) {
|
||||||
|
if (compatible_param_type_2 == CPT2_COLOR)
|
||||||
|
compatible_param_type_2 = CPT2_NONE;
|
||||||
|
else if (compatible_param_type_2 == CPT2_COLORED_FACEDIR)
|
||||||
|
compatible_param_type_2 = CPT2_FACEDIR;
|
||||||
|
else if (compatible_param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
||||||
|
compatible_param_type_2 = CPT2_WALLMOUNTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (protocol_version == 13)
|
if (protocol_version == 13)
|
||||||
{
|
{
|
||||||
writeU8(os, 5); // version
|
writeU8(os, 5); // version
|
||||||
@ -1454,7 +1631,7 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
|||||||
writeU8(os, post_effect_color.getGreen());
|
writeU8(os, post_effect_color.getGreen());
|
||||||
writeU8(os, post_effect_color.getBlue());
|
writeU8(os, post_effect_color.getBlue());
|
||||||
writeU8(os, param_type);
|
writeU8(os, param_type);
|
||||||
writeU8(os, param_type_2);
|
writeU8(os, compatible_param_type_2);
|
||||||
writeU8(os, is_ground_content);
|
writeU8(os, is_ground_content);
|
||||||
writeU8(os, light_propagates);
|
writeU8(os, light_propagates);
|
||||||
writeU8(os, sunlight_propagates);
|
writeU8(os, sunlight_propagates);
|
||||||
@ -1483,9 +1660,9 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
|||||||
os<<serializeString(name);
|
os<<serializeString(name);
|
||||||
writeU16(os, groups.size());
|
writeU16(os, groups.size());
|
||||||
for (ItemGroupList::const_iterator
|
for (ItemGroupList::const_iterator
|
||||||
i = groups.begin(); i != groups.end(); ++i) {
|
i = groups.begin(); i != groups.end(); ++i) {
|
||||||
os<<serializeString(i->first);
|
os<<serializeString(i->first);
|
||||||
writeS16(os, i->second);
|
writeS16(os, i->second);
|
||||||
}
|
}
|
||||||
writeU8(os, drawtype);
|
writeU8(os, drawtype);
|
||||||
writeF1000(os, visual_scale);
|
writeF1000(os, visual_scale);
|
||||||
@ -1502,7 +1679,7 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
|||||||
writeU8(os, post_effect_color.getGreen());
|
writeU8(os, post_effect_color.getGreen());
|
||||||
writeU8(os, post_effect_color.getBlue());
|
writeU8(os, post_effect_color.getBlue());
|
||||||
writeU8(os, param_type);
|
writeU8(os, param_type);
|
||||||
writeU8(os, param_type_2);
|
writeU8(os, compatible_param_type_2);
|
||||||
writeU8(os, is_ground_content);
|
writeU8(os, is_ground_content);
|
||||||
writeU8(os, light_propagates);
|
writeU8(os, light_propagates);
|
||||||
writeU8(os, sunlight_propagates);
|
writeU8(os, sunlight_propagates);
|
||||||
@ -1530,6 +1707,68 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
|||||||
writeU8(os, drowning);
|
writeU8(os, drowning);
|
||||||
writeU8(os, leveled);
|
writeU8(os, leveled);
|
||||||
writeU8(os, liquid_range);
|
writeU8(os, liquid_range);
|
||||||
|
}
|
||||||
|
else if(protocol_version >= 24 && protocol_version < 30) {
|
||||||
|
writeU8(os, protocol_version < 27 ? 7 : 8);
|
||||||
|
|
||||||
|
os << serializeString(name);
|
||||||
|
writeU16(os, groups.size());
|
||||||
|
for (ItemGroupList::const_iterator i = groups.begin();
|
||||||
|
i != groups.end(); ++i) {
|
||||||
|
os << serializeString(i->first);
|
||||||
|
writeS16(os, i->second);
|
||||||
|
}
|
||||||
|
writeU8(os, drawtype);
|
||||||
|
writeF1000(os, visual_scale);
|
||||||
|
writeU8(os, 6);
|
||||||
|
for (u32 i = 0; i < 6; i++)
|
||||||
|
tiledef[i].serialize(os, protocol_version);
|
||||||
|
writeU8(os, CF_SPECIAL_COUNT);
|
||||||
|
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||||
|
tiledef_special[i].serialize(os, protocol_version);
|
||||||
|
writeU8(os, alpha);
|
||||||
|
writeU8(os, post_effect_color.getAlpha());
|
||||||
|
writeU8(os, post_effect_color.getRed());
|
||||||
|
writeU8(os, post_effect_color.getGreen());
|
||||||
|
writeU8(os, post_effect_color.getBlue());
|
||||||
|
writeU8(os, param_type);
|
||||||
|
writeU8(os, compatible_param_type_2);
|
||||||
|
writeU8(os, is_ground_content);
|
||||||
|
writeU8(os, light_propagates);
|
||||||
|
writeU8(os, sunlight_propagates);
|
||||||
|
writeU8(os, walkable);
|
||||||
|
writeU8(os, pointable);
|
||||||
|
writeU8(os, diggable);
|
||||||
|
writeU8(os, climbable);
|
||||||
|
writeU8(os, buildable_to);
|
||||||
|
os << serializeString(""); // legacy: used to be metadata_name
|
||||||
|
writeU8(os, liquid_type);
|
||||||
|
os << serializeString(liquid_alternative_flowing);
|
||||||
|
os << serializeString(liquid_alternative_source);
|
||||||
|
writeU8(os, liquid_viscosity);
|
||||||
|
writeU8(os, liquid_renewable);
|
||||||
|
writeU8(os, light_source);
|
||||||
|
writeU32(os, damage_per_second);
|
||||||
|
node_box.serialize(os, protocol_version);
|
||||||
|
selection_box.serialize(os, protocol_version);
|
||||||
|
writeU8(os, legacy_facedir_simple);
|
||||||
|
writeU8(os, legacy_wallmounted);
|
||||||
|
serializeSimpleSoundSpec(sound_footstep, os);
|
||||||
|
serializeSimpleSoundSpec(sound_dig, os);
|
||||||
|
serializeSimpleSoundSpec(sound_dug, os);
|
||||||
|
writeU8(os, rightclickable);
|
||||||
|
writeU8(os, drowning);
|
||||||
|
writeU8(os, leveled);
|
||||||
|
writeU8(os, liquid_range);
|
||||||
|
writeU8(os, waving);
|
||||||
|
os << serializeString(mesh);
|
||||||
|
collision_box.serialize(os, protocol_version);
|
||||||
|
writeU8(os, floodable);
|
||||||
|
writeU16(os, connects_to_ids.size());
|
||||||
|
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
|
||||||
|
i != connects_to_ids.end(); ++i)
|
||||||
|
writeU16(os, *i);
|
||||||
|
writeU8(os, connect_sides);
|
||||||
} else
|
} else
|
||||||
throw SerializationError("ContentFeatures::serialize(): "
|
throw SerializationError("ContentFeatures::serialize(): "
|
||||||
"Unsupported version requested");
|
"Unsupported version requested");
|
||||||
@ -1642,7 +1881,73 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||||||
drowning = readU8(is);
|
drowning = readU8(is);
|
||||||
leveled = readU8(is);
|
leveled = readU8(is);
|
||||||
liquid_range = readU8(is);
|
liquid_range = readU8(is);
|
||||||
} else {
|
} else if (version == 7 || version == 8){
|
||||||
|
name = deSerializeString(is);
|
||||||
|
groups.clear();
|
||||||
|
u32 groups_size = readU16(is);
|
||||||
|
for (u32 i = 0; i < groups_size; i++) {
|
||||||
|
std::string name = deSerializeString(is);
|
||||||
|
int value = readS16(is);
|
||||||
|
groups[name] = value;
|
||||||
|
}
|
||||||
|
drawtype = (enum NodeDrawType) readU8(is);
|
||||||
|
|
||||||
|
visual_scale = readF1000(is);
|
||||||
|
if (readU8(is) != 6)
|
||||||
|
throw SerializationError("unsupported tile count");
|
||||||
|
for (u32 i = 0; i < 6; i++)
|
||||||
|
tiledef[i].deSerialize(is, version, drawtype);
|
||||||
|
if (readU8(is) != CF_SPECIAL_COUNT)
|
||||||
|
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||||
|
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||||
|
tiledef_special[i].deSerialize(is, version, drawtype);
|
||||||
|
alpha = readU8(is);
|
||||||
|
post_effect_color.setAlpha(readU8(is));
|
||||||
|
post_effect_color.setRed(readU8(is));
|
||||||
|
post_effect_color.setGreen(readU8(is));
|
||||||
|
post_effect_color.setBlue(readU8(is));
|
||||||
|
param_type = (enum ContentParamType) readU8(is);
|
||||||
|
param_type_2 = (enum ContentParamType2) readU8(is);
|
||||||
|
is_ground_content = readU8(is);
|
||||||
|
light_propagates = readU8(is);
|
||||||
|
sunlight_propagates = readU8(is);
|
||||||
|
walkable = readU8(is);
|
||||||
|
pointable = readU8(is);
|
||||||
|
diggable = readU8(is);
|
||||||
|
climbable = readU8(is);
|
||||||
|
buildable_to = readU8(is);
|
||||||
|
deSerializeString(is); // legacy: used to be metadata_name
|
||||||
|
liquid_type = (enum LiquidType) readU8(is);
|
||||||
|
liquid_alternative_flowing = deSerializeString(is);
|
||||||
|
liquid_alternative_source = deSerializeString(is);
|
||||||
|
liquid_viscosity = readU8(is);
|
||||||
|
liquid_renewable = readU8(is);
|
||||||
|
light_source = readU8(is);
|
||||||
|
light_source = MYMIN(light_source, LIGHT_MAX);
|
||||||
|
damage_per_second = readU32(is);
|
||||||
|
node_box.deSerialize(is);
|
||||||
|
selection_box.deSerialize(is);
|
||||||
|
legacy_facedir_simple = readU8(is);
|
||||||
|
legacy_wallmounted = readU8(is);
|
||||||
|
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||||
|
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||||
|
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||||
|
rightclickable = readU8(is);
|
||||||
|
drowning = readU8(is);
|
||||||
|
leveled = readU8(is);
|
||||||
|
liquid_range = readU8(is);
|
||||||
|
waving = readU8(is);
|
||||||
|
try {
|
||||||
|
mesh = deSerializeString(is);
|
||||||
|
collision_box.deSerialize(is);
|
||||||
|
floodable = readU8(is);
|
||||||
|
u16 connects_to_size = readU16(is);
|
||||||
|
connects_to_ids.clear();
|
||||||
|
for (u16 i = 0; i < connects_to_size; i++)
|
||||||
|
connects_to_ids.insert(readU16(is));
|
||||||
|
connect_sides = readU8(is);
|
||||||
|
} catch (SerializationError &e) {};
|
||||||
|
}else{
|
||||||
throw SerializationError("unsupported ContentFeatures version");
|
throw SerializationError("unsupported ContentFeatures version");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1736,19 +2041,23 @@ bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to, u8 connect_face)
|
|||||||
|
|
||||||
// does to node declare usable faces?
|
// does to node declare usable faces?
|
||||||
if (f2.connect_sides > 0) {
|
if (f2.connect_sides > 0) {
|
||||||
if ((f2.param_type_2 == CPT2_FACEDIR) && (connect_face >= 4)) {
|
if ((f2.param_type_2 == CPT2_FACEDIR ||
|
||||||
static const u8 rot[33 * 4] = {
|
f2.param_type_2 == CPT2_COLORED_FACEDIR)
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
&& (connect_face >= 4)) {
|
||||||
4, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - back
|
static const u8 rot[33 * 4] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
8, 4, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - right
|
0, 0, 0, 0, 4, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, // 4 - back
|
||||||
16, 8, 4, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - front
|
8, 4, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, // 8 - right
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 4, 32, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
32, 16, 8, 4 // 32 - left
|
0, // 16 - front
|
||||||
};
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
return (f2.connect_sides & rot[(connect_face * 4) + to.param2]);
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 32, 16, 8, 4 // 32 - left
|
||||||
|
};
|
||||||
|
return (f2.connect_sides
|
||||||
|
& rot[(connect_face * 4) + (to.param2 & 0x1F)]);
|
||||||
}
|
}
|
||||||
return (f2.connect_sides & connect_face);
|
return (f2.connect_sides & connect_face);
|
||||||
}
|
}
|
||||||
|
108
src/nodedef.h
108
src/nodedef.h
@ -68,7 +68,13 @@ enum ContentParamType2
|
|||||||
// 2D rotation for things like plants
|
// 2D rotation for things like plants
|
||||||
CPT2_DEGROTATE,
|
CPT2_DEGROTATE,
|
||||||
// Mesh options for plants
|
// Mesh options for plants
|
||||||
CPT2_MESHOPTIONS
|
CPT2_MESHOPTIONS,
|
||||||
|
// Index for palette
|
||||||
|
CPT2_COLOR,
|
||||||
|
// 3 bits of palette index, then facedir
|
||||||
|
CPT2_COLORED_FACEDIR,
|
||||||
|
// 5 bits of palette index, then wallmounted
|
||||||
|
CPT2_COLORED_WALLMOUNTED
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LiquidType
|
enum LiquidType
|
||||||
@ -170,6 +176,11 @@ struct TileDef
|
|||||||
bool backface_culling; // Takes effect only in special cases
|
bool backface_culling; // Takes effect only in special cases
|
||||||
bool tileable_horizontal;
|
bool tileable_horizontal;
|
||||||
bool tileable_vertical;
|
bool tileable_vertical;
|
||||||
|
//! If true, the tile has its own color.
|
||||||
|
bool has_color;
|
||||||
|
//! The color of the tile.
|
||||||
|
video::SColor color;
|
||||||
|
|
||||||
struct TileAnimationParams animation;
|
struct TileAnimationParams animation;
|
||||||
|
|
||||||
TileDef()
|
TileDef()
|
||||||
@ -178,6 +189,8 @@ struct TileDef
|
|||||||
backface_culling = true;
|
backface_culling = true;
|
||||||
tileable_horizontal = true;
|
tileable_horizontal = true;
|
||||||
tileable_vertical = true;
|
tileable_vertical = true;
|
||||||
|
has_color = false;
|
||||||
|
color = video::SColor(0xFFFFFFFF);
|
||||||
animation.type = TAT_NONE;
|
animation.type = TAT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +204,7 @@ struct ContentFeatures
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Cached stuff
|
Cached stuff
|
||||||
*/
|
*/
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
// 0 1 2 3 4 5
|
// 0 1 2 3 4 5
|
||||||
// up down right left back front
|
// up down right left back front
|
||||||
@ -211,12 +224,19 @@ struct ContentFeatures
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Actual data
|
Actual data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// --- GENERAL PROPERTIES ---
|
||||||
|
|
||||||
std::string name; // "" = undefined node
|
std::string name; // "" = undefined node
|
||||||
ItemGroupList groups; // Same as in itemdef
|
ItemGroupList groups; // Same as in itemdef
|
||||||
|
// Type of MapNode::param1
|
||||||
|
ContentParamType param_type;
|
||||||
|
// Type of MapNode::param2
|
||||||
|
ContentParamType2 param_type_2;
|
||||||
|
|
||||||
|
// --- VISUAL PROPERTIES ---
|
||||||
|
|
||||||
// Visual definition
|
|
||||||
enum NodeDrawType drawtype;
|
enum NodeDrawType drawtype;
|
||||||
std::string mesh;
|
std::string mesh;
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
@ -226,19 +246,38 @@ struct ContentFeatures
|
|||||||
float visual_scale; // Misc. scale parameter
|
float visual_scale; // Misc. scale parameter
|
||||||
TileDef tiledef[6];
|
TileDef tiledef[6];
|
||||||
TileDef tiledef_special[CF_SPECIAL_COUNT]; // eg. flowing liquid
|
TileDef tiledef_special[CF_SPECIAL_COUNT]; // eg. flowing liquid
|
||||||
|
// If 255, the node is opaque.
|
||||||
|
// Otherwise it uses texture alpha.
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
|
// The color of the node.
|
||||||
|
video::SColor color;
|
||||||
|
std::string palette_name;
|
||||||
|
std::vector<video::SColor> *palette;
|
||||||
|
// Used for waving leaves/plants
|
||||||
|
u8 waving;
|
||||||
|
// for NDT_CONNECTED pairing
|
||||||
|
u8 connect_sides;
|
||||||
|
std::vector<std::string> connects_to;
|
||||||
|
std::set<content_t> connects_to_ids;
|
||||||
// Post effect color, drawn when the camera is inside the node.
|
// Post effect color, drawn when the camera is inside the node.
|
||||||
video::SColor post_effect_color;
|
video::SColor post_effect_color;
|
||||||
|
// Flowing liquid or snow, value = default level
|
||||||
|
u8 leveled;
|
||||||
|
|
||||||
|
// --- LIGHTING-RELATED ---
|
||||||
|
|
||||||
// Type of MapNode::param1
|
|
||||||
ContentParamType param_type;
|
|
||||||
// Type of MapNode::param2
|
|
||||||
ContentParamType2 param_type_2;
|
|
||||||
// True for all ground-like things like stone and mud, false for eg. trees
|
|
||||||
bool is_ground_content;
|
|
||||||
bool light_propagates;
|
bool light_propagates;
|
||||||
bool sunlight_propagates;
|
bool sunlight_propagates;
|
||||||
|
// Amount of light the node emits
|
||||||
|
u8 light_source;
|
||||||
|
|
||||||
|
// --- MAP GENERATION ---
|
||||||
|
|
||||||
|
// True for all ground-like things like stone and mud, false for eg. trees
|
||||||
|
bool is_ground_content;
|
||||||
|
|
||||||
|
// --- INTERACTION PROPERTIES ---
|
||||||
|
|
||||||
// This is used for collision detection.
|
// This is used for collision detection.
|
||||||
// Also for general solidness queries.
|
// Also for general solidness queries.
|
||||||
bool walkable;
|
bool walkable;
|
||||||
@ -250,12 +289,12 @@ struct ContentFeatures
|
|||||||
bool climbable;
|
bool climbable;
|
||||||
// Player can build on these
|
// Player can build on these
|
||||||
bool buildable_to;
|
bool buildable_to;
|
||||||
// Liquids flow into and replace node
|
|
||||||
bool floodable;
|
|
||||||
// Player cannot build to these (placement prediction disabled)
|
// Player cannot build to these (placement prediction disabled)
|
||||||
bool rightclickable;
|
bool rightclickable;
|
||||||
// Flowing liquid or snow, value = default level
|
u32 damage_per_second;
|
||||||
u8 leveled;
|
|
||||||
|
// --- LIQUID PROPERTIES ---
|
||||||
|
|
||||||
// Whether the node is non-liquid, source liquid or flowing liquid
|
// Whether the node is non-liquid, source liquid or flowing liquid
|
||||||
enum LiquidType liquid_type;
|
enum LiquidType liquid_type;
|
||||||
// If the content is liquid, this is the flowing version of the liquid.
|
// If the content is liquid, this is the flowing version of the liquid.
|
||||||
@ -271,29 +310,28 @@ struct ContentFeatures
|
|||||||
// Number of flowing liquids surrounding source
|
// Number of flowing liquids surrounding source
|
||||||
u8 liquid_range;
|
u8 liquid_range;
|
||||||
u8 drowning;
|
u8 drowning;
|
||||||
// Amount of light the node emits
|
// Liquids flow into and replace node
|
||||||
u8 light_source;
|
bool floodable;
|
||||||
u32 damage_per_second;
|
|
||||||
|
// --- NODEBOXES ---
|
||||||
|
|
||||||
NodeBox node_box;
|
NodeBox node_box;
|
||||||
NodeBox selection_box;
|
NodeBox selection_box;
|
||||||
NodeBox collision_box;
|
NodeBox collision_box;
|
||||||
// Used for waving leaves/plants
|
|
||||||
u8 waving;
|
// --- SOUND PROPERTIES ---
|
||||||
|
|
||||||
|
SimpleSoundSpec sound_footstep;
|
||||||
|
SimpleSoundSpec sound_dig;
|
||||||
|
SimpleSoundSpec sound_dug;
|
||||||
|
|
||||||
|
// --- LEGACY ---
|
||||||
|
|
||||||
// Compatibility with old maps
|
// Compatibility with old maps
|
||||||
// Set to true if paramtype used to be 'facedir_simple'
|
// Set to true if paramtype used to be 'facedir_simple'
|
||||||
bool legacy_facedir_simple;
|
bool legacy_facedir_simple;
|
||||||
// Set to true if wall_mounted used to be set to true
|
// Set to true if wall_mounted used to be set to true
|
||||||
bool legacy_wallmounted;
|
bool legacy_wallmounted;
|
||||||
// for NDT_CONNECTED pairing
|
|
||||||
u8 connect_sides;
|
|
||||||
|
|
||||||
// Sound properties
|
|
||||||
SimpleSoundSpec sound_footstep;
|
|
||||||
SimpleSoundSpec sound_dig;
|
|
||||||
SimpleSoundSpec sound_dug;
|
|
||||||
|
|
||||||
std::vector<std::string> connects_to;
|
|
||||||
std::set<content_t> connects_to_ids;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Methods
|
Methods
|
||||||
@ -306,6 +344,14 @@ struct ContentFeatures
|
|||||||
void deSerialize(std::istream &is);
|
void deSerialize(std::istream &is);
|
||||||
void serializeOld(std::ostream &os, u16 protocol_version) const;
|
void serializeOld(std::ostream &os, u16 protocol_version) const;
|
||||||
void deSerializeOld(std::istream &is, int version);
|
void deSerializeOld(std::istream &is, int version);
|
||||||
|
/*!
|
||||||
|
* Since vertex alpha is no lnger supported, this method
|
||||||
|
* adds instructions to the texture names to blend alpha there.
|
||||||
|
*
|
||||||
|
* tiledef, tiledef_special and alpha must be initialized
|
||||||
|
* before calling this.
|
||||||
|
*/
|
||||||
|
void correctAlpha();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some handy methods
|
Some handy methods
|
||||||
@ -321,7 +367,7 @@ struct ContentFeatures
|
|||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef,
|
void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef,
|
||||||
u32 shader_id, bool use_normal_texture, bool backface_culling,
|
u32 shader_id, bool use_normal_texture, bool backface_culling,
|
||||||
u8 alpha, u8 material_type);
|
u8 material_type);
|
||||||
void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
||||||
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings);
|
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings);
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,7 +56,8 @@ Particle::Particle(
|
|||||||
v2f texpos,
|
v2f texpos,
|
||||||
v2f texsize,
|
v2f texsize,
|
||||||
const struct TileAnimationParams &anim,
|
const struct TileAnimationParams &anim,
|
||||||
u8 glow
|
u8 glow,
|
||||||
|
video::SColor color
|
||||||
):
|
):
|
||||||
scene::ISceneNode(smgr->getRootSceneNode(), smgr)
|
scene::ISceneNode(smgr->getRootSceneNode(), smgr)
|
||||||
{
|
{
|
||||||
@ -77,6 +78,10 @@ Particle::Particle(
|
|||||||
m_animation_frame = 0;
|
m_animation_frame = 0;
|
||||||
m_animation_time = 0.0;
|
m_animation_time = 0.0;
|
||||||
|
|
||||||
|
// Color
|
||||||
|
m_base_color = color;
|
||||||
|
m_color = color;
|
||||||
|
|
||||||
// Particle related
|
// Particle related
|
||||||
m_pos = pos;
|
m_pos = pos;
|
||||||
m_velocity = velocity;
|
m_velocity = velocity;
|
||||||
@ -183,12 +188,15 @@ void Particle::updateLight()
|
|||||||
else
|
else
|
||||||
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
|
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
|
||||||
|
|
||||||
m_light = decode_light(light + m_glow);
|
u8 m_light = decode_light(light + m_glow);
|
||||||
|
m_color.set(255,
|
||||||
|
m_light * m_base_color.getRed() / 255,
|
||||||
|
m_light * m_base_color.getGreen() / 255,
|
||||||
|
m_light * m_base_color.getBlue() / 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Particle::updateVertices()
|
void Particle::updateVertices()
|
||||||
{
|
{
|
||||||
video::SColor c(255, m_light, m_light, m_light);
|
|
||||||
f32 tx0, tx1, ty0, ty1;
|
f32 tx0, tx1, ty0, ty1;
|
||||||
|
|
||||||
if (m_animation.type != TAT_NONE) {
|
if (m_animation.type != TAT_NONE) {
|
||||||
@ -210,14 +218,14 @@ void Particle::updateVertices()
|
|||||||
ty1 = m_texpos.Y + m_texsize.Y;
|
ty1 = m_texpos.Y + m_texsize.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
|
m_vertices[0] = video::S3DVertex(-m_size / 2, -m_size / 2,
|
||||||
c, tx0, ty1);
|
0, 0, 0, 0, m_color, tx0, ty1);
|
||||||
m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
|
m_vertices[1] = video::S3DVertex(m_size / 2, -m_size / 2,
|
||||||
c, tx1, ty1);
|
0, 0, 0, 0, m_color, tx1, ty1);
|
||||||
m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
|
m_vertices[2] = video::S3DVertex(m_size / 2, m_size / 2,
|
||||||
c, tx1, ty0);
|
0, 0, 0, 0, m_color, tx1, ty0);
|
||||||
m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
|
m_vertices[3] = video::S3DVertex(-m_size / 2, m_size / 2,
|
||||||
c, tx0, ty0);
|
0, 0, 0, 0, m_color, tx0, ty0);
|
||||||
|
|
||||||
v3s16 camera_offset = m_env->getCameraOffset();
|
v3s16 camera_offset = m_env->getCameraOffset();
|
||||||
for(u16 i=0; i<4; i++)
|
for(u16 i=0; i<4; i++)
|
||||||
@ -589,35 +597,39 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleManager::addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
void ParticleManager::addDiggingParticles(IGameDef* gamedef,
|
||||||
LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos,
|
||||||
|
const MapNode &n, const ContentFeatures &f)
|
||||||
{
|
{
|
||||||
for (u16 j = 0; j < 32; j++) // set the amount of particles here
|
for (u16 j = 0; j < 32; j++) // set the amount of particles here
|
||||||
{
|
{
|
||||||
addNodeParticle(gamedef, smgr, player, pos, tiles);
|
addNodeParticle(gamedef, smgr, player, pos, n, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleManager::addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
void ParticleManager::addPunchingParticles(IGameDef* gamedef,
|
||||||
LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos,
|
||||||
|
const MapNode &n, const ContentFeatures &f)
|
||||||
{
|
{
|
||||||
addNodeParticle(gamedef, smgr, player, pos, tiles);
|
addNodeParticle(gamedef, smgr, player, pos, n, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
void ParticleManager::addNodeParticle(IGameDef* gamedef,
|
||||||
LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos,
|
||||||
|
const MapNode &n, const ContentFeatures &f)
|
||||||
{
|
{
|
||||||
// Texture
|
// Texture
|
||||||
u8 texid = myrand_range(0, 5);
|
u8 texid = myrand_range(0, 5);
|
||||||
|
const TileSpec &tile = f.tiles[texid];
|
||||||
video::ITexture *texture;
|
video::ITexture *texture;
|
||||||
struct TileAnimationParams anim;
|
struct TileAnimationParams anim;
|
||||||
anim.type = TAT_NONE;
|
anim.type = TAT_NONE;
|
||||||
|
|
||||||
// Only use first frame of animated texture
|
// Only use first frame of animated texture
|
||||||
if (tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION)
|
if (tile.material_flags & MATERIAL_FLAG_ANIMATION)
|
||||||
texture = tiles[texid].frames[0].texture;
|
texture = tile.frames[0].texture;
|
||||||
else
|
else
|
||||||
texture = tiles[texid].texture;
|
texture = tile.texture;
|
||||||
|
|
||||||
float size = rand() % 64 / 512.;
|
float size = rand() % 64 / 512.;
|
||||||
float visual_size = BS * size;
|
float visual_size = BS * size;
|
||||||
@ -638,6 +650,12 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s
|
|||||||
(f32) pos.Z + rand() %100 /200. - 0.25
|
(f32) pos.Z + rand() %100 /200. - 0.25
|
||||||
);
|
);
|
||||||
|
|
||||||
|
video::SColor color;
|
||||||
|
if (tile.has_color)
|
||||||
|
color = tile.color;
|
||||||
|
else
|
||||||
|
n.getColor(f, &color);
|
||||||
|
|
||||||
Particle* toadd = new Particle(
|
Particle* toadd = new Particle(
|
||||||
gamedef,
|
gamedef,
|
||||||
smgr,
|
smgr,
|
||||||
@ -655,7 +673,8 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s
|
|||||||
texpos,
|
texpos,
|
||||||
texsize,
|
texsize,
|
||||||
anim,
|
anim,
|
||||||
0);
|
0,
|
||||||
|
color);
|
||||||
|
|
||||||
addParticle(toadd);
|
addParticle(toadd);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
struct ClientEvent;
|
struct ClientEvent;
|
||||||
class ParticleManager;
|
class ParticleManager;
|
||||||
class ClientEnvironment;
|
class ClientEnvironment;
|
||||||
|
class MapNode;
|
||||||
|
class ContentFeatures;
|
||||||
|
|
||||||
class Particle : public scene::ISceneNode
|
class Particle : public scene::ISceneNode
|
||||||
{
|
{
|
||||||
@ -53,7 +55,8 @@ class Particle : public scene::ISceneNode
|
|||||||
v2f texpos,
|
v2f texpos,
|
||||||
v2f texsize,
|
v2f texsize,
|
||||||
const struct TileAnimationParams &anim,
|
const struct TileAnimationParams &anim,
|
||||||
u8 glow
|
u8 glow,
|
||||||
|
video::SColor color = video::SColor(0xFFFFFFFF)
|
||||||
);
|
);
|
||||||
~Particle();
|
~Particle();
|
||||||
|
|
||||||
@ -100,7 +103,10 @@ private:
|
|||||||
v3f m_acceleration;
|
v3f m_acceleration;
|
||||||
LocalPlayer *m_player;
|
LocalPlayer *m_player;
|
||||||
float m_size;
|
float m_size;
|
||||||
u8 m_light;
|
//! Color without lighting
|
||||||
|
video::SColor m_base_color;
|
||||||
|
//! Final rendered color
|
||||||
|
video::SColor m_color;
|
||||||
bool m_collisiondetection;
|
bool m_collisiondetection;
|
||||||
bool m_collision_removal;
|
bool m_collision_removal;
|
||||||
bool m_vertical;
|
bool m_vertical;
|
||||||
@ -184,13 +190,16 @@ public:
|
|||||||
scene::ISceneManager* smgr, LocalPlayer *player);
|
scene::ISceneManager* smgr, LocalPlayer *player);
|
||||||
|
|
||||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||||
LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
LocalPlayer *player, v3s16 pos, const MapNode &n,
|
||||||
|
const ContentFeatures &f);
|
||||||
|
|
||||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||||
LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
LocalPlayer *player, v3s16 pos, const MapNode &n,
|
||||||
|
const ContentFeatures &f);
|
||||||
|
|
||||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||||
LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
LocalPlayer *player, v3s16 pos, const MapNode &n,
|
||||||
|
const ContentFeatures &f);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addParticle(Particle* toadd);
|
void addParticle(Particle* toadd);
|
||||||
|
@ -332,6 +332,10 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
|
|||||||
L, index, "tileable_horizontal", default_tiling);
|
L, index, "tileable_horizontal", default_tiling);
|
||||||
tiledef.tileable_vertical = getboolfield_default(
|
tiledef.tileable_vertical = getboolfield_default(
|
||||||
L, index, "tileable_vertical", default_tiling);
|
L, index, "tileable_vertical", default_tiling);
|
||||||
|
// color = ...
|
||||||
|
lua_getfield(L, index, "color");
|
||||||
|
tiledef.has_color = read_color(L, -1, &tiledef.color);
|
||||||
|
lua_pop(L, 1);
|
||||||
// animation = {}
|
// animation = {}
|
||||||
lua_getfield(L, index, "animation");
|
lua_getfield(L, index, "animation");
|
||||||
tiledef.animation = read_animation_definition(L, -1);
|
tiledef.animation = read_animation_definition(L, -1);
|
||||||
@ -450,6 +454,13 @@ ContentFeatures read_content_features(lua_State *L, int index)
|
|||||||
if (usealpha)
|
if (usealpha)
|
||||||
f.alpha = 0;
|
f.alpha = 0;
|
||||||
|
|
||||||
|
// Read node color.
|
||||||
|
lua_getfield(L, index, "color");
|
||||||
|
read_color(L, -1, &f.color);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
getstringfield(L, index, "palette", f.palette_name);
|
||||||
|
|
||||||
/* Other stuff */
|
/* Other stuff */
|
||||||
|
|
||||||
lua_getfield(L, index, "post_effect_color");
|
lua_getfield(L, index, "post_effect_color");
|
||||||
@ -461,6 +472,13 @@ ContentFeatures read_content_features(lua_State *L, int index)
|
|||||||
f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
|
f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
|
||||||
ScriptApiNode::es_ContentParamType2, CPT2_NONE);
|
ScriptApiNode::es_ContentParamType2, CPT2_NONE);
|
||||||
|
|
||||||
|
if (f.palette_name != "" &&
|
||||||
|
!(f.param_type_2 == CPT2_COLOR ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_FACEDIR ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
|
||||||
|
warningstream << "Node " << f.name.c_str()
|
||||||
|
<< " has a palette, but not a suitable paramtype2." << std::endl;
|
||||||
|
|
||||||
// Warn about some deprecated fields
|
// Warn about some deprecated fields
|
||||||
warn_if_field_exists(L, index, "wall_mounted",
|
warn_if_field_exists(L, index, "wall_mounted",
|
||||||
"Deprecated; use paramtype2 = 'wallmounted'");
|
"Deprecated; use paramtype2 = 'wallmounted'");
|
||||||
|
@ -59,6 +59,9 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
|
|||||||
{CPT2_LEVELED, "leveled"},
|
{CPT2_LEVELED, "leveled"},
|
||||||
{CPT2_DEGROTATE, "degrotate"},
|
{CPT2_DEGROTATE, "degrotate"},
|
||||||
{CPT2_MESHOPTIONS, "meshoptions"},
|
{CPT2_MESHOPTIONS, "meshoptions"},
|
||||||
|
{CPT2_COLOR, "color"},
|
||||||
|
{CPT2_COLORED_FACEDIR, "colorfacedir"},
|
||||||
|
{CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
|
||||||
{0, NULL},
|
{0, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -543,7 +543,7 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
|
|||||||
shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
break;
|
break;
|
||||||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||||
shaderinfo.base_material = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
break;
|
break;
|
||||||
case TILE_MATERIAL_LIQUID_OPAQUE:
|
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||||
shaderinfo.base_material = video::EMT_SOLID;
|
shaderinfo.base_material = video::EMT_SOLID;
|
||||||
|
@ -318,6 +318,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
|
|||||||
u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
||||||
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
||||||
}
|
}
|
||||||
|
m_colors.clear();
|
||||||
|
|
||||||
// If wield_image is defined, it overrides everything else
|
// If wield_image is defined, it overrides everything else
|
||||||
if (def.wield_image != "") {
|
if (def.wield_image != "") {
|
||||||
@ -358,28 +359,30 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
|
|||||||
material_count = 6;
|
material_count = 6;
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < material_count; ++i) {
|
for (u32 i = 0; i < material_count; ++i) {
|
||||||
|
const TileSpec *tile = &(f.tiles[i]);
|
||||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
|
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
|
||||||
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
|
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
|
||||||
bool animated = (f.tiles[i].animation_frame_count > 1);
|
bool animated = (tile->animation_frame_count > 1);
|
||||||
if (animated) {
|
if (animated) {
|
||||||
FrameSpec animation_frame = f.tiles[i].frames[0];
|
FrameSpec animation_frame = tile->frames[0];
|
||||||
material.setTexture(0, animation_frame.texture);
|
material.setTexture(0, animation_frame.texture);
|
||||||
} else {
|
} else {
|
||||||
material.setTexture(0, f.tiles[i].texture);
|
material.setTexture(0, tile->texture);
|
||||||
}
|
}
|
||||||
|
m_colors.push_back(tile->color);
|
||||||
material.MaterialType = m_material_type;
|
material.MaterialType = m_material_type;
|
||||||
if (m_enable_shaders) {
|
if (m_enable_shaders) {
|
||||||
if (f.tiles[i].normal_texture) {
|
if (tile->normal_texture) {
|
||||||
if (animated) {
|
if (animated) {
|
||||||
FrameSpec animation_frame = f.tiles[i].frames[0];
|
FrameSpec animation_frame = tile->frames[0];
|
||||||
material.setTexture(1, animation_frame.normal_texture);
|
material.setTexture(1, animation_frame.normal_texture);
|
||||||
} else {
|
} else {
|
||||||
material.setTexture(1, f.tiles[i].normal_texture);
|
material.setTexture(1, tile->normal_texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
material.setTexture(2, f.tiles[i].flags_texture);
|
material.setTexture(2, tile->flags_texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -393,11 +396,28 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
|
|||||||
changeToMesh(NULL);
|
changeToMesh(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WieldMeshSceneNode::setColor(video::SColor color)
|
void WieldMeshSceneNode::setColor(video::SColor c)
|
||||||
{
|
{
|
||||||
assert(!m_lighting);
|
assert(!m_lighting);
|
||||||
setMeshColor(m_meshnode->getMesh(), color);
|
scene::IMesh *mesh=m_meshnode->getMesh();
|
||||||
shadeMeshFaces(m_meshnode->getMesh());
|
if (mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 red = c.getRed();
|
||||||
|
u8 green = c.getGreen();
|
||||||
|
u8 blue = c.getBlue();
|
||||||
|
u32 mc = mesh->getMeshBufferCount();
|
||||||
|
for (u32 j = 0; j < mc; j++) {
|
||||||
|
video::SColor bc(0xFFFFFFFF);
|
||||||
|
if (m_colors.size() > j)
|
||||||
|
bc = m_colors[j];
|
||||||
|
video::SColor buffercolor(255,
|
||||||
|
bc.getRed() * red / 255,
|
||||||
|
bc.getGreen() * green / 255,
|
||||||
|
bc.getBlue() * blue / 255);
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
colorizeMeshBuffer(buf, &buffercolor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WieldMeshSceneNode::render()
|
void WieldMeshSceneNode::render()
|
||||||
@ -464,7 +484,6 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
|||||||
} else if (f.drawtype == NDT_PLANTLIKE) {
|
} else if (f.drawtype == NDT_PLANTLIKE) {
|
||||||
mesh = getExtrudedMesh(tsrc,
|
mesh = getExtrudedMesh(tsrc,
|
||||||
tsrc->getTextureName(f.tiles[0].texture_id));
|
tsrc->getTextureName(f.tiles[0].texture_id));
|
||||||
return mesh;
|
|
||||||
} else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES
|
} else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES
|
||||||
|| f.drawtype == NDT_LIQUID || f.drawtype == NDT_FLOWINGLIQUID) {
|
|| f.drawtype == NDT_LIQUID || f.drawtype == NDT_FLOWINGLIQUID) {
|
||||||
mesh = cloneMesh(g_extrusion_mesh_cache->createCube());
|
mesh = cloneMesh(g_extrusion_mesh_cache->createCube());
|
||||||
@ -477,8 +496,6 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
|||||||
mesh = cloneMesh(mapblock_mesh.getMesh());
|
mesh = cloneMesh(mapblock_mesh.getMesh());
|
||||||
translateMesh(mesh, v3f(-BS, -BS, -BS));
|
translateMesh(mesh, v3f(-BS, -BS, -BS));
|
||||||
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
||||||
rotateMeshXZby(mesh, -45);
|
|
||||||
rotateMeshYZby(mesh, -30);
|
|
||||||
|
|
||||||
u32 mc = mesh->getMeshBufferCount();
|
u32 mc = mesh->getMeshBufferCount();
|
||||||
for (u32 i = 0; i < mc; ++i) {
|
for (u32 i = 0; i < mc; ++i) {
|
||||||
@ -492,28 +509,29 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
|||||||
material1.setTexture(3, material2.getTexture(3));
|
material1.setTexture(3, material2.getTexture(3));
|
||||||
material1.MaterialType = material2.MaterialType;
|
material1.MaterialType = material2.MaterialType;
|
||||||
}
|
}
|
||||||
return mesh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shadeMeshFaces(mesh);
|
|
||||||
rotateMeshXZby(mesh, -45);
|
|
||||||
rotateMeshYZby(mesh, -30);
|
|
||||||
|
|
||||||
u32 mc = mesh->getMeshBufferCount();
|
u32 mc = mesh->getMeshBufferCount();
|
||||||
for (u32 i = 0; i < mc; ++i) {
|
for (u32 i = 0; i < mc; ++i) {
|
||||||
video::SMaterial &material = mesh->getMeshBuffer(i)->getMaterial();
|
const TileSpec *tile = &(f.tiles[i]);
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||||
|
colorizeMeshBuffer(buf, &tile->color);
|
||||||
|
video::SMaterial &material = buf->getMaterial();
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
|
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
if (f.tiles[i].animation_frame_count > 1) {
|
if (tile->animation_frame_count > 1) {
|
||||||
FrameSpec animation_frame = f.tiles[i].frames[0];
|
FrameSpec animation_frame = tile->frames[0];
|
||||||
material.setTexture(0, animation_frame.texture);
|
material.setTexture(0, animation_frame.texture);
|
||||||
} else {
|
} else {
|
||||||
material.setTexture(0, f.tiles[i].texture);
|
material.setTexture(0, tile->texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rotateMeshXZby(mesh, -45);
|
||||||
|
rotateMeshYZby(mesh, -30);
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -70,6 +70,11 @@ private:
|
|||||||
bool m_anisotropic_filter;
|
bool m_anisotropic_filter;
|
||||||
bool m_bilinear_filter;
|
bool m_bilinear_filter;
|
||||||
bool m_trilinear_filter;
|
bool m_trilinear_filter;
|
||||||
|
/*!
|
||||||
|
* Stores the colors of the mesh's mesh buffers.
|
||||||
|
* This does not include lighting.
|
||||||
|
*/
|
||||||
|
std::vector<video::SColor> m_colors;
|
||||||
|
|
||||||
// Bounding box culling is disabled for this type of scene node,
|
// Bounding box culling is disabled for this type of scene node,
|
||||||
// so this variable is just required so we can implement
|
// so this variable is just required so we can implement
|
||||||
|
Loading…
Reference in New Issue
Block a user