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