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