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