1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "EmulatedScene"
19 #include "EmulatedScene.h"
20 #include "EmulatedSensor.h"
21
22 #include <stdlib.h>
23 #include <utils/Log.h>
24
25 #include <cmath>
26
27 // TODO: This should probably be done host-side in OpenGL for speed and better
28 // quality
29
30 namespace android {
31
32 // Define single-letter shortcuts for scene definition, for directly indexing
33 // mCurrentColors
34 #define G (EmulatedScene::GRASS * EmulatedScene::NUM_CHANNELS)
35 #define S (EmulatedScene::GRASS_SHADOW * EmulatedScene::NUM_CHANNELS)
36 #define H (EmulatedScene::HILL * EmulatedScene::NUM_CHANNELS)
37 #define W (EmulatedScene::WALL * EmulatedScene::NUM_CHANNELS)
38 #define R (EmulatedScene::ROOF * EmulatedScene::NUM_CHANNELS)
39 #define D (EmulatedScene::DOOR * EmulatedScene::NUM_CHANNELS)
40 #define C (EmulatedScene::CHIMNEY * EmulatedScene::NUM_CHANNELS)
41 #define I (EmulatedScene::WINDOW * EmulatedScene::NUM_CHANNELS)
42 #define U (EmulatedScene::SUN * EmulatedScene::NUM_CHANNELS)
43 #define K (EmulatedScene::SKY * EmulatedScene::NUM_CHANNELS)
44 #define M (EmulatedScene::MOON * EmulatedScene::NUM_CHANNELS)
45
46 const uint8_t EmulatedScene::kScene[EmulatedScene::kSceneWidth *
47 EmulatedScene::kSceneHeight] = {
48 // 5 10 15 20
49 K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
50 K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
51 K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
52 K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
53 K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, // 5
54 K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
55 K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, H, H, H,
56 K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, C, C, H, H, H,
57 K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, C, C, H, H, H,
58 H, K, K, K, K, K, H, R, R, R, R, R, R, R, R, R, R, R, R, H, // 10
59 H, K, K, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
60 H, H, H, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
61 H, H, H, K, K, H, H, H, W, W, W, W, W, W, W, W, W, W, H, H,
62 S, S, S, G, G, S, S, S, W, W, W, W, W, W, W, W, W, W, S, S,
63 S, G, G, G, G, S, S, S, W, I, I, W, D, D, W, I, I, W, S, S, // 15
64 G, G, G, G, G, G, S, S, W, I, I, W, D, D, W, I, I, W, S, S,
65 G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
66 G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
67 G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G,
68 G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G, // 20
69 // 5 10 15 20
70 };
71
72 #undef G
73 #undef S
74 #undef H
75 #undef W
76 #undef R
77 #undef D
78 #undef C
79 #undef I
80 #undef U
81 #undef K
82 #undef M
83
EmulatedScene(int sensor_width_px,int sensor_height_px,float sensor_sensitivity,int sensor_orientation,bool is_front_facing)84 EmulatedScene::EmulatedScene(int sensor_width_px, int sensor_height_px,
85 float sensor_sensitivity, int sensor_orientation,
86 bool is_front_facing)
87 : screen_rotation_(0),
88 current_scene_(scene_rot0_),
89 sensor_orientation_(sensor_orientation),
90 is_front_facing_(is_front_facing),
91 hour_(12),
92 exposure_duration_(0.033f) {
93 // Assume that sensor filters are sRGB primaries to start
94 filter_r_[0] = 3.2406f;
95 filter_r_[1] = -1.5372f;
96 filter_r_[2] = -0.4986f;
97 filter_gr_[0] = -0.9689f;
98 filter_gr_[1] = 1.8758f;
99 filter_gr_[2] = 0.0415f;
100 filter_gb_[0] = -0.9689f;
101 filter_gb_[1] = 1.8758f;
102 filter_gb_[2] = 0.0415f;
103 filter_b_[0] = 0.0557f;
104 filter_b_[1] = -0.2040f;
105 filter_b_[2] = 1.0570f;
106
107 InitiliazeSceneRotation(!is_front_facing_);
108 Initialize(sensor_width_px, sensor_height_px, sensor_sensitivity);
109 }
110
~EmulatedScene()111 EmulatedScene::~EmulatedScene() {
112 }
113
Initialize(int sensor_width_px,int sensor_height_px,float sensor_sensitivity)114 void EmulatedScene::Initialize(int sensor_width_px, int sensor_height_px,
115 float sensor_sensitivity) {
116 sensor_width_ = sensor_width_px;
117 sensor_height_ = sensor_height_px;
118 sensor_sensitivity_ = sensor_sensitivity;
119
120 // Map scene to sensor pixels
121 if (sensor_width_ > sensor_height_) {
122 map_div_ = (sensor_width_ / (kSceneWidth + 1)) + 1;
123 }
124 else {
125 map_div_ = (sensor_height_ / (kSceneHeight + 1)) + 1;
126 }
127 offset_x_ = (kSceneWidth * map_div_ - sensor_width_) / 2;
128 offset_y_ = (kSceneHeight * map_div_ - sensor_height_) / 2;
129
130 }
131
SetColorFilterXYZ(float rX,float rY,float rZ,float grX,float grY,float grZ,float gbX,float gbY,float gbZ,float bX,float bY,float bZ)132 void EmulatedScene::SetColorFilterXYZ(float rX, float rY, float rZ, float grX,
133 float grY, float grZ, float gbX, float gbY,
134 float gbZ, float bX, float bY, float bZ) {
135 filter_r_[0] = rX;
136 filter_r_[1] = rY;
137 filter_r_[2] = rZ;
138 filter_gr_[0] = grX;
139 filter_gr_[1] = grY;
140 filter_gr_[2] = grZ;
141 filter_gb_[0] = gbX;
142 filter_gb_[1] = gbY;
143 filter_gb_[2] = gbZ;
144 filter_b_[0] = bX;
145 filter_b_[1] = bY;
146 filter_b_[2] = bZ;
147 }
148
SetHour(int hour)149 void EmulatedScene::SetHour(int hour) {
150 ALOGV("Hour set to: %d", hour);
151 hour_ = hour % 24;
152 }
153
GetHour() const154 int EmulatedScene::GetHour() const {
155 return hour_;
156 }
157
SetScreenRotation(uint32_t screen_rotation)158 void EmulatedScene::SetScreenRotation(uint32_t screen_rotation) {
159 screen_rotation_ = screen_rotation;
160 }
161
SetExposureDuration(float seconds)162 void EmulatedScene::SetExposureDuration(float seconds) {
163 exposure_duration_ = seconds;
164 }
165
SetTestPattern(bool enabled)166 void EmulatedScene::SetTestPattern(bool enabled) {
167 test_pattern_mode_ = enabled;
168 }
169
SetTestPatternData(uint32_t data[4])170 void EmulatedScene::SetTestPatternData(uint32_t data[4]) {
171 memcpy(test_pattern_data_, data, 4);
172 }
173
CalculateScene(nsecs_t time,int32_t handshake_divider)174 void EmulatedScene::CalculateScene(nsecs_t time, int32_t handshake_divider) {
175 // Calculate time fractions for interpolation
176 const nsecs_t kOneHourInNsec = 1e9 * 60 * 60;
177 #ifdef FAST_SCENE_CYCLE
178 hour_ = static_cast<int>(time * 6000 / kOneHourInNsec) % 24;
179 #endif
180 int time_idx = hour_ / kTimeStep;
181 int next_time_idx = (time_idx + 1) % (24 / kTimeStep);
182 nsecs_t time_since_idx =
183 (hour_ - time_idx * kTimeStep) * kOneHourInNsec + time;
184 float time_frac = time_since_idx / (float)(kOneHourInNsec * kTimeStep);
185
186 // Determine overall sunlight levels
187 float sun_lux = kSunlight[time_idx] * (1 - time_frac) +
188 kSunlight[next_time_idx] * time_frac;
189 ALOGV("Sun lux: %f", sun_lux);
190
191 float sun_shade_lux = sun_lux * (kDaylightShadeIllum / kDirectSunIllum);
192
193 // Determine sun/shade illumination chromaticity
194 float current_sun_xy[2];
195 float current_shade_xy[2];
196
197 const float *prev_sun_xy, *next_sun_xy;
198 const float *prev_shade_xy, *next_shade_xy;
199 if (kSunlight[time_idx] == kSunsetIllum ||
200 kSunlight[time_idx] == kTwilightIllum) {
201 prev_sun_xy = kSunsetXY;
202 prev_shade_xy = kSunsetXY;
203 } else {
204 prev_sun_xy = kDirectSunlightXY;
205 prev_shade_xy = kDaylightXY;
206 }
207 if (kSunlight[next_time_idx] == kSunsetIllum ||
208 kSunlight[next_time_idx] == kTwilightIllum) {
209 next_sun_xy = kSunsetXY;
210 next_shade_xy = kSunsetXY;
211 } else {
212 next_sun_xy = kDirectSunlightXY;
213 next_shade_xy = kDaylightXY;
214 }
215 current_sun_xy[0] =
216 prev_sun_xy[0] * (1 - time_frac) + next_sun_xy[0] * time_frac;
217 current_sun_xy[1] =
218 prev_sun_xy[1] * (1 - time_frac) + next_sun_xy[1] * time_frac;
219
220 current_shade_xy[0] =
221 prev_shade_xy[0] * (1 - time_frac) + next_shade_xy[0] * time_frac;
222 current_shade_xy[1] =
223 prev_shade_xy[1] * (1 - time_frac) + next_shade_xy[1] * time_frac;
224
225 ALOGV("Sun XY: %f, %f, Shade XY: %f, %f", current_sun_xy[0],
226 current_sun_xy[1], current_shade_xy[0], current_shade_xy[1]);
227
228 // Converting for xyY to XYZ:
229 // X = Y / y * x
230 // Y = Y
231 // Z = Y / y * (1 - x - y);
232 float sun_xyz[3] = {sun_lux / current_sun_xy[1] * current_sun_xy[0], sun_lux,
233 sun_lux / current_sun_xy[1] *
234 (1 - current_sun_xy[0] - current_sun_xy[1])};
235 float sun_shade_xyz[3] = {
236 sun_shade_lux / current_shade_xy[1] * current_shade_xy[0], sun_shade_lux,
237 sun_shade_lux / current_shade_xy[1] *
238 (1 - current_shade_xy[0] - current_shade_xy[1])};
239 ALOGV("Sun XYZ: %f, %f, %f", sun_xyz[0], sun_xyz[1], sun_xyz[2]);
240 ALOGV("Sun shade XYZ: %f, %f, %f", sun_shade_xyz[0], sun_shade_xyz[1],
241 sun_shade_xyz[2]);
242
243 // Determine moonlight levels
244 float moon_lux = kMoonlight[time_idx] * (1 - time_frac) +
245 kMoonlight[next_time_idx] * time_frac;
246 float moonshade_lux = moon_lux * (kDaylightShadeIllum / kDirectSunIllum);
247
248 float moon_xyz[3] = {
249 moon_lux / kMoonlightXY[1] * kMoonlightXY[0], moon_lux,
250 moon_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
251 float moon_shade_xyz[3] = {
252 moonshade_lux / kMoonlightXY[1] * kMoonlightXY[0], moonshade_lux,
253 moonshade_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
254
255 // Determine starlight level
256 const float kClearNightXYZ[3] = {
257 kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0], kClearNightIllum,
258 kClearNightIllum / kMoonlightXY[1] *
259 (1 - kMoonlightXY[0] - kMoonlightXY[1])};
260
261 // Calculate direct and shaded light
262 float direct_illum_xyz[3] = {
263 sun_xyz[0] + moon_xyz[0] + kClearNightXYZ[0],
264 sun_xyz[1] + moon_xyz[1] + kClearNightXYZ[1],
265 sun_xyz[2] + moon_xyz[2] + kClearNightXYZ[2],
266 };
267
268 float shade_illum_xyz[3] = {kClearNightXYZ[0], kClearNightXYZ[1],
269 kClearNightXYZ[2]};
270
271 shade_illum_xyz[0] += (hour_ < kSunOverhead) ? sun_xyz[0] : sun_shade_xyz[0];
272 shade_illum_xyz[1] += (hour_ < kSunOverhead) ? sun_xyz[1] : sun_shade_xyz[1];
273 shade_illum_xyz[2] += (hour_ < kSunOverhead) ? sun_xyz[2] : sun_shade_xyz[2];
274
275 // Moon up period covers 23->0 transition, shift for simplicity
276 int adj_hour = (hour_ + 12) % 24;
277 int adj_moon_overhead = (kMoonOverhead + 12) % 24;
278 shade_illum_xyz[0] +=
279 (adj_hour < adj_moon_overhead) ? moon_xyz[0] : moon_shade_xyz[0];
280 shade_illum_xyz[1] +=
281 (adj_hour < adj_moon_overhead) ? moon_xyz[1] : moon_shade_xyz[1];
282 shade_illum_xyz[2] +=
283 (adj_hour < adj_moon_overhead) ? moon_xyz[2] : moon_shade_xyz[2];
284
285 ALOGV("Direct XYZ: %f, %f, %f", direct_illum_xyz[0], direct_illum_xyz[1],
286 direct_illum_xyz[2]);
287 ALOGV("Shade XYZ: %f, %f, %f", shade_illum_xyz[0], shade_illum_xyz[1],
288 shade_illum_xyz[2]);
289
290 for (int i = 0; i < NUM_MATERIALS; i++) {
291 // Converting for xyY to XYZ:
292 // X = Y / y * x
293 // Y = Y
294 // Z = Y / y * (1 - x - y);
295 float mat_xyz[3] = {
296 kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * kMaterials_xyY[i][0],
297 kMaterials_xyY[i][2],
298 kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
299 (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])};
300
301 if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) {
302 mat_xyz[0] *= direct_illum_xyz[0];
303 mat_xyz[1] *= direct_illum_xyz[1];
304 mat_xyz[2] *= direct_illum_xyz[2];
305 } else if (kMaterialsFlags[i] & kShadowed) {
306 mat_xyz[0] *= shade_illum_xyz[0];
307 mat_xyz[1] *= shade_illum_xyz[1];
308 mat_xyz[2] *= shade_illum_xyz[2];
309 } // else if (kMaterialsFlags[i] * kSelfLit), do nothing
310
311 ALOGV("Mat %d XYZ: %f, %f, %f", i, mat_xyz[0], mat_xyz[1], mat_xyz[2]);
312 float lux_to_electrons =
313 sensor_sensitivity_ * exposure_duration_ / (kAperture * kAperture);
314 current_colors_[i * NUM_CHANNELS + 0] =
315 (filter_r_[0] * mat_xyz[0] + filter_r_[1] * mat_xyz[1] +
316 filter_r_[2] * mat_xyz[2]) *
317 lux_to_electrons;
318 current_colors_[i * NUM_CHANNELS + 1] =
319 (filter_gr_[0] * mat_xyz[0] + filter_gr_[1] * mat_xyz[1] +
320 filter_gr_[2] * mat_xyz[2]) *
321 lux_to_electrons;
322 current_colors_[i * NUM_CHANNELS + 2] =
323 (filter_gb_[0] * mat_xyz[0] + filter_gb_[1] * mat_xyz[1] +
324 filter_gb_[2] * mat_xyz[2]) *
325 lux_to_electrons;
326 current_colors_[i * NUM_CHANNELS + 3] =
327 (filter_b_[0] * mat_xyz[0] + filter_b_[1] * mat_xyz[1] +
328 filter_b_[2] * mat_xyz[2]) *
329 lux_to_electrons;
330
331 ALOGV("Color %d RGGB: %d, %d, %d, %d", i,
332 current_colors_[i * NUM_CHANNELS + 0],
333 current_colors_[i * NUM_CHANNELS + 1],
334 current_colors_[i * NUM_CHANNELS + 2],
335 current_colors_[i * NUM_CHANNELS + 3]);
336 }
337 // Shake viewpoint; horizontal and vertical sinusoids at roughly
338 // human handshake frequencies
339 handshake_x_ =
340 (kFreq1Magnitude * std::sin(kHorizShakeFreq1 * time_since_idx) +
341 kFreq2Magnitude * std::sin(kHorizShakeFreq2 * time_since_idx)) *
342 map_div_ * kShakeFraction;
343 if (handshake_divider > 0) {
344 handshake_x_ /= handshake_divider;
345 }
346
347 handshake_y_ = (kFreq1Magnitude * std::sin(kVertShakeFreq1 * time_since_idx) +
348 kFreq2Magnitude * std::sin(kVertShakeFreq2 * time_since_idx)) *
349 map_div_ * kShakeFraction;
350 if (handshake_divider > 0) {
351 handshake_y_ /= handshake_divider;
352 }
353
354 int32_t sensor_orientation =
355 is_front_facing_ ? -sensor_orientation_ : sensor_orientation_;
356 int32_t scene_rotation = ((screen_rotation_ + 360) + sensor_orientation) % 360;
357 switch (scene_rotation) {
358 case 90:
359 current_scene_ = scene_rot90_;
360 break;
361 case 180:
362 current_scene_ = scene_rot180_;
363 break;
364 case 270:
365 current_scene_ = scene_rot270_;
366 break;
367 default:
368 current_scene_ = scene_rot0_;
369 }
370
371 // Set starting pixel
372 SetReadoutPixel(0, 0);
373 }
374
InitiliazeSceneRotation(bool clock_wise)375 void EmulatedScene::InitiliazeSceneRotation(bool clock_wise) {
376 memcpy(scene_rot0_, kScene, sizeof(scene_rot0_));
377
378 size_t c = 0;
379 for (ssize_t i = kSceneHeight-1; i >= 0; i--) {
380 for (ssize_t j = kSceneWidth-1; j >= 0; j--) {
381 scene_rot180_[c++] = kScene[i*kSceneWidth + j];
382 }
383 }
384
385 c = 0;
386 for (ssize_t i = kSceneWidth-1; i >= 0; i--) {
387 for (size_t j = 0; j < kSceneHeight; j++) {
388 if (clock_wise) {
389 scene_rot90_[c++] = kScene[j*kSceneWidth + i];
390 } else {
391 scene_rot270_[c++] = kScene[j*kSceneWidth + i];
392 }
393 }
394 }
395
396 c = 0;
397 for (size_t i = 0; i < kSceneWidth; i++) {
398 for (ssize_t j = kSceneHeight-1; j >= 0; j--) {
399 if (clock_wise) {
400 scene_rot270_[c++] = kScene[j*kSceneWidth + i];
401 } else {
402 scene_rot90_[c++] = kScene[j*kSceneWidth + i];
403 }
404 }
405 }
406 }
407
SetReadoutPixel(int x,int y)408 void EmulatedScene::SetReadoutPixel(int x, int y) {
409 current_x_ = x;
410 current_y_ = y;
411 sub_x_ = (x + offset_x_ + handshake_x_) % map_div_;
412 sub_y_ = (y + offset_y_ + handshake_y_) % map_div_;
413 scene_x_ = (x + offset_x_ + handshake_x_) / map_div_;
414 scene_y_ = (y + offset_y_ + handshake_y_) / map_div_;
415 scene_idx_ = scene_y_ * kSceneWidth + scene_x_;
416 current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
417 }
418
GetPixelElectrons()419 const uint32_t* EmulatedScene::GetPixelElectrons() {
420 if (test_pattern_mode_) return test_pattern_data_;
421
422 const uint32_t* pixel = current_scene_material_;
423 current_x_++;
424 sub_x_++;
425 if (current_x_ >= sensor_width_) {
426 current_x_ = 0;
427 current_y_++;
428 if (current_y_ >= sensor_height_) current_y_ = 0;
429 SetReadoutPixel(current_x_, current_y_);
430 } else if (sub_x_ > map_div_) {
431 scene_idx_++;
432 scene_x_++;
433 current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
434 sub_x_ = 0;
435 }
436 return pixel;
437 }
438
GetPixelElectronsColumn()439 const uint32_t* EmulatedScene::GetPixelElectronsColumn() {
440 const uint32_t* pixel = current_scene_material_;
441 current_y_++;
442 sub_y_++;
443 if (current_y_ >= sensor_height_) {
444 current_y_ = 0;
445 current_x_++;
446 if (current_x_ >= sensor_width_) current_x_ = 0;
447 SetReadoutPixel(current_x_, current_y_);
448 } else if (sub_y_ > map_div_) {
449 scene_idx_ += kSceneWidth;
450 scene_y_++;
451 current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
452 sub_y_ = 0;
453 }
454 return pixel;
455 }
456
457 // Handshake model constants.
458 // Frequencies measured in a nanosecond timebase
459 const float EmulatedScene::kHorizShakeFreq1 = 2 * M_PI * 2 / 1e9; // 2 Hz
460 const float EmulatedScene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9; // 13 Hz
461 const float EmulatedScene::kVertShakeFreq1 = 2 * M_PI * 3 / 1e9; // 3 Hz
462 const float EmulatedScene::kVertShakeFreq2 = 2 * M_PI * 11 / 1e9; // 1 Hz
463 const float EmulatedScene::kFreq1Magnitude = 5;
464 const float EmulatedScene::kFreq2Magnitude = 1;
465 const float EmulatedScene::kShakeFraction =
466 0.03; // As a fraction of a scene tile
467
468 // Aperture of imaging lens
469 const float EmulatedScene::kAperture = 2.8;
470
471 // Sun illumination levels through the day
472 const float EmulatedScene::kSunlight[24 / kTimeStep] = {
473 0, // 00:00
474 0,
475 0,
476 kTwilightIllum, // 06:00
477 kDirectSunIllum,
478 kDirectSunIllum,
479 kDirectSunIllum, // 12:00
480 kDirectSunIllum,
481 kDirectSunIllum,
482 kSunsetIllum, // 18:00
483 kTwilightIllum,
484 0};
485
486 // Moon illumination levels through the day
487 const float EmulatedScene::kMoonlight[24 / kTimeStep] = {
488 kFullMoonIllum, // 00:00
489 kFullMoonIllum,
490 0,
491 0, // 06:00
492 0,
493 0,
494 0, // 12:00
495 0,
496 0,
497 0, // 18:00
498 0,
499 kFullMoonIllum};
500
501 const int EmulatedScene::kSunOverhead = 12;
502 const int EmulatedScene::kMoonOverhead = 0;
503
504 // Used for sun illumination levels
505 const float EmulatedScene::kDirectSunIllum = 100000;
506 const float EmulatedScene::kSunsetIllum = 400;
507 const float EmulatedScene::kTwilightIllum = 4;
508 // Used for moon illumination levels
509 const float EmulatedScene::kFullMoonIllum = 1;
510 // Other illumination levels
511 const float EmulatedScene::kDaylightShadeIllum = 20000;
512 const float EmulatedScene::kClearNightIllum = 2e-3;
513 const float EmulatedScene::kStarIllum = 2e-6;
514 const float EmulatedScene::kLivingRoomIllum = 50;
515
516 const float EmulatedScene::kIncandescentXY[2] = {0.44757f, 0.40745f};
517 const float EmulatedScene::kDirectSunlightXY[2] = {0.34842f, 0.35161f};
518 const float EmulatedScene::kDaylightXY[2] = {0.31271f, 0.32902f};
519 const float EmulatedScene::kNoonSkyXY[2] = {0.346f, 0.359f};
520 const float EmulatedScene::kMoonlightXY[2] = {0.34842f, 0.35161f};
521 const float EmulatedScene::kSunsetXY[2] = {0.527f, 0.413f};
522
523 const uint8_t EmulatedScene::kSelfLit = 0x01;
524 const uint8_t EmulatedScene::kShadowed = 0x02;
525 const uint8_t EmulatedScene::kSky = 0x04;
526
527 // For non-self-lit materials, the Y component is normalized with 1=full
528 // reflectance; for self-lit materials, it's the constant illuminance in lux.
529 const float EmulatedScene::kMaterials_xyY[EmulatedScene::NUM_MATERIALS][3] = {
530 {0.3688f, 0.4501f, .1329f}, // GRASS
531 {0.3688f, 0.4501f, .1329f}, // GRASS_SHADOW
532 {0.3986f, 0.5002f, .4440f}, // HILL
533 {0.3262f, 0.5040f, .2297f}, // WALL
534 {0.4336f, 0.3787f, .1029f}, // ROOF
535 {0.3316f, 0.2544f, .0639f}, // DOOR
536 {0.3425f, 0.3577f, .0887f}, // CHIMNEY
537 {kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum}, // WINDOW
538 {kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum}, // SUN
539 {kNoonSkyXY[0], kNoonSkyXY[1], kDaylightShadeIllum / kDirectSunIllum}, // SKY
540 {kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum} // MOON
541 };
542
543 const uint8_t EmulatedScene::kMaterialsFlags[EmulatedScene::NUM_MATERIALS] = {
544 0, kShadowed, kShadowed, kShadowed, kShadowed, kShadowed,
545 kShadowed, kSelfLit, kSelfLit, kSky, kSelfLit,
546 };
547
548 } // namespace android
549