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 using ::android::frameworks::sensorservice::V1_0::ISensorManager;
33 using ::android::frameworks::sensorservice::V1_0::Result;
34 using ::android::hardware::sensors::V1_0::SensorInfo;
35 using ::android::hardware::sensors::V1_0::SensorType;
36 
37 // Define single-letter shortcuts for scene definition, for directly indexing
38 // mCurrentColors
39 #define G (EmulatedScene::GRASS * EmulatedScene::NUM_CHANNELS)
40 #define S (EmulatedScene::GRASS_SHADOW * EmulatedScene::NUM_CHANNELS)
41 #define H (EmulatedScene::HILL * EmulatedScene::NUM_CHANNELS)
42 #define W (EmulatedScene::WALL * EmulatedScene::NUM_CHANNELS)
43 #define R (EmulatedScene::ROOF * EmulatedScene::NUM_CHANNELS)
44 #define D (EmulatedScene::DOOR * EmulatedScene::NUM_CHANNELS)
45 #define C (EmulatedScene::CHIMNEY * EmulatedScene::NUM_CHANNELS)
46 #define I (EmulatedScene::WINDOW * EmulatedScene::NUM_CHANNELS)
47 #define U (EmulatedScene::SUN * EmulatedScene::NUM_CHANNELS)
48 #define K (EmulatedScene::SKY * EmulatedScene::NUM_CHANNELS)
49 #define M (EmulatedScene::MOON * EmulatedScene::NUM_CHANNELS)
50 
51 const uint8_t EmulatedScene::kScene[EmulatedScene::kSceneWidth *
52                                     EmulatedScene::kSceneHeight] = {
53     //      5         10        15        20
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, K, K, K, K, K, K, K, K, K, K, K, K,
56     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
57     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
58     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,  // 5
59     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
60     K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, H, H, H,
61     K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, C, C, H, H, H,
62     K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, C, C, H, H, H,
63     H, K, K, K, K, K, H, R, R, R, R, R, R, R, R, R, R, R, R, H,  // 10
64     H, K, K, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
65     H, H, H, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
66     H, H, H, K, K, H, H, H, W, W, W, W, W, W, W, W, W, W, H, H,
67     S, S, S, G, G, S, S, S, W, W, W, W, W, W, W, W, W, W, S, S,
68     S, G, G, G, G, S, S, S, W, I, I, W, D, D, W, I, I, W, S, S,  // 15
69     G, G, G, G, G, G, S, S, W, I, I, W, D, D, W, I, I, W, S, S,
70     G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
71     G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
72     G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G,
73     G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G,  // 20
74     //      5         10        15        20
75 };
76 
77 #undef G
78 #undef S
79 #undef H
80 #undef W
81 #undef R
82 #undef D
83 #undef C
84 #undef I
85 #undef U
86 #undef K
87 #undef M
88 
EmulatedScene(int sensor_width_px,int sensor_height_px,float sensor_sensitivity,int sensor_orientation,bool is_front_facing)89 EmulatedScene::EmulatedScene(int sensor_width_px, int sensor_height_px,
90                              float sensor_sensitivity, int sensor_orientation,
91                              bool is_front_facing)
92     : sensor_handle_(-1),
93       screen_rotation_(0),
94       current_scene_(scene_rot0_),
95       sensor_orientation_(sensor_orientation),
96       is_front_facing_(is_front_facing),
97       hour_(12),
98       exposure_duration_(0.033f) {
99   // Assume that sensor filters are sRGB primaries to start
100   filter_r_[0] = 3.2406f;
101   filter_r_[1] = -1.5372f;
102   filter_r_[2] = -0.4986f;
103   filter_gr_[0] = -0.9689f;
104   filter_gr_[1] = 1.8758f;
105   filter_gr_[2] = 0.0415f;
106   filter_gb_[0] = -0.9689f;
107   filter_gb_[1] = 1.8758f;
108   filter_gb_[2] = 0.0415f;
109   filter_b_[0] = 0.0557f;
110   filter_b_[1] = -0.2040f;
111   filter_b_[2] = 1.0570f;
112 
113   InitiliazeSceneRotation(!is_front_facing_);
114   Initialize(sensor_width_px, sensor_height_px, sensor_sensitivity);
115 }
116 
~EmulatedScene()117 EmulatedScene::~EmulatedScene() {
118   if (sensor_event_queue_.get() != nullptr) {
119     sensor_event_queue_->disableSensor(sensor_handle_);
120     sensor_event_queue_.clear();
121     sensor_event_queue_ = nullptr;
122   }
123 }
124 
Initialize(int sensor_width_px,int sensor_height_px,float sensor_sensitivity)125 void EmulatedScene::Initialize(int sensor_width_px, int sensor_height_px,
126                                float sensor_sensitivity) {
127   sensor_width_ = sensor_width_px;
128   sensor_height_ = sensor_height_px;
129   sensor_sensitivity_ = sensor_sensitivity;
130 
131   // Map scene to sensor pixels
132   if (sensor_width_ > sensor_height_) {
133     map_div_ = (sensor_width_ / (kSceneWidth + 1)) + 1;
134   }
135   else {
136     map_div_ = (sensor_height_ / (kSceneHeight + 1)) + 1;
137   }
138   offset_x_ = (kSceneWidth * map_div_ - sensor_width_) / 2;
139   offset_y_ = (kSceneHeight * map_div_ - sensor_height_) / 2;
140 
141 }
142 
onEvent(const Event & e)143 Return<void> EmulatedScene::SensorHandler::onEvent(const Event& e) {
144   auto scene = scene_.promote();
145   if (scene.get() == nullptr) {
146     return Void();
147   }
148 
149   if (e.sensorType == SensorType::ACCELEROMETER) {
150     // Heuristic approach for deducing the screen
151     // rotation depending on the reported
152     // accelerometer readings. We switch
153     // the screen rotation when one of the
154     // x/y axis gets close enough to the earth
155     // acceleration.
156     const uint32_t earth_accel = 9; // Switch threshold [m/s^2]
157     uint32_t x_accel = e.u.vec3.x;
158     uint32_t y_accel = e.u.vec3.y;
159     if (x_accel == earth_accel) {
160       scene->screen_rotation_ = 270;
161     } else if (x_accel == -earth_accel) {
162       scene->screen_rotation_ = 90;
163     } else if (y_accel == -earth_accel) {
164       scene->screen_rotation_ = 180;
165     } else {
166       scene->screen_rotation_ = 0;
167     }
168   } else {
169     ALOGE("%s: unexpected event received type: %d", __func__, e.sensorType);
170   }
171   return Void();
172 }
173 
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)174 void EmulatedScene::SetColorFilterXYZ(float rX, float rY, float rZ, float grX,
175                                       float grY, float grZ, float gbX, float gbY,
176                                       float gbZ, float bX, float bY, float bZ) {
177   filter_r_[0] = rX;
178   filter_r_[1] = rY;
179   filter_r_[2] = rZ;
180   filter_gr_[0] = grX;
181   filter_gr_[1] = grY;
182   filter_gr_[2] = grZ;
183   filter_gb_[0] = gbX;
184   filter_gb_[1] = gbY;
185   filter_gb_[2] = gbZ;
186   filter_b_[0] = bX;
187   filter_b_[1] = bY;
188   filter_b_[2] = bZ;
189 }
190 
SetHour(int hour)191 void EmulatedScene::SetHour(int hour) {
192   ALOGV("Hour set to: %d", hour);
193   hour_ = hour % 24;
194 }
195 
GetHour() const196 int EmulatedScene::GetHour() const {
197   return hour_;
198 }
199 
SetExposureDuration(float seconds)200 void EmulatedScene::SetExposureDuration(float seconds) {
201   exposure_duration_ = seconds;
202 }
203 
CalculateScene(nsecs_t time,int32_t handshake_divider)204 void EmulatedScene::CalculateScene(nsecs_t time, int32_t handshake_divider) {
205   // Calculate time fractions for interpolation
206   int time_idx = hour_ / kTimeStep;
207   int next_time_idx = (time_idx + 1) % (24 / kTimeStep);
208   const nsecs_t kOneHourInNsec = 1e9 * 60 * 60;
209   nsecs_t time_since_idx =
210       (hour_ - time_idx * kTimeStep) * kOneHourInNsec + time;
211   float time_frac = time_since_idx / (float)(kOneHourInNsec * kTimeStep);
212 
213   // Determine overall sunlight levels
214   float sun_lux = kSunlight[time_idx] * (1 - time_frac) +
215                   kSunlight[next_time_idx] * time_frac;
216   ALOGV("Sun lux: %f", sun_lux);
217 
218   float sun_shade_lux = sun_lux * (kDaylightShadeIllum / kDirectSunIllum);
219 
220   // Determine sun/shade illumination chromaticity
221   float current_sun_xy[2];
222   float current_shade_xy[2];
223 
224   const float *prev_sun_xy, *next_sun_xy;
225   const float *prev_shade_xy, *next_shade_xy;
226   if (kSunlight[time_idx] == kSunsetIllum ||
227       kSunlight[time_idx] == kTwilightIllum) {
228     prev_sun_xy = kSunsetXY;
229     prev_shade_xy = kSunsetXY;
230   } else {
231     prev_sun_xy = kDirectSunlightXY;
232     prev_shade_xy = kDaylightXY;
233   }
234   if (kSunlight[next_time_idx] == kSunsetIllum ||
235       kSunlight[next_time_idx] == kTwilightIllum) {
236     next_sun_xy = kSunsetXY;
237     next_shade_xy = kSunsetXY;
238   } else {
239     next_sun_xy = kDirectSunlightXY;
240     next_shade_xy = kDaylightXY;
241   }
242   current_sun_xy[0] =
243       prev_sun_xy[0] * (1 - time_frac) + next_sun_xy[0] * time_frac;
244   current_sun_xy[1] =
245       prev_sun_xy[1] * (1 - time_frac) + next_sun_xy[1] * time_frac;
246 
247   current_shade_xy[0] =
248       prev_shade_xy[0] * (1 - time_frac) + next_shade_xy[0] * time_frac;
249   current_shade_xy[1] =
250       prev_shade_xy[1] * (1 - time_frac) + next_shade_xy[1] * time_frac;
251 
252   ALOGV("Sun XY: %f, %f, Shade XY: %f, %f", current_sun_xy[0],
253         current_sun_xy[1], current_shade_xy[0], current_shade_xy[1]);
254 
255   // Converting for xyY to XYZ:
256   // X = Y / y * x
257   // Y = Y
258   // Z = Y / y * (1 - x - y);
259   float sun_xyz[3] = {sun_lux / current_sun_xy[1] * current_sun_xy[0], sun_lux,
260                       sun_lux / current_sun_xy[1] *
261                           (1 - current_sun_xy[0] - current_sun_xy[1])};
262   float sun_shade_xyz[3] = {
263       sun_shade_lux / current_shade_xy[1] * current_shade_xy[0], sun_shade_lux,
264       sun_shade_lux / current_shade_xy[1] *
265           (1 - current_shade_xy[0] - current_shade_xy[1])};
266   ALOGV("Sun XYZ: %f, %f, %f", sun_xyz[0], sun_xyz[1], sun_xyz[2]);
267   ALOGV("Sun shade XYZ: %f, %f, %f", sun_shade_xyz[0], sun_shade_xyz[1],
268         sun_shade_xyz[2]);
269 
270   // Determine moonlight levels
271   float moon_lux = kMoonlight[time_idx] * (1 - time_frac) +
272                    kMoonlight[next_time_idx] * time_frac;
273   float moonshade_lux = moon_lux * (kDaylightShadeIllum / kDirectSunIllum);
274 
275   float moon_xyz[3] = {
276       moon_lux / kMoonlightXY[1] * kMoonlightXY[0], moon_lux,
277       moon_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
278   float moon_shade_xyz[3] = {
279       moonshade_lux / kMoonlightXY[1] * kMoonlightXY[0], moonshade_lux,
280       moonshade_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
281 
282   // Determine starlight level
283   const float kClearNightXYZ[3] = {
284       kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0], kClearNightIllum,
285       kClearNightIllum / kMoonlightXY[1] *
286           (1 - kMoonlightXY[0] - kMoonlightXY[1])};
287 
288   // Calculate direct and shaded light
289   float direct_illum_xyz[3] = {
290       sun_xyz[0] + moon_xyz[0] + kClearNightXYZ[0],
291       sun_xyz[1] + moon_xyz[1] + kClearNightXYZ[1],
292       sun_xyz[2] + moon_xyz[2] + kClearNightXYZ[2],
293   };
294 
295   float shade_illum_xyz[3] = {kClearNightXYZ[0], kClearNightXYZ[1],
296                               kClearNightXYZ[2]};
297 
298   shade_illum_xyz[0] += (hour_ < kSunOverhead) ? sun_xyz[0] : sun_shade_xyz[0];
299   shade_illum_xyz[1] += (hour_ < kSunOverhead) ? sun_xyz[1] : sun_shade_xyz[1];
300   shade_illum_xyz[2] += (hour_ < kSunOverhead) ? sun_xyz[2] : sun_shade_xyz[2];
301 
302   // Moon up period covers 23->0 transition, shift for simplicity
303   int adj_hour = (hour_ + 12) % 24;
304   int adj_moon_overhead = (kMoonOverhead + 12) % 24;
305   shade_illum_xyz[0] +=
306       (adj_hour < adj_moon_overhead) ? moon_xyz[0] : moon_shade_xyz[0];
307   shade_illum_xyz[1] +=
308       (adj_hour < adj_moon_overhead) ? moon_xyz[1] : moon_shade_xyz[1];
309   shade_illum_xyz[2] +=
310       (adj_hour < adj_moon_overhead) ? moon_xyz[2] : moon_shade_xyz[2];
311 
312   ALOGV("Direct XYZ: %f, %f, %f", direct_illum_xyz[0], direct_illum_xyz[1],
313         direct_illum_xyz[2]);
314   ALOGV("Shade XYZ: %f, %f, %f", shade_illum_xyz[0], shade_illum_xyz[1],
315         shade_illum_xyz[2]);
316 
317   for (int i = 0; i < NUM_MATERIALS; i++) {
318     // Converting for xyY to XYZ:
319     // X = Y / y * x
320     // Y = Y
321     // Z = Y / y * (1 - x - y);
322     float mat_xyz[3] = {
323         kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * kMaterials_xyY[i][0],
324         kMaterials_xyY[i][2],
325         kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
326             (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])};
327 
328     if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) {
329       mat_xyz[0] *= direct_illum_xyz[0];
330       mat_xyz[1] *= direct_illum_xyz[1];
331       mat_xyz[2] *= direct_illum_xyz[2];
332     } else if (kMaterialsFlags[i] & kShadowed) {
333       mat_xyz[0] *= shade_illum_xyz[0];
334       mat_xyz[1] *= shade_illum_xyz[1];
335       mat_xyz[2] *= shade_illum_xyz[2];
336     }  // else if (kMaterialsFlags[i] * kSelfLit), do nothing
337 
338     ALOGV("Mat %d XYZ: %f, %f, %f", i, mat_xyz[0], mat_xyz[1], mat_xyz[2]);
339     float lux_to_electrons =
340         sensor_sensitivity_ * exposure_duration_ / (kAperture * kAperture);
341     current_colors_[i * NUM_CHANNELS + 0] =
342         (filter_r_[0] * mat_xyz[0] + filter_r_[1] * mat_xyz[1] +
343          filter_r_[2] * mat_xyz[2]) *
344         lux_to_electrons;
345     current_colors_[i * NUM_CHANNELS + 1] =
346         (filter_gr_[0] * mat_xyz[0] + filter_gr_[1] * mat_xyz[1] +
347          filter_gr_[2] * mat_xyz[2]) *
348         lux_to_electrons;
349     current_colors_[i * NUM_CHANNELS + 2] =
350         (filter_gb_[0] * mat_xyz[0] + filter_gb_[1] * mat_xyz[1] +
351          filter_gb_[2] * mat_xyz[2]) *
352         lux_to_electrons;
353     current_colors_[i * NUM_CHANNELS + 3] =
354         (filter_b_[0] * mat_xyz[0] + filter_b_[1] * mat_xyz[1] +
355          filter_b_[2] * mat_xyz[2]) *
356         lux_to_electrons;
357 
358     ALOGV("Color %d RGGB: %d, %d, %d, %d", i,
359           current_colors_[i * NUM_CHANNELS + 0],
360           current_colors_[i * NUM_CHANNELS + 1],
361           current_colors_[i * NUM_CHANNELS + 2],
362           current_colors_[i * NUM_CHANNELS + 3]);
363   }
364   // Shake viewpoint; horizontal and vertical sinusoids at roughly
365   // human handshake frequencies
366   handshake_x_ =
367       (kFreq1Magnitude * std::sin(kHorizShakeFreq1 * time_since_idx) +
368        kFreq2Magnitude * std::sin(kHorizShakeFreq2 * time_since_idx)) *
369       map_div_ * kShakeFraction;
370   if (handshake_divider > 0) {
371     handshake_x_ /= handshake_divider;
372   }
373 
374   handshake_y_ = (kFreq1Magnitude * std::sin(kVertShakeFreq1 * time_since_idx) +
375                   kFreq2Magnitude * std::sin(kVertShakeFreq2 * time_since_idx)) *
376                  map_div_ * kShakeFraction;
377   if (handshake_divider > 0) {
378     handshake_y_ /= handshake_divider;
379   }
380 
381   if (sensor_event_queue_.get() != nullptr) {
382     int32_t sensor_orientation = is_front_facing_ ? -sensor_orientation_ : sensor_orientation_;
383     int32_t scene_rotation = ((screen_rotation_ + 360) + sensor_orientation) % 360;
384     switch (scene_rotation) {
385       case 90:
386         current_scene_ = scene_rot90_;
387         break;
388       case 180:
389         current_scene_ = scene_rot180_;
390         break;
391       case 270:
392         current_scene_ = scene_rot270_;
393         break;
394       default:
395         current_scene_ = scene_rot0_;
396     }
397   } else {
398     current_scene_ = scene_rot0_;
399   }
400 
401   // Set starting pixel
402   SetReadoutPixel(0, 0);
403 }
404 
InitiliazeSceneRotation(bool clock_wise)405 void EmulatedScene::InitiliazeSceneRotation(bool clock_wise) {
406   memcpy(scene_rot0_, kScene, sizeof(scene_rot0_));
407 
408   size_t c = 0;
409   for (ssize_t i = kSceneHeight-1; i >= 0; i--) {
410     for (ssize_t j = kSceneWidth-1; j >= 0; j--) {
411       scene_rot180_[c++] = kScene[i*kSceneWidth + j];
412     }
413   }
414 
415   c = 0;
416   for (ssize_t i = kSceneWidth-1; i >= 0; i--) {
417     for (size_t j = 0; j < kSceneHeight; j++) {
418       if (clock_wise) {
419         scene_rot90_[c++] = kScene[j*kSceneWidth + i];
420       } else {
421         scene_rot270_[c++] = kScene[j*kSceneWidth + i];
422       }
423     }
424   }
425 
426   c = 0;
427   for (size_t i = 0; i < kSceneWidth; i++) {
428     for (ssize_t j = kSceneHeight-1; j >= 0; j--) {
429       if (clock_wise) {
430         scene_rot270_[c++] = kScene[j*kSceneWidth + i];
431       } else {
432         scene_rot90_[c++] = kScene[j*kSceneWidth + i];
433       }
434     }
435   }
436 }
437 
InitializeSensorQueue()438 void EmulatedScene::InitializeSensorQueue() {
439   if (sensor_event_queue_.get() != nullptr) {
440     return;
441   }
442 
443   sp<ISensorManager> manager = ISensorManager::getService();
444   if (manager == nullptr) {
445     ALOGE("%s: Cannot get ISensorManager", __func__);
446   } else {
447     bool sensor_found = false;
448     manager->getSensorList(
449         [&] (const auto& list, auto result) {
450         if (result != Result::OK) {
451           ALOGE("%s: Failed to retrieve sensor list!", __func__);
452         } else {
453           for (const SensorInfo& it : list) {
454             if (it.type == SensorType::ACCELEROMETER) {
455               sensor_found = true;
456               sensor_handle_ = it.sensorHandle;
457             }
458           }
459         }});
460     if (sensor_found) {
461       manager->createEventQueue(
462           new SensorHandler(this), [&](const auto& q, auto result) {
463             if (result != Result::OK) {
464               ALOGE("%s: Cannot create event queue", __func__);
465               return;
466             }
467             sensor_event_queue_ = q;
468           });
469 
470       if (sensor_event_queue_.get() != nullptr) {
471         auto res = sensor_event_queue_->enableSensor(sensor_handle_,
472             ns2us(EmulatedSensor::kSupportedFrameDurationRange[0]), 0/*maxBatchReportLatencyUs*/);
473         if (res.isOk()) {
474         } else {
475           ALOGE("%s: Failed to enable sensor", __func__);
476         }
477       } else {
478         ALOGE("%s: Failed to create event queue", __func__);
479       }
480     }
481   }
482 }
483 
SetReadoutPixel(int x,int y)484 void EmulatedScene::SetReadoutPixel(int x, int y) {
485   current_x_ = x;
486   current_y_ = y;
487   sub_x_ = (x + offset_x_ + handshake_x_) % map_div_;
488   sub_y_ = (y + offset_y_ + handshake_y_) % map_div_;
489   scene_x_ = (x + offset_x_ + handshake_x_) / map_div_;
490   scene_y_ = (y + offset_y_ + handshake_y_) / map_div_;
491   scene_idx_ = scene_y_ * kSceneWidth + scene_x_;
492   current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
493 }
494 
GetPixelElectrons()495 const uint32_t* EmulatedScene::GetPixelElectrons() {
496   const uint32_t* pixel = current_scene_material_;
497   current_x_++;
498   sub_x_++;
499   if (current_x_ >= sensor_width_) {
500     current_x_ = 0;
501     current_y_++;
502     if (current_y_ >= sensor_height_) current_y_ = 0;
503     SetReadoutPixel(current_x_, current_y_);
504   } else if (sub_x_ > map_div_) {
505     scene_idx_++;
506     scene_x_++;
507     current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
508     sub_x_ = 0;
509   }
510   return pixel;
511 }
512 
GetPixelElectronsColumn()513 const uint32_t* EmulatedScene::GetPixelElectronsColumn() {
514   const uint32_t* pixel = current_scene_material_;
515   current_y_++;
516   sub_y_++;
517   if (current_y_ >= sensor_height_) {
518     current_y_ = 0;
519     current_x_++;
520     if (current_x_ >= sensor_width_) current_x_ = 0;
521     SetReadoutPixel(current_x_, current_y_);
522   } else if (sub_y_ > map_div_) {
523     scene_idx_ += kSceneWidth;
524     scene_y_++;
525     current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
526     sub_y_ = 0;
527   }
528   return pixel;
529 }
530 
531 // Handshake model constants.
532 // Frequencies measured in a nanosecond timebase
533 const float EmulatedScene::kHorizShakeFreq1 = 2 * M_PI * 2 / 1e9;   // 2 Hz
534 const float EmulatedScene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9;  // 13 Hz
535 const float EmulatedScene::kVertShakeFreq1 = 2 * M_PI * 3 / 1e9;    // 3 Hz
536 const float EmulatedScene::kVertShakeFreq2 = 2 * M_PI * 11 / 1e9;   // 1 Hz
537 const float EmulatedScene::kFreq1Magnitude = 5;
538 const float EmulatedScene::kFreq2Magnitude = 1;
539 const float EmulatedScene::kShakeFraction =
540     0.03;  // As a fraction of a scene tile
541 
542 // Aperture of imaging lens
543 const float EmulatedScene::kAperture = 2.8;
544 
545 // Sun illumination levels through the day
546 const float EmulatedScene::kSunlight[24 / kTimeStep] = {
547     0,  // 00:00
548     0,
549     0,
550     kTwilightIllum,  // 06:00
551     kDirectSunIllum,
552     kDirectSunIllum,
553     kDirectSunIllum,  // 12:00
554     kDirectSunIllum,
555     kDirectSunIllum,
556     kSunsetIllum,  // 18:00
557     kTwilightIllum,
558     0};
559 
560 // Moon illumination levels through the day
561 const float EmulatedScene::kMoonlight[24 / kTimeStep] = {
562     kFullMoonIllum,  // 00:00
563     kFullMoonIllum,
564     0,
565     0,  // 06:00
566     0,
567     0,
568     0,  // 12:00
569     0,
570     0,
571     0,  // 18:00
572     0,
573     kFullMoonIllum};
574 
575 const int EmulatedScene::kSunOverhead = 12;
576 const int EmulatedScene::kMoonOverhead = 0;
577 
578 // Used for sun illumination levels
579 const float EmulatedScene::kDirectSunIllum = 100000;
580 const float EmulatedScene::kSunsetIllum = 400;
581 const float EmulatedScene::kTwilightIllum = 4;
582 // Used for moon illumination levels
583 const float EmulatedScene::kFullMoonIllum = 1;
584 // Other illumination levels
585 const float EmulatedScene::kDaylightShadeIllum = 20000;
586 const float EmulatedScene::kClearNightIllum = 2e-3;
587 const float EmulatedScene::kStarIllum = 2e-6;
588 const float EmulatedScene::kLivingRoomIllum = 50;
589 
590 const float EmulatedScene::kIncandescentXY[2] = {0.44757f, 0.40745f};
591 const float EmulatedScene::kDirectSunlightXY[2] = {0.34842f, 0.35161f};
592 const float EmulatedScene::kDaylightXY[2] = {0.31271f, 0.32902f};
593 const float EmulatedScene::kNoonSkyXY[2] = {0.346f, 0.359f};
594 const float EmulatedScene::kMoonlightXY[2] = {0.34842f, 0.35161f};
595 const float EmulatedScene::kSunsetXY[2] = {0.527f, 0.413f};
596 
597 const uint8_t EmulatedScene::kSelfLit = 0x01;
598 const uint8_t EmulatedScene::kShadowed = 0x02;
599 const uint8_t EmulatedScene::kSky = 0x04;
600 
601 // For non-self-lit materials, the Y component is normalized with 1=full
602 // reflectance; for self-lit materials, it's the constant illuminance in lux.
603 const float EmulatedScene::kMaterials_xyY[EmulatedScene::NUM_MATERIALS][3] = {
604     {0.3688f, 0.4501f, .1329f},                                  // GRASS
605     {0.3688f, 0.4501f, .1329f},                                  // GRASS_SHADOW
606     {0.3986f, 0.5002f, .4440f},                                  // HILL
607     {0.3262f, 0.5040f, .2297f},                                  // WALL
608     {0.4336f, 0.3787f, .1029f},                                  // ROOF
609     {0.3316f, 0.2544f, .0639f},                                  // DOOR
610     {0.3425f, 0.3577f, .0887f},                                  // CHIMNEY
611     {kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum},  // WINDOW
612     {kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum},  // SUN
613     {kNoonSkyXY[0], kNoonSkyXY[1], kDaylightShadeIllum / kDirectSunIllum},  // SKY
614     {kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum}  // MOON
615 };
616 
617 const uint8_t EmulatedScene::kMaterialsFlags[EmulatedScene::NUM_MATERIALS] = {
618     0,         kShadowed, kShadowed, kShadowed, kShadowed, kShadowed,
619     kShadowed, kSelfLit,  kSelfLit,  kSky,      kSelfLit,
620 };
621 
622 }  // namespace android
623