1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "bladerunner/set_effects.h"
24
25 namespace BladeRunner {
26
SetEffects(BladeRunnerEngine * vm)27 SetEffects::SetEffects(BladeRunnerEngine *vm) {
28 _vm = vm;
29
30 _distanceColor.r = 1.0f;
31 _distanceColor.g = 1.0f;
32 _distanceColor.b = 1.0f;
33 _distanceCoeficient = 0.1f;
34
35 _fadeColor.r = 0.0f;
36 _fadeColor.g = 0.0f;
37 _fadeColor.b = 0.0f;
38 _fadeDensity = 0.0f;
39
40 _fogCount = 0;
41 _fogs = nullptr;
42 }
43
~SetEffects()44 SetEffects::~SetEffects() {
45 reset();
46 }
47
read(Common::ReadStream * stream,int frameCount)48 void SetEffects::read(Common::ReadStream *stream, int frameCount) {
49 _distanceCoeficient = stream->readFloatLE();
50 _distanceColor.r = stream->readFloatLE();
51 _distanceColor.g = stream->readFloatLE();
52 _distanceColor.b = stream->readFloatLE();
53
54 _fogCount = stream->readUint32LE();
55 int i;
56 for (i = 0; i < _fogCount; ++i) {
57 int type = stream->readUint32LE();
58 Fog *fog = nullptr;
59 switch (type) {
60 case 0:
61 fog = new FogSphere();
62 break;
63 case 1:
64 fog = new FogCone();
65 break;
66 case 2:
67 fog = new FogBox();
68 break;
69 default:
70 error("Unknown fog type %d", type);
71 }
72 if (fog != nullptr) {
73 fog->read(stream, frameCount);
74 fog->_next = _fogs;
75 _fogs = fog;
76 }
77 }
78 }
79
reset()80 void SetEffects::reset() {
81 Fog *nextFog;
82
83 if (!_fogs) {
84 return;
85 }
86
87 do {
88 nextFog = _fogs->_next;
89 delete _fogs;
90 _fogs = nextFog;
91 } while (nextFog);
92 }
93
setupFrame(int frame)94 void SetEffects::setupFrame(int frame) {
95 for (Fog *fog = _fogs; fog != nullptr; fog = fog->_next) {
96 fog->setupFrame(frame);
97 }
98 }
99
setFadeColor(float r,float g,float b)100 void SetEffects::setFadeColor(float r, float g, float b) {
101 _fadeColor.r = r;
102 _fadeColor.g = g;
103 _fadeColor.b = b;
104 }
105
setFadeDensity(float density)106 void SetEffects::setFadeDensity(float density) {
107 _fadeDensity = density;
108 }
109
110 /**
111 * Set fog color for fog effect named fogName.
112 * RGB arguments are percentages of red, green and blue
113 */
setFogColor(const Common::String & fogName,float r,float g,float b)114 void SetEffects::setFogColor(const Common::String &fogName, float r, float g, float b) {
115 Fog *fog = findFog(fogName);
116 if (fog == nullptr) {
117 return;
118 }
119
120 fog->_fogColor.r = r;
121 fog->_fogColor.g = g;
122 fog->_fogColor.b = b;
123 }
124
setFogDensity(const Common::String & fogName,float density)125 void SetEffects::setFogDensity(const Common::String &fogName, float density) {
126 Fog *fog = findFog(fogName);
127 if (fog == nullptr) {
128 return;
129 }
130
131 fog->_fogDensity = density;
132 }
133
calculateColor(Vector3 viewPosition,Vector3 position,float * outCoeficient,Color * outColor) const134 void SetEffects::calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor) const {
135 float distanceCoeficient = CLIP((position - viewPosition).length() * _distanceCoeficient, 0.0f, 1.0f);
136
137 *outCoeficient = 1.0f - distanceCoeficient;
138 outColor->r = _distanceColor.r * distanceCoeficient;
139 outColor->g = _distanceColor.g * distanceCoeficient;
140 outColor->b = _distanceColor.b * distanceCoeficient;
141
142 for (Fog *fog = _fogs; fog != nullptr; fog = fog->_next) {
143 float fogCoeficient = 0.0f;
144 fog->calculateCoeficient(position, viewPosition, &fogCoeficient);
145 if (fogCoeficient > 0.0f) {
146 fogCoeficient = CLIP(fog->_fogDensity * fogCoeficient, 0.0f, 1.0f);
147
148 *outCoeficient = *outCoeficient * (1.0f - fogCoeficient);
149 outColor->r = outColor->r * (1.0f - fogCoeficient) + fog->_fogColor.r * fogCoeficient;
150 outColor->g = outColor->g * (1.0f - fogCoeficient) + fog->_fogColor.g * fogCoeficient;
151 outColor->b = outColor->b * (1.0f - fogCoeficient) + fog->_fogColor.b * fogCoeficient;
152 }
153 }
154
155 *outCoeficient = *outCoeficient * (1.0f - _fadeDensity);
156 outColor->r = outColor->r * (1.0f - _fadeDensity) + _fadeColor.r * _fadeDensity;
157 outColor->g = outColor->g * (1.0f - _fadeDensity) + _fadeColor.g * _fadeDensity;
158 outColor->b = outColor->b * (1.0f - _fadeDensity) + _fadeColor.b * _fadeDensity;
159 }
160
findFog(const Common::String & fogName) const161 Fog *SetEffects::findFog(const Common::String &fogName) const {
162 if (!_fogs) {
163 return nullptr;
164 }
165
166 Fog *fog = _fogs;
167
168 while (fog != nullptr) {
169 if (fogName.compareTo(fog->_name) == 0) {
170 break;
171 }
172 fog = fog->_next;
173 }
174
175 return fog;
176 }
177
178 } // End of namespace BladeRunner
179