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 
SetTestPattern(bool enabled)204 void EmulatedScene::SetTestPattern(bool enabled) {
205   test_pattern_mode_ = enabled;
206 }
207 
SetTestPatternData(uint32_t data[4])208 void EmulatedScene::SetTestPatternData(uint32_t data[4]) {
209   memcpy(test_pattern_data_, data, 4);
210 }
211 
CalculateScene(nsecs_t time,int32_t handshake_divider)212 void EmulatedScene::CalculateScene(nsecs_t time, int32_t handshake_divider) {
213   // Calculate time fractions for interpolation
214   int time_idx = hour_ / kTimeStep;
215   int next_time_idx = (time_idx + 1) % (24 / kTimeStep);
216   const nsecs_t kOneHourInNsec = 1e9 * 60 * 60;
217   nsecs_t time_since_idx =
218       (hour_ - time_idx * kTimeStep) * kOneHourInNsec + time;
219   float time_frac = time_since_idx / (float)(kOneHourInNsec * kTimeStep);
220 
221   // Determine overall sunlight levels
222   float sun_lux = kSunlight[time_idx] * (1 - time_frac) +
223                   kSunlight[next_time_idx] * time_frac;
224   ALOGV("Sun lux: %f", sun_lux);
225 
226   float sun_shade_lux = sun_lux * (kDaylightShadeIllum / kDirectSunIllum);
227 
228   // Determine sun/shade illumination chromaticity
229   float current_sun_xy[2];
230   float current_shade_xy[2];
231 
232   const float *prev_sun_xy, *next_sun_xy;
233   const float *prev_shade_xy, *next_shade_xy;
234   if (kSunlight[time_idx] == kSunsetIllum ||
235       kSunlight[time_idx] == kTwilightIllum) {
236     prev_sun_xy = kSunsetXY;
237     prev_shade_xy = kSunsetXY;
238   } else {
239     prev_sun_xy = kDirectSunlightXY;
240     prev_shade_xy = kDaylightXY;
241   }
242   if (kSunlight[next_time_idx] == kSunsetIllum ||
243       kSunlight[next_time_idx] == kTwilightIllum) {
244     next_sun_xy = kSunsetXY;
245     next_shade_xy = kSunsetXY;
246   } else {
247     next_sun_xy = kDirectSunlightXY;
248     next_shade_xy = kDaylightXY;
249   }
250   current_sun_xy[0] =
251       prev_sun_xy[0] * (1 - time_frac) + next_sun_xy[0] * time_frac;
252   current_sun_xy[1] =
253       prev_sun_xy[1] * (1 - time_frac) + next_sun_xy[1] * time_frac;
254 
255   current_shade_xy[0] =
256       prev_shade_xy[0] * (1 - time_frac) + next_shade_xy[0] * time_frac;
257   current_shade_xy[1] =
258       prev_shade_xy[1] * (1 - time_frac) + next_shade_xy[1] * time_frac;
259 
260   ALOGV("Sun XY: %f, %f, Shade XY: %f, %f", current_sun_xy[0],
261         current_sun_xy[1], current_shade_xy[0], current_shade_xy[1]);
262 
263   // Converting for xyY to XYZ:
264   // X = Y / y * x
265   // Y = Y
266   // Z = Y / y * (1 - x - y);
267   float sun_xyz[3] = {sun_lux / current_sun_xy[1] * current_sun_xy[0], sun_lux,
268                       sun_lux / current_sun_xy[1] *
269                           (1 - current_sun_xy[0] - current_sun_xy[1])};
270   float sun_shade_xyz[3] = {
271       sun_shade_lux / current_shade_xy[1] * current_shade_xy[0], sun_shade_lux,
272       sun_shade_lux / current_shade_xy[1] *
273           (1 - current_shade_xy[0] - current_shade_xy[1])};
274   ALOGV("Sun XYZ: %f, %f, %f", sun_xyz[0], sun_xyz[1], sun_xyz[2]);
275   ALOGV("Sun shade XYZ: %f, %f, %f", sun_shade_xyz[0], sun_shade_xyz[1],
276         sun_shade_xyz[2]);
277 
278   // Determine moonlight levels
279   float moon_lux = kMoonlight[time_idx] * (1 - time_frac) +
280                    kMoonlight[next_time_idx] * time_frac;
281   float moonshade_lux = moon_lux * (kDaylightShadeIllum / kDirectSunIllum);
282 
283   float moon_xyz[3] = {
284       moon_lux / kMoonlightXY[1] * kMoonlightXY[0], moon_lux,
285       moon_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
286   float moon_shade_xyz[3] = {
287       moonshade_lux / kMoonlightXY[1] * kMoonlightXY[0], moonshade_lux,
288       moonshade_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
289 
290   // Determine starlight level
291   const float kClearNightXYZ[3] = {
292       kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0], kClearNightIllum,
293       kClearNightIllum / kMoonlightXY[1] *
294           (1 - kMoonlightXY[0] - kMoonlightXY[1])};
295 
296   // Calculate direct and shaded light
297   float direct_illum_xyz[3] = {
298       sun_xyz[0] + moon_xyz[0] + kClearNightXYZ[0],
299       sun_xyz[1] + moon_xyz[1] + kClearNightXYZ[1],
300       sun_xyz[2] + moon_xyz[2] + kClearNightXYZ[2],
301   };
302 
303   float shade_illum_xyz[3] = {kClearNightXYZ[0], kClearNightXYZ[1],
304                               kClearNightXYZ[2]};
305 
306   shade_illum_xyz[0] += (hour_ < kSunOverhead) ? sun_xyz[0] : sun_shade_xyz[0];
307   shade_illum_xyz[1] += (hour_ < kSunOverhead) ? sun_xyz[1] : sun_shade_xyz[1];
308   shade_illum_xyz[2] += (hour_ < kSunOverhead) ? sun_xyz[2] : sun_shade_xyz[2];
309 
310   // Moon up period covers 23->0 transition, shift for simplicity
311   int adj_hour = (hour_ + 12) % 24;
312   int adj_moon_overhead = (kMoonOverhead + 12) % 24;
313   shade_illum_xyz[0] +=
314       (adj_hour < adj_moon_overhead) ? moon_xyz[0] : moon_shade_xyz[0];
315   shade_illum_xyz[1] +=
316       (adj_hour < adj_moon_overhead) ? moon_xyz[1] : moon_shade_xyz[1];
317   shade_illum_xyz[2] +=
318       (adj_hour < adj_moon_overhead) ? moon_xyz[2] : moon_shade_xyz[2];
319 
320   ALOGV("Direct XYZ: %f, %f, %f", direct_illum_xyz[0], direct_illum_xyz[1],
321         direct_illum_xyz[2]);
322   ALOGV("Shade XYZ: %f, %f, %f", shade_illum_xyz[0], shade_illum_xyz[1],
323         shade_illum_xyz[2]);
324 
325   for (int i = 0; i < NUM_MATERIALS; i++) {
326     // Converting for xyY to XYZ:
327     // X = Y / y * x
328     // Y = Y
329     // Z = Y / y * (1 - x - y);
330     float mat_xyz[3] = {
331         kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * kMaterials_xyY[i][0],
332         kMaterials_xyY[i][2],
333         kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
334             (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])};
335 
336     if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) {
337       mat_xyz[0] *= direct_illum_xyz[0];
338       mat_xyz[1] *= direct_illum_xyz[1];
339       mat_xyz[2] *= direct_illum_xyz[2];
340     } else if (kMaterialsFlags[i] & kShadowed) {
341       mat_xyz[0] *= shade_illum_xyz[0];
342       mat_xyz[1] *= shade_illum_xyz[1];
343       mat_xyz[2] *= shade_illum_xyz[2];
344     }  // else if (kMaterialsFlags[i] * kSelfLit), do nothing
345 
346     ALOGV("Mat %d XYZ: %f, %f, %f", i, mat_xyz[0], mat_xyz[1], mat_xyz[2]);
347     float lux_to_electrons =
348         sensor_sensitivity_ * exposure_duration_ / (kAperture * kAperture);
349     current_colors_[i * NUM_CHANNELS + 0] =
350         (filter_r_[0] * mat_xyz[0] + filter_r_[1] * mat_xyz[1] +
351          filter_r_[2] * mat_xyz[2]) *
352         lux_to_electrons;
353     current_colors_[i * NUM_CHANNELS + 1] =
354         (filter_gr_[0] * mat_xyz[0] + filter_gr_[1] * mat_xyz[1] +
355          filter_gr_[2] * mat_xyz[2]) *
356         lux_to_electrons;
357     current_colors_[i * NUM_CHANNELS + 2] =
358         (filter_gb_[0] * mat_xyz[0] + filter_gb_[1] * mat_xyz[1] +
359          filter_gb_[2] * mat_xyz[2]) *
360         lux_to_electrons;
361     current_colors_[i * NUM_CHANNELS + 3] =
362         (filter_b_[0] * mat_xyz[0] + filter_b_[1] * mat_xyz[1] +
363          filter_b_[2] * mat_xyz[2]) *
364         lux_to_electrons;
365 
366     ALOGV("Color %d RGGB: %d, %d, %d, %d", i,
367           current_colors_[i * NUM_CHANNELS + 0],
368           current_colors_[i * NUM_CHANNELS + 1],
369           current_colors_[i * NUM_CHANNELS + 2],
370           current_colors_[i * NUM_CHANNELS + 3]);
371   }
372   // Shake viewpoint; horizontal and vertical sinusoids at roughly
373   // human handshake frequencies
374   handshake_x_ =
375       (kFreq1Magnitude * std::sin(kHorizShakeFreq1 * time_since_idx) +
376        kFreq2Magnitude * std::sin(kHorizShakeFreq2 * time_since_idx)) *
377       map_div_ * kShakeFraction;
378   if (handshake_divider > 0) {
379     handshake_x_ /= handshake_divider;
380   }
381 
382   handshake_y_ = (kFreq1Magnitude * std::sin(kVertShakeFreq1 * time_since_idx) +
383                   kFreq2Magnitude * std::sin(kVertShakeFreq2 * time_since_idx)) *
384                  map_div_ * kShakeFraction;
385   if (handshake_divider > 0) {
386     handshake_y_ /= handshake_divider;
387   }
388 
389   if (sensor_event_queue_.get() != nullptr) {
390     int32_t sensor_orientation = is_front_facing_ ? -sensor_orientation_ : sensor_orientation_;
391     int32_t scene_rotation = ((screen_rotation_ + 360) + sensor_orientation) % 360;
392     switch (scene_rotation) {
393       case 90:
394         current_scene_ = scene_rot90_;
395         break;
396       case 180:
397         current_scene_ = scene_rot180_;
398         break;
399       case 270:
400         current_scene_ = scene_rot270_;
401         break;
402       default:
403         current_scene_ = scene_rot0_;
404     }
405   } else {
406     current_scene_ = scene_rot0_;
407   }
408 
409   // Set starting pixel
410   SetReadoutPixel(0, 0);
411 }
412 
InitiliazeSceneRotation(bool clock_wise)413 void EmulatedScene::InitiliazeSceneRotation(bool clock_wise) {
414   memcpy(scene_rot0_, kScene, sizeof(scene_rot0_));
415 
416   size_t c = 0;
417   for (ssize_t i = kSceneHeight-1; i >= 0; i--) {
418     for (ssize_t j = kSceneWidth-1; j >= 0; j--) {
419       scene_rot180_[c++] = kScene[i*kSceneWidth + j];
420     }
421   }
422 
423   c = 0;
424   for (ssize_t i = kSceneWidth-1; i >= 0; i--) {
425     for (size_t j = 0; j < kSceneHeight; j++) {
426       if (clock_wise) {
427         scene_rot90_[c++] = kScene[j*kSceneWidth + i];
428       } else {
429         scene_rot270_[c++] = kScene[j*kSceneWidth + i];
430       }
431     }
432   }
433 
434   c = 0;
435   for (size_t i = 0; i < kSceneWidth; i++) {
436     for (ssize_t j = kSceneHeight-1; j >= 0; j--) {
437       if (clock_wise) {
438         scene_rot270_[c++] = kScene[j*kSceneWidth + i];
439       } else {
440         scene_rot90_[c++] = kScene[j*kSceneWidth + i];
441       }
442     }
443   }
444 }
445 
InitializeSensorQueue()446 void EmulatedScene::InitializeSensorQueue() {
447   if (sensor_event_queue_.get() != nullptr) {
448     return;
449   }
450 
451   sp<ISensorManager> manager = ISensorManager::getService();
452   if (manager == nullptr) {
453     ALOGE("%s: Cannot get ISensorManager", __func__);
454   } else {
455     bool sensor_found = false;
456     manager->getSensorList(
457         [&] (const auto& list, auto result) {
458         if (result != Result::OK) {
459           ALOGE("%s: Failed to retrieve sensor list!", __func__);
460         } else {
461           for (const SensorInfo& it : list) {
462             if (it.type == SensorType::ACCELEROMETER) {
463               sensor_found = true;
464               sensor_handle_ = it.sensorHandle;
465             }
466           }
467         }});
468     if (sensor_found) {
469       manager->createEventQueue(
470           new SensorHandler(this), [&](const auto& q, auto result) {
471             if (result != Result::OK) {
472               ALOGE("%s: Cannot create event queue", __func__);
473               return;
474             }
475             sensor_event_queue_ = q;
476           });
477 
478       if (sensor_event_queue_.get() != nullptr) {
479         auto res = sensor_event_queue_->enableSensor(sensor_handle_,
480             ns2us(EmulatedSensor::kSupportedFrameDurationRange[0]), 0/*maxBatchReportLatencyUs*/);
481         if (res.isOk()) {
482         } else {
483           ALOGE("%s: Failed to enable sensor", __func__);
484         }
485       } else {
486         ALOGE("%s: Failed to create event queue", __func__);
487       }
488     }
489   }
490 }
491 
SetReadoutPixel(int x,int y)492 void EmulatedScene::SetReadoutPixel(int x, int y) {
493   current_x_ = x;
494   current_y_ = y;
495   sub_x_ = (x + offset_x_ + handshake_x_) % map_div_;
496   sub_y_ = (y + offset_y_ + handshake_y_) % map_div_;
497   scene_x_ = (x + offset_x_ + handshake_x_) / map_div_;
498   scene_y_ = (y + offset_y_ + handshake_y_) / map_div_;
499   scene_idx_ = scene_y_ * kSceneWidth + scene_x_;
500   current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
501 }
502 
GetPixelElectrons()503 const uint32_t* EmulatedScene::GetPixelElectrons() {
504   if (test_pattern_mode_) return test_pattern_data_;
505 
506   const uint32_t* pixel = current_scene_material_;
507   current_x_++;
508   sub_x_++;
509   if (current_x_ >= sensor_width_) {
510     current_x_ = 0;
511     current_y_++;
512     if (current_y_ >= sensor_height_) current_y_ = 0;
513     SetReadoutPixel(current_x_, current_y_);
514   } else if (sub_x_ > map_div_) {
515     scene_idx_++;
516     scene_x_++;
517     current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
518     sub_x_ = 0;
519   }
520   return pixel;
521 }
522 
GetPixelElectronsColumn()523 const uint32_t* EmulatedScene::GetPixelElectronsColumn() {
524   const uint32_t* pixel = current_scene_material_;
525   current_y_++;
526   sub_y_++;
527   if (current_y_ >= sensor_height_) {
528     current_y_ = 0;
529     current_x_++;
530     if (current_x_ >= sensor_width_) current_x_ = 0;
531     SetReadoutPixel(current_x_, current_y_);
532   } else if (sub_y_ > map_div_) {
533     scene_idx_ += kSceneWidth;
534     scene_y_++;
535     current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]);
536     sub_y_ = 0;
537   }
538   return pixel;
539 }
540 
541 // Handshake model constants.
542 // Frequencies measured in a nanosecond timebase
543 const float EmulatedScene::kHorizShakeFreq1 = 2 * M_PI * 2 / 1e9;   // 2 Hz
544 const float EmulatedScene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9;  // 13 Hz
545 const float EmulatedScene::kVertShakeFreq1 = 2 * M_PI * 3 / 1e9;    // 3 Hz
546 const float EmulatedScene::kVertShakeFreq2 = 2 * M_PI * 11 / 1e9;   // 1 Hz
547 const float EmulatedScene::kFreq1Magnitude = 5;
548 const float EmulatedScene::kFreq2Magnitude = 1;
549 const float EmulatedScene::kShakeFraction =
550     0.03;  // As a fraction of a scene tile
551 
552 // Aperture of imaging lens
553 const float EmulatedScene::kAperture = 2.8;
554 
555 // Sun illumination levels through the day
556 const float EmulatedScene::kSunlight[24 / kTimeStep] = {
557     0,  // 00:00
558     0,
559     0,
560     kTwilightIllum,  // 06:00
561     kDirectSunIllum,
562     kDirectSunIllum,
563     kDirectSunIllum,  // 12:00
564     kDirectSunIllum,
565     kDirectSunIllum,
566     kSunsetIllum,  // 18:00
567     kTwilightIllum,
568     0};
569 
570 // Moon illumination levels through the day
571 const float EmulatedScene::kMoonlight[24 / kTimeStep] = {
572     kFullMoonIllum,  // 00:00
573     kFullMoonIllum,
574     0,
575     0,  // 06:00
576     0,
577     0,
578     0,  // 12:00
579     0,
580     0,
581     0,  // 18:00
582     0,
583     kFullMoonIllum};
584 
585 const int EmulatedScene::kSunOverhead = 12;
586 const int EmulatedScene::kMoonOverhead = 0;
587 
588 // Used for sun illumination levels
589 const float EmulatedScene::kDirectSunIllum = 100000;
590 const float EmulatedScene::kSunsetIllum = 400;
591 const float EmulatedScene::kTwilightIllum = 4;
592 // Used for moon illumination levels
593 const float EmulatedScene::kFullMoonIllum = 1;
594 // Other illumination levels
595 const float EmulatedScene::kDaylightShadeIllum = 20000;
596 const float EmulatedScene::kClearNightIllum = 2e-3;
597 const float EmulatedScene::kStarIllum = 2e-6;
598 const float EmulatedScene::kLivingRoomIllum = 50;
599 
600 const float EmulatedScene::kIncandescentXY[2] = {0.44757f, 0.40745f};
601 const float EmulatedScene::kDirectSunlightXY[2] = {0.34842f, 0.35161f};
602 const float EmulatedScene::kDaylightXY[2] = {0.31271f, 0.32902f};
603 const float EmulatedScene::kNoonSkyXY[2] = {0.346f, 0.359f};
604 const float EmulatedScene::kMoonlightXY[2] = {0.34842f, 0.35161f};
605 const float EmulatedScene::kSunsetXY[2] = {0.527f, 0.413f};
606 
607 const uint8_t EmulatedScene::kSelfLit = 0x01;
608 const uint8_t EmulatedScene::kShadowed = 0x02;
609 const uint8_t EmulatedScene::kSky = 0x04;
610 
611 // For non-self-lit materials, the Y component is normalized with 1=full
612 // reflectance; for self-lit materials, it's the constant illuminance in lux.
613 const float EmulatedScene::kMaterials_xyY[EmulatedScene::NUM_MATERIALS][3] = {
614     {0.3688f, 0.4501f, .1329f},                                  // GRASS
615     {0.3688f, 0.4501f, .1329f},                                  // GRASS_SHADOW
616     {0.3986f, 0.5002f, .4440f},                                  // HILL
617     {0.3262f, 0.5040f, .2297f},                                  // WALL
618     {0.4336f, 0.3787f, .1029f},                                  // ROOF
619     {0.3316f, 0.2544f, .0639f},                                  // DOOR
620     {0.3425f, 0.3577f, .0887f},                                  // CHIMNEY
621     {kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum},  // WINDOW
622     {kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum},  // SUN
623     {kNoonSkyXY[0], kNoonSkyXY[1], kDaylightShadeIllum / kDirectSunIllum},  // SKY
624     {kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum}  // MOON
625 };
626 
627 const uint8_t EmulatedScene::kMaterialsFlags[EmulatedScene::NUM_MATERIALS] = {
628     0,         kShadowed, kShadowed, kShadowed, kShadowed, kShadowed,
629     kShadowed, kSelfLit,  kSelfLit,  kSky,      kSelfLit,
630 };
631 
632 }  // namespace android
633