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/light.h"
24
25 #include "common/util.h"
26
27 namespace BladeRunner {
28
Light()29 Light::Light() {
30 _frameCount = 0;
31 _animated = 0;
32 _animationData = nullptr;
33 _animatedParameters = 0;
34 _falloffStart = 0.0f;
35 _falloffEnd = 0.0f;
36 _angleStart = 0.0f;
37 _angleEnd = 0.0f;
38 _m11ptr = nullptr;
39 _m12ptr = nullptr;
40 _m13ptr = nullptr;
41 _m14ptr = nullptr;
42 _m21ptr = nullptr;
43 _m22ptr = nullptr;
44 _m23ptr = nullptr;
45 _m24ptr = nullptr;
46 _m31ptr = nullptr;
47 _m32ptr = nullptr;
48 _m33ptr = nullptr;
49 _m34ptr = nullptr;
50 _colorRPtr = nullptr;
51 _colorGPtr = nullptr;
52 _colorBPtr = nullptr;
53 _falloffStartPtr = nullptr;
54 _falloffEndPtr = nullptr;
55 _angleStartPtr = nullptr;
56 _angleEndPtr = nullptr;
57 }
58
~Light()59 Light::~Light() {
60 if (_animationData != nullptr) {
61 delete[] _animationData;
62 }
63 }
64
read(Common::ReadStream * stream,int frameCount,int frame,int animated)65 void Light::read(Common::ReadStream *stream, int frameCount, int frame, int animated) {
66 _frameCount = frameCount;
67 _animated = animated;
68
69 int size = stream->readUint32LE();
70 size = size - 32;
71
72 char buf[20];
73 stream->read(buf, sizeof(buf));
74 _name = buf;
75
76 _animatedParameters = stream->readUint32LE();
77
78 if (_animationData != nullptr) {
79 delete[] _animationData;
80 }
81 int floatCount = size / 4;
82 _animationData = new float[floatCount];
83 for (int i = 0; i < floatCount; ++i) {
84 _animationData[i] = stream->readFloatLE();
85 }
86
87 _m11ptr = _animationData;
88 _m12ptr = _m11ptr + ((_animatedParameters & 0x1) ? frameCount : 1);
89 _m13ptr = _m12ptr + ((_animatedParameters & 0x2) ? frameCount : 1);
90 _m14ptr = _m13ptr + ((_animatedParameters & 0x4) ? frameCount : 1);
91 _m21ptr = _m14ptr + ((_animatedParameters & 0x8) ? frameCount : 1);
92 _m22ptr = _m21ptr + ((_animatedParameters & 0x10) ? frameCount : 1);
93 _m23ptr = _m22ptr + ((_animatedParameters & 0x20) ? frameCount : 1);
94 _m24ptr = _m23ptr + ((_animatedParameters & 0x40) ? frameCount : 1);
95 _m31ptr = _m24ptr + ((_animatedParameters & 0x80) ? frameCount : 1);
96 _m32ptr = _m31ptr + ((_animatedParameters & 0x100) ? frameCount : 1);
97 _m33ptr = _m32ptr + ((_animatedParameters & 0x200) ? frameCount : 1);
98 _m34ptr = _m33ptr + ((_animatedParameters & 0x400) ? frameCount : 1);
99 _colorRPtr = _m34ptr + ((_animatedParameters & 0x800) ? frameCount : 1);
100 _colorGPtr = _colorRPtr + ((_animatedParameters & 0x1000) ? frameCount : 1);
101 _colorBPtr = _colorGPtr + ((_animatedParameters & 0x2000) ? frameCount : 1);
102 _falloffStartPtr = _colorBPtr + ((_animatedParameters & 0x4000) ? frameCount : 1);
103 _falloffEndPtr = _falloffStartPtr + ((_animatedParameters & 0x8000) ? frameCount : 1);
104 _angleStartPtr = _falloffEndPtr + ((_animatedParameters & 0x10000) ? frameCount : 1);
105 _angleEndPtr = _angleStartPtr + ((_animatedParameters & 0x20000) ? frameCount : 1);
106
107 setupFrame(frame);
108 }
109
readVqa(Common::ReadStream * stream,int frameCount,int frame,int animated)110 void Light::readVqa(Common::ReadStream *stream, int frameCount, int frame, int animated) {
111 _frameCount = frameCount;
112 _animated = animated;
113
114 _animatedParameters = stream->readUint32LE();
115
116 int size = stream->readUint32LE();
117
118 if (_animationData != nullptr) {
119 delete[] _animationData;
120 }
121
122 int floatCount = size / 4;
123 _animationData = new float[floatCount];
124 for (int i = 0; i < floatCount; ++i) {
125 _animationData[i] = stream->readFloatLE();
126 }
127
128 _m11ptr = _animationData;
129 _m12ptr = _m11ptr + ((_animatedParameters & 0x1) ? frameCount : 1);
130 _m13ptr = _m12ptr + ((_animatedParameters & 0x2) ? frameCount : 1);
131 _m14ptr = _m13ptr + ((_animatedParameters & 0x4) ? frameCount : 1);
132 _m21ptr = _m14ptr + ((_animatedParameters & 0x8) ? frameCount : 1);
133 _m22ptr = _m21ptr + ((_animatedParameters & 0x10) ? frameCount : 1);
134 _m23ptr = _m22ptr + ((_animatedParameters & 0x20) ? frameCount : 1);
135 _m24ptr = _m23ptr + ((_animatedParameters & 0x40) ? frameCount : 1);
136 _m31ptr = _m24ptr + ((_animatedParameters & 0x80) ? frameCount : 1);
137 _m32ptr = _m31ptr + ((_animatedParameters & 0x100) ? frameCount : 1);
138 _m33ptr = _m32ptr + ((_animatedParameters & 0x200) ? frameCount : 1);
139 _m34ptr = _m33ptr + ((_animatedParameters & 0x400) ? frameCount : 1);
140 _colorRPtr = _m34ptr + ((_animatedParameters & 0x800) ? frameCount : 1);
141 _colorGPtr = _colorRPtr + ((_animatedParameters & 0x1000) ? frameCount : 1);
142 _colorBPtr = _colorGPtr + ((_animatedParameters & 0x2000) ? frameCount : 1);
143 _falloffStartPtr = _colorBPtr + ((_animatedParameters & 0x4000) ? frameCount : 1);
144 _falloffEndPtr = _falloffStartPtr + ((_animatedParameters & 0x8000) ? frameCount : 1);
145 _angleStartPtr = _falloffEndPtr + ((_animatedParameters & 0x10000) ? frameCount : 1);
146 _angleEndPtr = _angleStartPtr + ((_animatedParameters & 0x20000) ? frameCount : 1);
147
148 setupFrame(frame);
149 }
150
setupFrame(int frame)151 void Light::setupFrame(int frame) {
152 int offset = frame % _frameCount;
153 _matrix._m[0][0] = ((_animatedParameters & 0x1) ? _m11ptr[offset] : *_m11ptr);
154 _matrix._m[0][1] = ((_animatedParameters & 0x2) ? _m12ptr[offset] : *_m12ptr);
155 _matrix._m[0][2] = ((_animatedParameters & 0x4) ? _m13ptr[offset] : *_m13ptr);
156 _matrix._m[0][3] = ((_animatedParameters & 0x8) ? _m14ptr[offset] : *_m14ptr);
157 _matrix._m[1][0] = ((_animatedParameters & 0x10) ? _m21ptr[offset] : *_m21ptr);
158 _matrix._m[1][1] = ((_animatedParameters & 0x20) ? _m22ptr[offset] : *_m22ptr);
159 _matrix._m[1][2] = ((_animatedParameters & 0x40) ? _m23ptr[offset] : *_m23ptr);
160 _matrix._m[1][3] = ((_animatedParameters & 0x80) ? _m24ptr[offset] : *_m24ptr);
161 _matrix._m[2][0] = ((_animatedParameters & 0x100) ? _m31ptr[offset] : *_m31ptr);
162 _matrix._m[2][1] = ((_animatedParameters & 0x200) ? _m32ptr[offset] : *_m32ptr);
163 _matrix._m[2][2] = ((_animatedParameters & 0x400) ? _m33ptr[offset] : *_m33ptr);
164 _matrix._m[2][3] = ((_animatedParameters & 0x800) ? _m34ptr[offset] : *_m34ptr);
165 _color.r = ((_animatedParameters & 0x1000) ? _colorRPtr[offset] : *_colorRPtr);
166 _color.g = ((_animatedParameters & 0x2000) ? _colorGPtr[offset] : *_colorGPtr);
167 _color.b = ((_animatedParameters & 0x4000) ? _colorBPtr[offset] : *_colorBPtr);
168 _falloffStart = ((_animatedParameters & 0x8000) ? _falloffStartPtr[offset] : *_falloffStartPtr);
169 _falloffEnd = ((_animatedParameters & 0x10000) ? _falloffEndPtr[offset] : *_falloffEndPtr);
170 _angleStart = ((_animatedParameters & 0x20000) ? _angleStartPtr[offset] : *_angleStartPtr);
171 _angleEnd = ((_animatedParameters & 0x40000) ? _angleEndPtr[offset] : *_angleEndPtr);
172 }
173
calculate(Vector3 start,Vector3 end) const174 float Light::calculate(Vector3 start, Vector3 end) const {
175 return calculateFalloutCoefficient(_matrix * start, _matrix * end, _falloffStart, _falloffEnd);
176 }
177
calculateColor(Color * outColor,Vector3 position) const178 void Light::calculateColor(Color *outColor, Vector3 position) const {
179 Vector3 positionT = _matrix * position;
180 float att = attenuation(_falloffStart, _falloffEnd, positionT.length());
181 outColor->r = _color.r * att;
182 outColor->g = _color.g * att;
183 outColor->b = _color.b * att;
184 }
185
calculateFalloutCoefficient(Vector3 start,Vector3 end,float falloffStart,float falloffEnd) const186 float Light::calculateFalloutCoefficient(Vector3 start, Vector3 end, float falloffStart, float falloffEnd) const {
187 if (falloffEnd == 0.0f) {
188 return 1.0e30f;
189 }
190
191 if (falloffStart * falloffStart >= start.length() && falloffStart * falloffStart >= end.length()) {
192 return 1.0e30f;
193 }
194
195 float diff = (end - start).length();
196 float v31 = 0.0f;
197 if (diff != 0.0f) {
198 Vector3 v27 = Vector3::cross(start, (end - start));
199 v31 = v27.length() / diff;
200 }
201
202 if (v31 < falloffEnd) {
203 return 1.0f / (1.0f - (v31 / falloffEnd));
204 }
205 return 1.0e30f;
206 }
207
attenuation(float min,float max,float distance) const208 float Light::attenuation(float min, float max, float distance) const {
209 if (max == 0.0f) {
210 return 1.0f;
211 }
212 if (min < max) {
213 distance = CLIP(distance, min, max);
214 float x = (max - distance) / (max - min);
215 return x * x * (3.0f - 2.0f * x);
216 }
217 if (distance < min) {
218 return 1.0f;
219 }
220 return 0.0f;
221 }
222
calculate(Vector3 start,Vector3 end) const223 float Light1::calculate(Vector3 start, Vector3 end) const {
224 start = _matrix * start;
225 end = _matrix * end;
226
227 float v40 = 0.0f;
228 if (_falloffEnd != 0.0f) {
229 v40 = calculateFalloutCoefficient(start, end, _falloffStart, _falloffEnd);
230 }
231
232 float v41 = atan2(sqrt(start.x * start.x + start.y * start.y), -start.z);
233 float v42 = atan2(sqrt(end.x * end.x + end.y * end.y), -end.z);
234
235 float v43;
236 if ((_angleStart >= v41 && _angleStart >= v42) || (_angleEnd <= v41 && _angleEnd <= v42)) {
237 v43 = 1.0e30f;
238 } else {
239 v43 = 2.0;
240 }
241 if (v43 < v40) {
242 return v40;
243 } else {
244 return v43;
245 }
246 }
247
calculateColor(Color * outColor,Vector3 position) const248 void Light1::calculateColor(Color *outColor, Vector3 position) const {
249 Vector3 positionT = _matrix * position;
250
251 outColor->r = 0.0f;
252 outColor->g = 0.0f;
253 outColor->b = 0.0f;
254
255 if (positionT.z < 0.0f) {
256 float v12 = attenuation(_angleStart, _angleEnd, atan2(sqrt(positionT.x * positionT.x + positionT.y * positionT.y), -positionT.z));
257 float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
258
259 outColor->r = v12 * v13 * _color.r;
260 outColor->g = v12 * v13 * _color.g;
261 outColor->b = v12 * v13 * _color.b;
262 }
263 }
264
calculate(Vector3 start,Vector3 end) const265 float Light2::calculate(Vector3 start, Vector3 end) const {
266 start = _matrix * start;
267 end = _matrix * end;
268
269 float v54 = 0.0f;
270 if (_falloffEnd != 0.0f) {
271 v54 = calculateFalloutCoefficient(start, end, _falloffStart, _falloffEnd);
272 }
273
274 float v55 = atan2(fabs(start.x), -start.z);
275 float v58 = atan2(fabs(start.y), -start.z);
276 float v57 = atan2(fabs(end.x), -end.z);
277 float v56 = atan2(fabs(end.y), -end.z);
278
279 float v59;
280 if ((_angleStart >= v55 && _angleStart >= v57 && _angleStart >= v58 && _angleStart >= v56) || (_angleEnd <= v55 && _angleEnd <= v57 && _angleEnd <= v58 && _angleEnd <= v56)) {
281 v59 = 1.0e30f;
282 } else {
283 v59 = 2.0f;
284 }
285 if (v59 < v54) {
286 return v54;
287 } else {
288 return v59;
289 }
290 }
291
calculateColor(Color * outColor,Vector3 position) const292 void Light2::calculateColor(Color *outColor, Vector3 position) const {
293 Vector3 positionT = _matrix * position;
294
295 outColor->r = 0.0f;
296 outColor->g = 0.0f;
297 outColor->b = 0.0f;
298
299 if (positionT.z < 0.0f) {
300 float v11 = attenuation(_angleStart, _angleEnd, atan2(fabs(positionT.y), -positionT.z));
301 float v12 = attenuation(_angleStart, _angleEnd, atan2(fabs(positionT.x), -positionT.z));
302 float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
303
304 outColor->r = v11 * v12 * v13 * _color.r;
305 outColor->g = v11 * v12 * v13 * _color.g;
306 outColor->b = v11 * v12 * v13 * _color.b;
307 }
308 }
309
calculateColor(Color * outColor,Vector3 position) const310 void Light3::calculateColor(Color *outColor, Vector3 position) const {
311 Vector3 positionT = _matrix * position;
312
313 outColor->r = 0.0f;
314 outColor->g = 0.0f;
315 outColor->b = 0.0f;
316
317 if (positionT.z < 0.0f) {
318 float v12 = attenuation(_angleStart, _angleEnd, sqrt(positionT.x * positionT.x + positionT.y * positionT.y));
319 float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
320
321 outColor->r = v12 * v13 * _color.r;
322 outColor->g = v12 * v13 * _color.g;
323 outColor->b = v12 * v13 * _color.b;
324 }
325 }
326
calculateColor(Color * outColor,Vector3 position) const327 void Light4::calculateColor(Color *outColor, Vector3 position) const {
328 Vector3 positionT = _matrix * position;
329
330 outColor->r = 0.0f;
331 outColor->g = 0.0f;
332 outColor->b = 0.0f;
333
334 if (positionT.z < 0.0f) {
335 float v11 = attenuation(_angleStart, _angleEnd, fabs(positionT.y));
336 float v12 = attenuation(_angleStart, _angleEnd, fabs(positionT.x));
337 float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
338
339 outColor->r = v11 * v12 * v13 * _color.r;
340 outColor->g = v11 * v12 * v13 * _color.g;
341 outColor->b = v11 * v12 * v13 * _color.b;
342 }
343 }
344
calculate(Vector3 start,Vector3 end) const345 float LightAmbient::calculate(Vector3 start, Vector3 end) const {
346 return 1.0e30f;
347 }
348
calculateColor(Color * outColor,Vector3 position) const349 void LightAmbient::calculateColor(Color *outColor, Vector3 position) const {
350 outColor->r = _color.r;
351 outColor->g = _color.g;
352 outColor->b = _color.b;
353 }
354
355 } // End of namespace BladeRunner
356