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