| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "EmulatedScene" |
| #include "EmulatedScene.h" |
| #include "EmulatedSensor.h" |
| |
| #include <stdlib.h> |
| #include <utils/Log.h> |
| |
| #include <cmath> |
| |
| // TODO: This should probably be done host-side in OpenGL for speed and better |
| // quality |
| |
| namespace android { |
| |
| // Define single-letter shortcuts for scene definition, for directly indexing |
| // mCurrentColors |
| #define G (EmulatedScene::GRASS * EmulatedScene::NUM_CHANNELS) |
| #define S (EmulatedScene::GRASS_SHADOW * EmulatedScene::NUM_CHANNELS) |
| #define H (EmulatedScene::HILL * EmulatedScene::NUM_CHANNELS) |
| #define W (EmulatedScene::WALL * EmulatedScene::NUM_CHANNELS) |
| #define R (EmulatedScene::ROOF * EmulatedScene::NUM_CHANNELS) |
| #define D (EmulatedScene::DOOR * EmulatedScene::NUM_CHANNELS) |
| #define C (EmulatedScene::CHIMNEY * EmulatedScene::NUM_CHANNELS) |
| #define I (EmulatedScene::WINDOW * EmulatedScene::NUM_CHANNELS) |
| #define U (EmulatedScene::SUN * EmulatedScene::NUM_CHANNELS) |
| #define K (EmulatedScene::SKY * EmulatedScene::NUM_CHANNELS) |
| #define M (EmulatedScene::MOON * EmulatedScene::NUM_CHANNELS) |
| |
| const uint8_t EmulatedScene::kScene[EmulatedScene::kSceneWidth * |
| EmulatedScene::kSceneHeight] = { |
| // 5 10 15 20 |
| K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, |
| K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, |
| K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, |
| K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, |
| K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, // 5 |
| K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, |
| K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, H, H, H, |
| K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, C, C, H, H, H, |
| K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, C, C, H, H, H, |
| H, K, K, K, K, K, H, R, R, R, R, R, R, R, R, R, R, R, R, H, // 10 |
| H, K, K, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H, |
| H, H, H, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H, |
| H, H, H, K, K, H, H, H, W, W, W, W, W, W, W, W, W, W, H, H, |
| S, S, S, G, G, S, S, S, W, W, W, W, W, W, W, W, W, W, S, S, |
| S, G, G, G, G, S, S, S, W, I, I, W, D, D, W, I, I, W, S, S, // 15 |
| G, G, G, G, G, G, S, S, W, I, I, W, D, D, W, I, I, W, S, S, |
| G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G, |
| G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G, |
| G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G, |
| G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G, // 20 |
| // 5 10 15 20 |
| }; |
| |
| #undef G |
| #undef S |
| #undef H |
| #undef W |
| #undef R |
| #undef D |
| #undef C |
| #undef I |
| #undef U |
| #undef K |
| #undef M |
| |
| EmulatedScene::EmulatedScene(int sensor_width_px, int sensor_height_px, |
| float sensor_sensitivity, int sensor_orientation, |
| bool is_front_facing) |
| : screen_rotation_(0), |
| current_scene_(scene_rot0_), |
| sensor_orientation_(sensor_orientation), |
| is_front_facing_(is_front_facing), |
| hour_(12), |
| exposure_duration_(0.033f) { |
| // Assume that sensor filters are sRGB primaries to start |
| filter_r_[0] = 3.2406f; |
| filter_r_[1] = -1.5372f; |
| filter_r_[2] = -0.4986f; |
| filter_gr_[0] = -0.9689f; |
| filter_gr_[1] = 1.8758f; |
| filter_gr_[2] = 0.0415f; |
| filter_gb_[0] = -0.9689f; |
| filter_gb_[1] = 1.8758f; |
| filter_gb_[2] = 0.0415f; |
| filter_b_[0] = 0.0557f; |
| filter_b_[1] = -0.2040f; |
| filter_b_[2] = 1.0570f; |
| |
| InitiliazeSceneRotation(!is_front_facing_); |
| Initialize(sensor_width_px, sensor_height_px, sensor_sensitivity); |
| } |
| |
| EmulatedScene::~EmulatedScene() { |
| } |
| |
| void EmulatedScene::Initialize(int sensor_width_px, int sensor_height_px, |
| float sensor_sensitivity) { |
| sensor_width_ = sensor_width_px; |
| sensor_height_ = sensor_height_px; |
| sensor_sensitivity_ = sensor_sensitivity; |
| |
| // Map scene to sensor pixels |
| if (sensor_width_ > sensor_height_) { |
| map_div_ = (sensor_width_ / (kSceneWidth + 1)) + 1; |
| } |
| else { |
| map_div_ = (sensor_height_ / (kSceneHeight + 1)) + 1; |
| } |
| offset_x_ = (kSceneWidth * map_div_ - sensor_width_) / 2; |
| offset_y_ = (kSceneHeight * map_div_ - sensor_height_) / 2; |
| |
| } |
| |
| void EmulatedScene::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) { |
| filter_r_[0] = rX; |
| filter_r_[1] = rY; |
| filter_r_[2] = rZ; |
| filter_gr_[0] = grX; |
| filter_gr_[1] = grY; |
| filter_gr_[2] = grZ; |
| filter_gb_[0] = gbX; |
| filter_gb_[1] = gbY; |
| filter_gb_[2] = gbZ; |
| filter_b_[0] = bX; |
| filter_b_[1] = bY; |
| filter_b_[2] = bZ; |
| } |
| |
| void EmulatedScene::SetHour(int hour) { |
| ALOGV("Hour set to: %d", hour); |
| hour_ = hour % 24; |
| } |
| |
| int EmulatedScene::GetHour() const { |
| return hour_; |
| } |
| |
| void EmulatedScene::SetScreenRotation(uint32_t screen_rotation) { |
| screen_rotation_ = screen_rotation; |
| } |
| |
| void EmulatedScene::SetExposureDuration(float seconds) { |
| exposure_duration_ = seconds; |
| } |
| |
| void EmulatedScene::SetTestPattern(bool enabled) { |
| test_pattern_mode_ = enabled; |
| } |
| |
| void EmulatedScene::SetTestPatternData(uint32_t data[4]) { |
| memcpy(test_pattern_data_, data, 4); |
| } |
| |
| void EmulatedScene::CalculateScene(nsecs_t time, int32_t handshake_divider) { |
| // Calculate time fractions for interpolation |
| const nsecs_t kOneHourInNsec = 1e9 * 60 * 60; |
| #ifdef FAST_SCENE_CYCLE |
| hour_ = static_cast<int>(time * 6000 / kOneHourInNsec) % 24; |
| #endif |
| int time_idx = hour_ / kTimeStep; |
| int next_time_idx = (time_idx + 1) % (24 / kTimeStep); |
| nsecs_t time_since_idx = |
| (hour_ - time_idx * kTimeStep) * kOneHourInNsec + time; |
| float time_frac = time_since_idx / (float)(kOneHourInNsec * kTimeStep); |
| |
| // Determine overall sunlight levels |
| float sun_lux = kSunlight[time_idx] * (1 - time_frac) + |
| kSunlight[next_time_idx] * time_frac; |
| ALOGV("Sun lux: %f", sun_lux); |
| |
| float sun_shade_lux = sun_lux * (kDaylightShadeIllum / kDirectSunIllum); |
| |
| // Determine sun/shade illumination chromaticity |
| float current_sun_xy[2]; |
| float current_shade_xy[2]; |
| |
| const float *prev_sun_xy, *next_sun_xy; |
| const float *prev_shade_xy, *next_shade_xy; |
| if (kSunlight[time_idx] == kSunsetIllum || |
| kSunlight[time_idx] == kTwilightIllum) { |
| prev_sun_xy = kSunsetXY; |
| prev_shade_xy = kSunsetXY; |
| } else { |
| prev_sun_xy = kDirectSunlightXY; |
| prev_shade_xy = kDaylightXY; |
| } |
| if (kSunlight[next_time_idx] == kSunsetIllum || |
| kSunlight[next_time_idx] == kTwilightIllum) { |
| next_sun_xy = kSunsetXY; |
| next_shade_xy = kSunsetXY; |
| } else { |
| next_sun_xy = kDirectSunlightXY; |
| next_shade_xy = kDaylightXY; |
| } |
| current_sun_xy[0] = |
| prev_sun_xy[0] * (1 - time_frac) + next_sun_xy[0] * time_frac; |
| current_sun_xy[1] = |
| prev_sun_xy[1] * (1 - time_frac) + next_sun_xy[1] * time_frac; |
| |
| current_shade_xy[0] = |
| prev_shade_xy[0] * (1 - time_frac) + next_shade_xy[0] * time_frac; |
| current_shade_xy[1] = |
| prev_shade_xy[1] * (1 - time_frac) + next_shade_xy[1] * time_frac; |
| |
| ALOGV("Sun XY: %f, %f, Shade XY: %f, %f", current_sun_xy[0], |
| current_sun_xy[1], current_shade_xy[0], current_shade_xy[1]); |
| |
| // Converting for xyY to XYZ: |
| // X = Y / y * x |
| // Y = Y |
| // Z = Y / y * (1 - x - y); |
| float sun_xyz[3] = {sun_lux / current_sun_xy[1] * current_sun_xy[0], sun_lux, |
| sun_lux / current_sun_xy[1] * |
| (1 - current_sun_xy[0] - current_sun_xy[1])}; |
| float sun_shade_xyz[3] = { |
| sun_shade_lux / current_shade_xy[1] * current_shade_xy[0], sun_shade_lux, |
| sun_shade_lux / current_shade_xy[1] * |
| (1 - current_shade_xy[0] - current_shade_xy[1])}; |
| ALOGV("Sun XYZ: %f, %f, %f", sun_xyz[0], sun_xyz[1], sun_xyz[2]); |
| ALOGV("Sun shade XYZ: %f, %f, %f", sun_shade_xyz[0], sun_shade_xyz[1], |
| sun_shade_xyz[2]); |
| |
| // Determine moonlight levels |
| float moon_lux = kMoonlight[time_idx] * (1 - time_frac) + |
| kMoonlight[next_time_idx] * time_frac; |
| float moonshade_lux = moon_lux * (kDaylightShadeIllum / kDirectSunIllum); |
| |
| float moon_xyz[3] = { |
| moon_lux / kMoonlightXY[1] * kMoonlightXY[0], moon_lux, |
| moon_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])}; |
| float moon_shade_xyz[3] = { |
| moonshade_lux / kMoonlightXY[1] * kMoonlightXY[0], moonshade_lux, |
| moonshade_lux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])}; |
| |
| // Determine starlight level |
| const float kClearNightXYZ[3] = { |
| kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0], kClearNightIllum, |
| kClearNightIllum / kMoonlightXY[1] * |
| (1 - kMoonlightXY[0] - kMoonlightXY[1])}; |
| |
| // Calculate direct and shaded light |
| float direct_illum_xyz[3] = { |
| sun_xyz[0] + moon_xyz[0] + kClearNightXYZ[0], |
| sun_xyz[1] + moon_xyz[1] + kClearNightXYZ[1], |
| sun_xyz[2] + moon_xyz[2] + kClearNightXYZ[2], |
| }; |
| |
| float shade_illum_xyz[3] = {kClearNightXYZ[0], kClearNightXYZ[1], |
| kClearNightXYZ[2]}; |
| |
| shade_illum_xyz[0] += (hour_ < kSunOverhead) ? sun_xyz[0] : sun_shade_xyz[0]; |
| shade_illum_xyz[1] += (hour_ < kSunOverhead) ? sun_xyz[1] : sun_shade_xyz[1]; |
| shade_illum_xyz[2] += (hour_ < kSunOverhead) ? sun_xyz[2] : sun_shade_xyz[2]; |
| |
| // Moon up period covers 23->0 transition, shift for simplicity |
| int adj_hour = (hour_ + 12) % 24; |
| int adj_moon_overhead = (kMoonOverhead + 12) % 24; |
| shade_illum_xyz[0] += |
| (adj_hour < adj_moon_overhead) ? moon_xyz[0] : moon_shade_xyz[0]; |
| shade_illum_xyz[1] += |
| (adj_hour < adj_moon_overhead) ? moon_xyz[1] : moon_shade_xyz[1]; |
| shade_illum_xyz[2] += |
| (adj_hour < adj_moon_overhead) ? moon_xyz[2] : moon_shade_xyz[2]; |
| |
| ALOGV("Direct XYZ: %f, %f, %f", direct_illum_xyz[0], direct_illum_xyz[1], |
| direct_illum_xyz[2]); |
| ALOGV("Shade XYZ: %f, %f, %f", shade_illum_xyz[0], shade_illum_xyz[1], |
| shade_illum_xyz[2]); |
| |
| for (int i = 0; i < NUM_MATERIALS; i++) { |
| // Converting for xyY to XYZ: |
| // X = Y / y * x |
| // Y = Y |
| // Z = Y / y * (1 - x - y); |
| float mat_xyz[3] = { |
| kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * kMaterials_xyY[i][0], |
| kMaterials_xyY[i][2], |
| kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * |
| (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])}; |
| |
| if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) { |
| mat_xyz[0] *= direct_illum_xyz[0]; |
| mat_xyz[1] *= direct_illum_xyz[1]; |
| mat_xyz[2] *= direct_illum_xyz[2]; |
| } else if (kMaterialsFlags[i] & kShadowed) { |
| mat_xyz[0] *= shade_illum_xyz[0]; |
| mat_xyz[1] *= shade_illum_xyz[1]; |
| mat_xyz[2] *= shade_illum_xyz[2]; |
| } // else if (kMaterialsFlags[i] * kSelfLit), do nothing |
| |
| ALOGV("Mat %d XYZ: %f, %f, %f", i, mat_xyz[0], mat_xyz[1], mat_xyz[2]); |
| float lux_to_electrons = |
| sensor_sensitivity_ * exposure_duration_ / (kAperture * kAperture); |
| current_colors_[i * NUM_CHANNELS + 0] = |
| (filter_r_[0] * mat_xyz[0] + filter_r_[1] * mat_xyz[1] + |
| filter_r_[2] * mat_xyz[2]) * |
| lux_to_electrons; |
| current_colors_[i * NUM_CHANNELS + 1] = |
| (filter_gr_[0] * mat_xyz[0] + filter_gr_[1] * mat_xyz[1] + |
| filter_gr_[2] * mat_xyz[2]) * |
| lux_to_electrons; |
| current_colors_[i * NUM_CHANNELS + 2] = |
| (filter_gb_[0] * mat_xyz[0] + filter_gb_[1] * mat_xyz[1] + |
| filter_gb_[2] * mat_xyz[2]) * |
| lux_to_electrons; |
| current_colors_[i * NUM_CHANNELS + 3] = |
| (filter_b_[0] * mat_xyz[0] + filter_b_[1] * mat_xyz[1] + |
| filter_b_[2] * mat_xyz[2]) * |
| lux_to_electrons; |
| |
| ALOGV("Color %d RGGB: %d, %d, %d, %d", i, |
| current_colors_[i * NUM_CHANNELS + 0], |
| current_colors_[i * NUM_CHANNELS + 1], |
| current_colors_[i * NUM_CHANNELS + 2], |
| current_colors_[i * NUM_CHANNELS + 3]); |
| } |
| // Shake viewpoint; horizontal and vertical sinusoids at roughly |
| // human handshake frequencies |
| handshake_x_ = |
| (kFreq1Magnitude * std::sin(kHorizShakeFreq1 * time_since_idx) + |
| kFreq2Magnitude * std::sin(kHorizShakeFreq2 * time_since_idx)) * |
| map_div_ * kShakeFraction; |
| if (handshake_divider > 0) { |
| handshake_x_ /= handshake_divider; |
| } |
| |
| handshake_y_ = (kFreq1Magnitude * std::sin(kVertShakeFreq1 * time_since_idx) + |
| kFreq2Magnitude * std::sin(kVertShakeFreq2 * time_since_idx)) * |
| map_div_ * kShakeFraction; |
| if (handshake_divider > 0) { |
| handshake_y_ /= handshake_divider; |
| } |
| |
| int32_t sensor_orientation = |
| is_front_facing_ ? -sensor_orientation_ : sensor_orientation_; |
| int32_t scene_rotation = ((screen_rotation_ + 360) + sensor_orientation) % 360; |
| switch (scene_rotation) { |
| case 90: |
| current_scene_ = scene_rot90_; |
| break; |
| case 180: |
| current_scene_ = scene_rot180_; |
| break; |
| case 270: |
| current_scene_ = scene_rot270_; |
| break; |
| default: |
| current_scene_ = scene_rot0_; |
| } |
| |
| // Set starting pixel |
| SetReadoutPixel(0, 0); |
| } |
| |
| void EmulatedScene::InitiliazeSceneRotation(bool clock_wise) { |
| memcpy(scene_rot0_, kScene, sizeof(scene_rot0_)); |
| |
| size_t c = 0; |
| for (ssize_t i = kSceneHeight-1; i >= 0; i--) { |
| for (ssize_t j = kSceneWidth-1; j >= 0; j--) { |
| scene_rot180_[c++] = kScene[i*kSceneWidth + j]; |
| } |
| } |
| |
| c = 0; |
| for (ssize_t i = kSceneWidth-1; i >= 0; i--) { |
| for (size_t j = 0; j < kSceneHeight; j++) { |
| if (clock_wise) { |
| scene_rot90_[c++] = kScene[j*kSceneWidth + i]; |
| } else { |
| scene_rot270_[c++] = kScene[j*kSceneWidth + i]; |
| } |
| } |
| } |
| |
| c = 0; |
| for (size_t i = 0; i < kSceneWidth; i++) { |
| for (ssize_t j = kSceneHeight-1; j >= 0; j--) { |
| if (clock_wise) { |
| scene_rot270_[c++] = kScene[j*kSceneWidth + i]; |
| } else { |
| scene_rot90_[c++] = kScene[j*kSceneWidth + i]; |
| } |
| } |
| } |
| } |
| |
| void EmulatedScene::SetReadoutPixel(int x, int y) { |
| current_x_ = x; |
| current_y_ = y; |
| sub_x_ = (x + offset_x_ + handshake_x_) % map_div_; |
| sub_y_ = (y + offset_y_ + handshake_y_) % map_div_; |
| scene_x_ = (x + offset_x_ + handshake_x_) / map_div_; |
| scene_y_ = (y + offset_y_ + handshake_y_) / map_div_; |
| scene_idx_ = scene_y_ * kSceneWidth + scene_x_; |
| current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]); |
| } |
| |
| const uint32_t* EmulatedScene::GetPixelElectrons() { |
| if (test_pattern_mode_) return test_pattern_data_; |
| |
| const uint32_t* pixel = current_scene_material_; |
| current_x_++; |
| sub_x_++; |
| if (current_x_ >= sensor_width_) { |
| current_x_ = 0; |
| current_y_++; |
| if (current_y_ >= sensor_height_) current_y_ = 0; |
| SetReadoutPixel(current_x_, current_y_); |
| } else if (sub_x_ > map_div_) { |
| scene_idx_++; |
| scene_x_++; |
| current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]); |
| sub_x_ = 0; |
| } |
| return pixel; |
| } |
| |
| const uint32_t* EmulatedScene::GetPixelElectronsColumn() { |
| const uint32_t* pixel = current_scene_material_; |
| current_y_++; |
| sub_y_++; |
| if (current_y_ >= sensor_height_) { |
| current_y_ = 0; |
| current_x_++; |
| if (current_x_ >= sensor_width_) current_x_ = 0; |
| SetReadoutPixel(current_x_, current_y_); |
| } else if (sub_y_ > map_div_) { |
| scene_idx_ += kSceneWidth; |
| scene_y_++; |
| current_scene_material_ = &(current_colors_[current_scene_[scene_idx_]]); |
| sub_y_ = 0; |
| } |
| return pixel; |
| } |
| |
| // Handshake model constants. |
| // Frequencies measured in a nanosecond timebase |
| const float EmulatedScene::kHorizShakeFreq1 = 2 * M_PI * 2 / 1e9; // 2 Hz |
| const float EmulatedScene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9; // 13 Hz |
| const float EmulatedScene::kVertShakeFreq1 = 2 * M_PI * 3 / 1e9; // 3 Hz |
| const float EmulatedScene::kVertShakeFreq2 = 2 * M_PI * 11 / 1e9; // 1 Hz |
| const float EmulatedScene::kFreq1Magnitude = 5; |
| const float EmulatedScene::kFreq2Magnitude = 1; |
| const float EmulatedScene::kShakeFraction = |
| 0.03; // As a fraction of a scene tile |
| |
| // Aperture of imaging lens |
| const float EmulatedScene::kAperture = 2.8; |
| |
| // Sun illumination levels through the day |
| const float EmulatedScene::kSunlight[24 / kTimeStep] = { |
| 0, // 00:00 |
| 0, |
| 0, |
| kTwilightIllum, // 06:00 |
| kDirectSunIllum, |
| kDirectSunIllum, |
| kDirectSunIllum, // 12:00 |
| kDirectSunIllum, |
| kDirectSunIllum, |
| kSunsetIllum, // 18:00 |
| kTwilightIllum, |
| 0}; |
| |
| // Moon illumination levels through the day |
| const float EmulatedScene::kMoonlight[24 / kTimeStep] = { |
| kFullMoonIllum, // 00:00 |
| kFullMoonIllum, |
| 0, |
| 0, // 06:00 |
| 0, |
| 0, |
| 0, // 12:00 |
| 0, |
| 0, |
| 0, // 18:00 |
| 0, |
| kFullMoonIllum}; |
| |
| const int EmulatedScene::kSunOverhead = 12; |
| const int EmulatedScene::kMoonOverhead = 0; |
| |
| // Used for sun illumination levels |
| const float EmulatedScene::kDirectSunIllum = 100000; |
| const float EmulatedScene::kSunsetIllum = 400; |
| const float EmulatedScene::kTwilightIllum = 4; |
| // Used for moon illumination levels |
| const float EmulatedScene::kFullMoonIllum = 1; |
| // Other illumination levels |
| const float EmulatedScene::kDaylightShadeIllum = 20000; |
| const float EmulatedScene::kClearNightIllum = 2e-3; |
| const float EmulatedScene::kStarIllum = 2e-6; |
| const float EmulatedScene::kLivingRoomIllum = 50; |
| |
| const float EmulatedScene::kIncandescentXY[2] = {0.44757f, 0.40745f}; |
| const float EmulatedScene::kDirectSunlightXY[2] = {0.34842f, 0.35161f}; |
| const float EmulatedScene::kDaylightXY[2] = {0.31271f, 0.32902f}; |
| const float EmulatedScene::kNoonSkyXY[2] = {0.346f, 0.359f}; |
| const float EmulatedScene::kMoonlightXY[2] = {0.34842f, 0.35161f}; |
| const float EmulatedScene::kSunsetXY[2] = {0.527f, 0.413f}; |
| |
| const uint8_t EmulatedScene::kSelfLit = 0x01; |
| const uint8_t EmulatedScene::kShadowed = 0x02; |
| const uint8_t EmulatedScene::kSky = 0x04; |
| |
| // For non-self-lit materials, the Y component is normalized with 1=full |
| // reflectance; for self-lit materials, it's the constant illuminance in lux. |
| const float EmulatedScene::kMaterials_xyY[EmulatedScene::NUM_MATERIALS][3] = { |
| {0.3688f, 0.4501f, .1329f}, // GRASS |
| {0.3688f, 0.4501f, .1329f}, // GRASS_SHADOW |
| {0.3986f, 0.5002f, .4440f}, // HILL |
| {0.3262f, 0.5040f, .2297f}, // WALL |
| {0.4336f, 0.3787f, .1029f}, // ROOF |
| {0.3316f, 0.2544f, .0639f}, // DOOR |
| {0.3425f, 0.3577f, .0887f}, // CHIMNEY |
| {kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum}, // WINDOW |
| {kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum}, // SUN |
| {kNoonSkyXY[0], kNoonSkyXY[1], kDaylightShadeIllum / kDirectSunIllum}, // SKY |
| {kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum} // MOON |
| }; |
| |
| const uint8_t EmulatedScene::kMaterialsFlags[EmulatedScene::NUM_MATERIALS] = { |
| 0, kShadowed, kShadowed, kShadowed, kShadowed, kShadowed, |
| kShadowed, kSelfLit, kSelfLit, kSky, kSelfLit, |
| }; |
| |
| } // namespace android |