engine: reject mbf21 and shit24 wads. there is no way to know if it is safe to ignore...
[k8vavoom.git] / source / textures / r_tex_warp.cpp
blob5b8f7c32599512210d138b48c910293edafc48d4
1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 Ketmar Dark
12 //**
13 //** This program is free software: you can redistribute it and/or modify
14 //** it under the terms of the GNU General Public License as published by
15 //** the Free Software Foundation, version 3 of the License ONLY.
16 //**
17 //** This program is distributed in the hope that it will be useful,
18 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 //** GNU General Public License for more details.
21 //**
22 //** You should have received a copy of the GNU General Public License
23 //** along with this program. If not, see <http://www.gnu.org/licenses/>.
24 //**
25 //**************************************************************************
26 #include "../gamedefs.h"
27 #include "r_tex.h"
30 //==========================================================================
32 // VWarpTexture::VWarpTexture
34 //==========================================================================
35 VWarpTexture::VWarpTexture (VTexture *ASrcTex, float aspeed)
36 : VTexture()
37 , SrcTex(ASrcTex)
38 , GenTime(0)
39 , Speed(aspeed)
40 , WarpXScale(1.0f)
41 , WarpYScale(1.0f)
42 , XSin1(nullptr)
43 , XSin2(nullptr)
44 , YSin1(nullptr)
45 , YSin2(nullptr)
47 Width = SrcTex->GetWidth();
48 Height = SrcTex->GetHeight();
49 SOffset = SrcTex->SOffset;
50 TOffset = SrcTex->TOffset;
51 SScale = SrcTex->SScale;
52 TScale = SrcTex->TScale;
53 WarpType = 1;
54 if (Speed < 1) Speed = 1; else if (Speed > 16) Speed = 16;
55 mFormat = mOrigFormat = (SrcTex ? SrcTex->Format : TEXFMT_RGBA);
59 //==========================================================================
61 // VWarpTexture::~VWarpTexture
63 //==========================================================================
64 VWarpTexture::~VWarpTexture () {
65 if (Pixels) {
66 delete[] Pixels;
67 Pixels = nullptr;
69 if (SrcTex) {
70 delete SrcTex;
71 SrcTex = nullptr;
73 if (XSin1) {
74 delete[] XSin1;
75 XSin1 = nullptr;
77 if (XSin2) {
78 delete[] XSin2;
79 XSin2 = nullptr;
81 if (YSin1) {
82 delete[] YSin1;
83 YSin1 = nullptr;
85 if (YSin2) {
86 delete[] YSin2;
87 YSin2 = nullptr;
92 //==========================================================================
94 // VWarpTexture::IsDynamicTexture
96 //==========================================================================
97 bool VWarpTexture::IsDynamicTexture () const noexcept {
98 return true;
102 //==========================================================================
104 // VWarpTexture::SetFrontSkyLayer
106 //==========================================================================
107 void VWarpTexture::SetFrontSkyLayer () {
108 SrcTex->SetFrontSkyLayer();
112 //==========================================================================
114 // VWarpTexture::CheckModified
116 // returns 0 if not, positive if only data need to be updated, or
117 // negative to recreate texture
119 //==========================================================================
120 int VWarpTexture::CheckModified () {
121 return (GenTime != GTextureManager.Time*Speed);
125 //==========================================================================
127 // VWarpTexture::GetPixels
129 //==========================================================================
130 vuint8 *VWarpTexture::GetPixels () {
131 if (Pixels && GenTime == GTextureManager.Time*Speed) return Pixels;
133 const vuint8 *SrcPixels = SrcTex->GetPixels();
134 mFormat = mOrigFormat = SrcTex->Format;
135 transFlags = SrcTex->transFlags;
137 GenTime = GTextureManager.Time*Speed;
138 Pixels8BitValid = false;
139 Pixels8BitAValid = false;
141 if (!XSin1) {
142 XSin1 = new float[Width];
143 YSin1 = new float[Height];
146 // precalculate sine values
147 for (int x = 0; x < Width; ++x) {
148 XSin1[x] = msin(GenTime*44+x/WarpXScale*5.625f+95.625f)*8*WarpYScale+8*WarpYScale*Height;
150 for (int y = 0; y < Height; ++y) {
151 YSin1[y] = msin(GenTime*50+y/WarpYScale*5.625f)*8*WarpXScale+8*WarpXScale*Width;
154 if (mFormat == TEXFMT_8 || mFormat == TEXFMT_8Pal) {
155 if (!Pixels) Pixels = new vuint8[Width*Height];
156 vuint8 *Dst = Pixels;
157 for (int y = 0; y < Height; ++y) {
158 for (int x = 0; x < Width; ++x) {
159 if (!(*Dst++ = SrcPixels[(((int)YSin1[y]+x)%Width)+(((int)XSin1[x]+y)%Height)*Width])) transFlags |= FlagTransparent;
160 else transFlags |= FlagHasSolidPixel;
163 } else {
164 if (!Pixels) Pixels = new vuint8[Width*Height*4];
165 vuint32 *Dst = (vuint32 *)Pixels;
166 for (int y = 0; y < Height; ++y) {
167 for (int x = 0; x < Width; ++x, ++Dst) {
168 *Dst = ((vuint32 *)SrcPixels)[(((int)YSin1[y]+x)%Width)+(((int)XSin1[x]+y)%Height)*Width];
169 const vuint8 a8 = (((*Dst)>>24)&0xffu);
170 if (a8 != 0xffu) transFlags |= (a8 ? FlagTranslucent : FlagTransparent);
171 else transFlags |= FlagHasSolidPixel;
176 return Pixels;
180 //==========================================================================
182 // VWarpTexture::GetPalette
184 //==========================================================================
185 rgba_t *VWarpTexture::GetPalette () {
186 return SrcTex->GetPalette();
190 //==========================================================================
192 // VWarpTexture::GetHighResolutionTexture
194 //==========================================================================
195 VTexture *VWarpTexture::GetHighResolutionTexture () {
196 //if (!r_hirestex) return nullptr;
197 // if high resolution texture is already created, then just return it
198 if (HiResTexture) return HiResTexture;
200 VTexture *SrcTex = VTexture::GetHighResolutionTexture();
201 if (!SrcTex) return nullptr;
203 VWarpTexture *NewTex;
204 if (WarpType == 1) NewTex = new VWarpTexture(SrcTex); else NewTex = new VWarp2Texture(SrcTex);
205 NewTex->Name = Name;
206 NewTex->Type = Type;
207 NewTex->WarpXScale = NewTex->GetWidth()/GetWidth();
208 NewTex->WarpYScale = NewTex->GetHeight()/GetHeight();
209 HiResTexture = NewTex;
210 return HiResTexture;
214 //==========================================================================
216 // VWarp2Texture::VWarp2Texture
218 //==========================================================================
219 VWarp2Texture::VWarp2Texture (VTexture *ASrcTex, float aspeed)
220 : VWarpTexture(ASrcTex, aspeed)
222 WarpType = 2;
226 //==========================================================================
228 // VWarp2Texture::GetPixels
230 //==========================================================================
231 vuint8 *VWarp2Texture::GetPixels () {
232 if (Pixels && GenTime == GTextureManager.Time*Speed) return Pixels;
233 Pixels8BitValid = false;
234 Pixels8BitAValid = false;
236 const vuint8 *SrcPixels = SrcTex->GetPixels();
237 mFormat = mOrigFormat = SrcTex->Format;
238 transFlags = SrcTex->transFlags;
240 GenTime = GTextureManager.Time*Speed;
242 if (!XSin1) {
243 XSin1 = new float[Height];
244 XSin2 = new float[Width];
245 YSin1 = new float[Height];
246 YSin2 = new float[Width];
249 // precalculate sine values
250 for (int y = 0; y < Height; ++y) {
251 XSin1[y] = msin(y/WarpYScale*5.625f+GenTime*313.895f+39.55f)*2*WarpXScale;
252 YSin1[y] = y+(2*Height+msin(y/WarpYScale*5.625f+GenTime*118.337f+30.76f)*2)*WarpYScale;
254 for (int x = 0; x < Width; ++x) {
255 XSin2[x] = x+(2*Width+msin(x/WarpXScale*11.25f+GenTime*251.116f+13.18f)*2)*WarpXScale;
256 YSin2[x] = msin(x/WarpXScale*11.25f+GenTime*251.116f+52.73f)*2*WarpYScale;
259 if (mFormat == TEXFMT_8 || mFormat == TEXFMT_8Pal) {
260 if (!Pixels) Pixels = new vuint8[Width*Height];
261 vuint8 *dest = Pixels;
262 for (int y = 0; y < Height; ++y) {
263 for (int x = 0; x < Width; ++x) {
264 *dest++ = SrcPixels[((int)(XSin1[y]+XSin2[x])%Width)+((int)(YSin1[y]+YSin2[x])%Height)*Width];
267 } else {
268 if (!Pixels) Pixels = new vuint8[Width*Height*4];
269 vuint32 *dest = (vuint32 *)Pixels;
270 for (int y = 0; y < Height; ++y) {
271 for (int x = 0; x < Width; ++x) {
272 int Idx = ((int)(XSin1[y]+XSin2[x])%Width)*4+((int)(YSin1[y]+YSin2[x])%Height)*Width*4;
273 *dest++ = *(vuint32 *)(SrcPixels+Idx);
278 return Pixels;
282 //==========================================================================
284 // VWarpTexture::ReleasePixels
286 //==========================================================================
287 void VWarpTexture::ReleasePixels () {
288 if (InReleasingPixels()) return; // already released
289 if (PixelsReleased()) return; // safeguard
290 VTexture::ReleasePixels();
291 ReleasePixelsLock rlock(this);
292 if (SrcTex) SrcTex->ReleasePixels();