]> git.lizzy.rs Git - minetest.git/blob - src/particles.cpp
8x block meshes (#13133)
[minetest.git] / src / particles.cpp
1 /*
2 Minetest
3 Copyright (C) 2020 sfan5 <sfan5@live.de>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "particles.h"
21 #include <type_traits>
22 using namespace ParticleParamTypes;
23
24 #define PARAM_PVFN(n) ParticleParamTypes::n##ParameterValue
25 v2f PARAM_PVFN(pick) (float* f, const v2f a, const v2f b) {
26         return v2f(
27                 numericalBlend(f[0], a.X, b.X),
28                 numericalBlend(f[1], a.Y, b.Y)
29         );
30 }
31
32 v3f PARAM_PVFN(pick) (float* f, const v3f a, const v3f b) {
33         return v3f(
34                 numericalBlend(f[0], a.X, b.X),
35                 numericalBlend(f[1], a.Y, b.Y),
36                 numericalBlend(f[2], a.Z, b.Z)
37         );
38 }
39
40 v2f PARAM_PVFN(interpolate) (float fac, const v2f a, const v2f b)
41         { return b.getInterpolated(a, fac); }
42 v3f PARAM_PVFN(interpolate) (float fac, const v3f a, const v3f b)
43         { return b.getInterpolated(a, fac); }
44
45 #define PARAM_DEF_SRZR(T, wr, rd) \
46         void PARAM_PVFN(serialize)  (std::ostream& os, T  v) {wr(os,v);  } \
47         void PARAM_PVFN(deSerialize)(std::istream& is, T& v) {v = rd(is);}
48
49
50 #define PARAM_DEF_NUM(T, wr, rd) PARAM_DEF_SRZR(T, wr, rd) \
51         T PARAM_PVFN(interpolate)(float fac, const T a, const T b) \
52                         { return numericalBlend<T>(fac,a,b); } \
53         T PARAM_PVFN(pick)       (float* f, const T a, const T b) \
54                         { return numericalBlend<T>(f[0],a,b); }
55
56 PARAM_DEF_NUM(u8,  writeU8,    readU8);  PARAM_DEF_NUM(s8,  writeS8,    readS8);
57 PARAM_DEF_NUM(u16, writeU16,   readU16); PARAM_DEF_NUM(s16, writeS16,   readS16);
58 PARAM_DEF_NUM(u32, writeU32,   readU32); PARAM_DEF_NUM(s32, writeS32,   readS32);
59 PARAM_DEF_NUM(f32, writeF32,   readF32);
60 PARAM_DEF_SRZR(v2f, writeV2F32, readV2F32);
61 PARAM_DEF_SRZR(v3f, writeV3F32, readV3F32);
62
63 enum class ParticleTextureFlags : u8 {
64         /* each value specifies a bit in a bitmask; if the maximum value
65          * goes above 1<<7 the type of the flags field must be changed
66          * from u8, which will necessitate a protocol change! */
67
68         // the first bit indicates whether the texture is animated
69         animated = 1,
70
71         /* the next three bits indicate the blending mode of the texture
72          * blendmode is encoded by (flags |= (u8)blend << 1); retrieve with
73          * (flags & ParticleTextureFlags::blend) >> 1. note that the third
74          * bit is currently reserved for adding more blend modes in the future */
75         blend = 0x7 << 1,
76 };
77
78 /* define some shorthand so we don't have to repeat ourselves or use
79  * decltype everywhere */
80 using FlagT = std::underlying_type_t<ParticleTextureFlags>;
81
82 void ServerParticleTexture::serialize(std::ostream &os, u16 protocol_ver, bool newPropertiesOnly) const
83 {
84         /* newPropertiesOnly is used to de/serialize parameters of the legacy texture
85          * field, which are encoded separately from the texspec string */
86         FlagT flags = 0;
87         if (animated)
88                 flags |= FlagT(ParticleTextureFlags::animated);
89         if (blendmode != BlendMode::alpha)
90                 flags |= FlagT(blendmode) << 1;
91         serializeParameterValue(os, flags);
92
93         alpha.serialize(os);
94         scale.serialize(os);
95         if (!newPropertiesOnly)
96                 os << serializeString32(string);
97
98         if (animated)
99                 animation.serialize(os, protocol_ver);
100 }
101
102 void ServerParticleTexture::deSerialize(std::istream &is, u16 protocol_ver, bool newPropertiesOnly)
103 {
104         FlagT flags = 0;
105         deSerializeParameterValue(is, flags);
106
107         animated = !!(flags & FlagT(ParticleTextureFlags::animated));
108         blendmode = BlendMode((flags & FlagT(ParticleTextureFlags::blend)) >> 1);
109
110         alpha.deSerialize(is);
111         scale.deSerialize(is);
112         if (!newPropertiesOnly)
113                 string = deSerializeString32(is);
114
115         if (animated)
116                 animation.deSerialize(is, protocol_ver);
117 }
118
119 void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const
120 {
121         writeV3F32(os, pos);
122         writeV3F32(os, vel);
123         writeV3F32(os, acc);
124         writeF32(os, expirationtime);
125         writeF32(os, size);
126         writeU8(os, collisiondetection);
127         os << serializeString32(texture.string);
128         writeU8(os, vertical);
129         writeU8(os, collision_removal);
130         animation.serialize(os, protocol_ver);
131         writeU8(os, glow);
132         writeU8(os, object_collision);
133         writeU16(os, node.param0);
134         writeU8(os, node.param2);
135         writeU8(os, node_tile);
136         writeV3F32(os, drag);
137         jitter.serialize(os);
138         bounce.serialize(os);
139 }
140
141 template <typename T, T (reader)(std::istream& is)>
142 inline bool streamEndsBeforeParam(T& val, std::istream& is)
143 {
144         // This is kinda awful
145         T tmp = reader(is);
146         if (is.eof())
147                 return true;
148         val = tmp;
149         return false;
150 }
151
152 void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
153 {
154         pos                = readV3F32(is);
155         vel                = readV3F32(is);
156         acc                = readV3F32(is);
157         expirationtime     = readF32(is);
158         size               = readF32(is);
159         collisiondetection = readU8(is);
160         texture.string     = deSerializeString32(is);
161         vertical           = readU8(is);
162         collision_removal  = readU8(is);
163         animation.deSerialize(is, protocol_ver);
164         glow               = readU8(is);
165         object_collision   = readU8(is);
166
167         if (streamEndsBeforeParam<u16, readU16>(node.param0, is))
168                 return;
169         node.param2 = readU8(is);
170         node_tile   = readU8(is);
171
172         if (streamEndsBeforeParam<v3f, readV3F32>(drag, is))
173                 return;
174         jitter.deSerialize(is);
175         bounce.deSerialize(is);
176 }