1 /*
2 * Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
3 *
4 * This file is part of Arx Libertatis.
5 *
6 * Arx Libertatis is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Arx Libertatis is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
18 */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
33 <http://www.gnu.org/licenses/>.
34
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43 // Code: Cyril Meynier
44 //
45 // Copyright (c) 1999-2000 ARKANE Studios SA. All rights reserved
46
47 #include "graphics/effects/Fog.h"
48
49 #include "animation/Animation.h"
50
51 #include "core/Config.h"
52 #include "core/Core.h"
53 #include "core/GameTime.h"
54
55 #include "graphics/Math.h"
56 #include "graphics/Draw.h"
57 #include "graphics/particle/ParticleEffects.h"
58
59 #include "math/Random.h"
60
61 EERIE_3DOBJ * fogobj = NULL;
62
63 FOG_DEF fogs[MAX_FOG];
64
65 //*************************************************************************************
66 // Used to Set 3D Object Visual for Fogs
67 //*************************************************************************************
ARX_FOGS_Set_Object(EERIE_3DOBJ * _fogobj)68 void ARX_FOGS_Set_Object(EERIE_3DOBJ * _fogobj)
69 {
70 fogobj = _fogobj;
71 }
72 //*************************************************************************************
73 //*************************************************************************************
ARX_FOGS_FirstInit()74 void ARX_FOGS_FirstInit()
75 {
76 ARX_FOGS_Clear();
77 }
78 //*************************************************************************************
79 //*************************************************************************************
ARX_FOGS_Clear()80 void ARX_FOGS_Clear()
81 {
82 for (long i = 0; i < MAX_FOG; i++)
83 {
84 memset(&fogs[i], 0, sizeof(FOG_DEF));
85 }
86 }
87
ARX_FOGS_TranslateSelected(Vec3f * trans)88 void ARX_FOGS_TranslateSelected(Vec3f * trans) {
89 for(long i = 0; i < MAX_FOG; i++) {
90 if(fogs[i].selected) {
91 fogs[i].pos += *trans;
92 }
93 }
94 }
95
ARX_FOGS_UnselectAll()96 void ARX_FOGS_UnselectAll()
97 {
98 for (long i = 0; i < MAX_FOG; i++)
99 {
100 fogs[i].selected = 0;
101 }
102 }
103 //*************************************************************************************
104 //*************************************************************************************
ARX_FOGS_Select(long n)105 void ARX_FOGS_Select(long n)
106 {
107 if (fogs[n].selected) fogs[n].selected = 0;
108 else fogs[n].selected = 1;
109 }
110 //*************************************************************************************
111 //*************************************************************************************
ARX_FOGS_KillByIndex(long num)112 void ARX_FOGS_KillByIndex(long num)
113 {
114 if ((num >= 0) && (num < MAX_FOG))
115 {
116 memset(&fogs[num], 0, sizeof(FOG_DEF));
117 }
118 }
119
ARX_FOGS_KillSelected()120 void ARX_FOGS_KillSelected()
121 {
122 for (long i = 0; i < MAX_FOG; i++)
123 {
124 if (fogs[i].selected)
125 {
126 ARX_FOGS_KillByIndex(i);
127 }
128 }
129 }
130 //*************************************************************************************
131 //*************************************************************************************
ARX_FOGS_GetFree()132 long ARX_FOGS_GetFree()
133 {
134 for (long i = 0; i < MAX_FOG; i++)
135 {
136 if (!fogs[i].exist) return i;
137 }
138
139 return -1;
140 }
141 //*************************************************************************************
142 //*************************************************************************************
ARX_FOGS_Count()143 long ARX_FOGS_Count()
144 {
145 long count = 0;
146
147 for (long i = 0; i < MAX_FOG; i++)
148 {
149 if (fogs[i].exist) count++;
150 }
151
152 return count;
153 }
ARX_FOGS_TimeReset()154 void ARX_FOGS_TimeReset()
155 {
156 }
157
AddPoisonFog(Vec3f * pos,float power)158 void AddPoisonFog(Vec3f * pos, float power) {
159
160 int iDiv = 4 - config.video.levelOfDetail;
161
162 float flDiv = static_cast<float>(1 << iDiv);
163
164 arxtime.update();
165
166 long count = std::max(1l, checked_range_cast<long>(FrameDiff / flDiv));
167 while(count--) {
168
169 if(rnd() * 2000.f >= power) {
170 continue;
171 }
172
173 PARTICLE_DEF * pd = createParticle();
174 if(!pd) {
175 return;
176 }
177
178 float speed = 1.f;
179 float fval = speed * 0.2f;
180 pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
181 pd->ov = *pos + randomVec(-100.f, 100.f);
182 pd->scale = Vec3f(8.f, 8.f, 10.f);
183 pd->move = Vec3f((speed - rnd()) * fval, (speed - speed * rnd()) * (1.f / 15),
184 (speed - rnd()) * fval);
185 pd->tolive = Random::get(4500, 9000);
186 pd->tc = TC_smoke;
187 pd->siz = (80.f + rnd() * 160.f) * (1.f / 3);
188 pd->rgb = Color3f(rnd() * (1.f / 3), 1.f, rnd() * 0.1f);
189 pd->fparam = 0.001f;
190 }
191 }
192
ARX_FOGS_Render()193 void ARX_FOGS_Render() {
194
195 if(arxtime.is_paused()) {
196 return;
197 }
198
199 int iDiv = 4 - config.video.levelOfDetail;
200
201 float flDiv = static_cast<float>(1 << iDiv);
202
203 for(long i = 0; i < MAX_FOG; i++) {
204
205 if(!fogs[i].exist) {
206 continue;
207 }
208
209 long count = std::max(1l, checked_range_cast<long>(FrameDiff / flDiv));
210 while(count--) {
211
212 if(rnd() * 2000.f >= fogs[i].frequency) {
213 continue;
214 }
215
216 PARTICLE_DEF * pd = createParticle(true);
217 if(!pd) {
218 break;
219 }
220
221 pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
222 if(fogs[i].special & FOG_DIRECTIONAL) {
223 pd->ov = fogs[i].pos;
224 pd->move = fogs[i].move * (fogs[i].speed * 0.1f);
225 } else {
226 pd->ov = fogs[i].pos + randomVec(-100.f, 100.f);
227 pd->move = Vec3f::repeat(fogs[i].speed) - randomVec(0.f, 2.f);
228 pd->move *= Vec3f(fogs[i].speed * 0.2f, 1.f / 15, fogs[i].speed * 0.2f);
229 }
230 pd->scale = Vec3f::repeat(fogs[i].scale);
231 pd->tolive = fogs[i].tolive + Random::get(0, fogs[i].tolive);
232 pd->tc = TC_smoke;
233 pd->siz = (fogs[i].size + rnd() * fogs[i].size * 2.f) * (1.0f / 3);
234 pd->rgb = fogs[i].rgb;
235 pd->fparam = fogs[i].rotatespeed;
236 }
237
238 fogs[i].lastupdate = (unsigned long)(arxtime);
239 }
240 }
241
ARX_FOGS_RenderAll()242 void ARX_FOGS_RenderAll() {
243
244 Anglef angle = Anglef::ZERO;
245
246 GRenderer->SetRenderState(Renderer::AlphaBlending, false);
247
248 for (long i = 0; i < MAX_FOG; i++)
249 {
250 if (fogs[i].exist)
251 {
252 if (fogobj)
253 DrawEERIEInter(fogobj, &angle, &fogs[i].pos, NULL);
254
255 fogs[i].bboxmin = BBOXMIN;
256 fogs[i].bboxmax = BBOXMAX;
257
258 if(fogs[i].special & FOG_DIRECTIONAL) {
259 EERIEDraw3DLine(fogs[i].pos, fogs[i].pos + fogs[i].move * 50.f, Color::white);
260 }
261
262 if(fogs[i].selected) {
263 EERIEDraw2DLine(fogs[i].bboxmin.x, fogs[i].bboxmin.y, fogs[i].bboxmax.x, fogs[i].bboxmin.y, 0.01f, Color::yellow);
264 EERIEDraw2DLine(fogs[i].bboxmax.x, fogs[i].bboxmin.y, fogs[i].bboxmax.x, fogs[i].bboxmax.y, 0.01f, Color::yellow);
265 EERIEDraw2DLine(fogs[i].bboxmax.x, fogs[i].bboxmax.y, fogs[i].bboxmin.x, fogs[i].bboxmax.y, 0.01f, Color::yellow);
266 EERIEDraw2DLine(fogs[i].bboxmin.x, fogs[i].bboxmax.y, fogs[i].bboxmin.x, fogs[i].bboxmin.y, 0.01f, Color::yellow);
267 }
268 }
269 }
270 }
271