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 "EmulatedCamera_Scene"
19 #include "Scene.h"
20 #include <stdlib.h>
21 #include <utils/Log.h>
22 #include <cmath>
23 
24 // TODO: This should probably be done host-side in OpenGL for speed and better
25 // quality
26 
27 namespace android {
28 
29 // Define single-letter shortcuts for scene definition, for directly indexing
30 // mCurrentColors
31 #define G (Scene::GRASS * Scene::NUM_CHANNELS)
32 #define S (Scene::GRASS_SHADOW * Scene::NUM_CHANNELS)
33 #define H (Scene::HILL * Scene::NUM_CHANNELS)
34 #define W (Scene::WALL * Scene::NUM_CHANNELS)
35 #define R (Scene::ROOF * Scene::NUM_CHANNELS)
36 #define D (Scene::DOOR * Scene::NUM_CHANNELS)
37 #define C (Scene::CHIMNEY * Scene::NUM_CHANNELS)
38 #define I (Scene::WINDOW * Scene::NUM_CHANNELS)
39 #define U (Scene::SUN * Scene::NUM_CHANNELS)
40 #define K (Scene::SKY * Scene::NUM_CHANNELS)
41 #define M (Scene::MOON * Scene::NUM_CHANNELS)
42 
43 const int Scene::kSceneWidth = 20;
44 const int Scene::kSceneHeight = 20;
45 
46 const uint8_t Scene::kScene[Scene::kSceneWidth * Scene::kSceneHeight] = {
47     //      5         10        15        20
48     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
49     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
50     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
51     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
52     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,  // 5
53     K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
54     K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, H, H, H,
55     K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, C, C, H, H, H,
56     K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, C, C, H, H, H,
57     H, K, K, K, K, K, H, R, R, R, R, R, R, R, R, R, R, R, R, H,  // 10
58     H, K, K, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
59     H, H, H, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
60     H, H, H, K, K, H, H, H, W, W, W, W, W, W, W, W, W, W, H, H,
61     S, S, S, G, G, S, S, S, W, W, W, W, W, W, W, W, W, W, S, S,
62     S, G, G, G, G, S, S, S, W, I, I, W, D, D, W, I, I, W, S, S,  // 15
63     G, G, G, G, G, G, S, S, W, I, I, W, D, D, W, I, I, W, S, S,
64     G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
65     G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
66     G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G,
67     G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G,  // 20
68     //      5         10        15        20
69 };
70 
71 #undef G
72 #undef S
73 #undef H
74 #undef W
75 #undef R
76 #undef D
77 #undef C
78 #undef I
79 #undef U
80 #undef K
81 #undef M
82 
Scene(int sensorWidthPx,int sensorHeightPx,float sensorSensitivity)83 Scene::Scene(int sensorWidthPx, int sensorHeightPx, float sensorSensitivity)
84     : mSensorWidth(sensorWidthPx),
85       mSensorHeight(sensorHeightPx),
86       mHour(12),
87       mExposureDuration(0.033f),
88       mSensorSensitivity(sensorSensitivity) {
89   // Map scene to sensor pixels
90   if (mSensorWidth > mSensorHeight) {
91     mMapDiv = (mSensorWidth / (kSceneWidth + 1)) + 1;
92   } else {
93     mMapDiv = (mSensorHeight / (kSceneHeight + 1)) + 1;
94   }
95   mOffsetX = (kSceneWidth * mMapDiv - mSensorWidth) / 2;
96   mOffsetY = (kSceneHeight * mMapDiv - mSensorHeight) / 2;
97 
98   // Assume that sensor filters are sRGB primaries to start
99   mFilterR[0] = 3.2406f;
100   mFilterR[1] = -1.5372f;
101   mFilterR[2] = -0.4986f;
102   mFilterGr[0] = -0.9689f;
103   mFilterGr[1] = 1.8758f;
104   mFilterGr[2] = 0.0415f;
105   mFilterGb[0] = -0.9689f;
106   mFilterGb[1] = 1.8758f;
107   mFilterGb[2] = 0.0415f;
108   mFilterB[0] = 0.0557f;
109   mFilterB[1] = -0.2040f;
110   mFilterB[2] = 1.0570f;
111 }
112 
~Scene()113 Scene::~Scene() {}
114 
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)115 void Scene::setColorFilterXYZ(float rX, float rY, float rZ, float grX,
116                               float grY, float grZ, float gbX, float gbY,
117                               float gbZ, float bX, float bY, float bZ) {
118   mFilterR[0] = rX;
119   mFilterR[1] = rY;
120   mFilterR[2] = rZ;
121   mFilterGr[0] = grX;
122   mFilterGr[1] = grY;
123   mFilterGr[2] = grZ;
124   mFilterGb[0] = gbX;
125   mFilterGb[1] = gbY;
126   mFilterGb[2] = gbZ;
127   mFilterB[0] = bX;
128   mFilterB[1] = bY;
129   mFilterB[2] = bZ;
130 }
131 
setHour(int hour)132 void Scene::setHour(int hour) {
133   ALOGV("Hour set to: %d", hour);
134   mHour = hour % 24;
135 }
136 
getHour()137 int Scene::getHour() { return mHour; }
138 
setExposureDuration(float seconds)139 void Scene::setExposureDuration(float seconds) { mExposureDuration = seconds; }
140 
calculateScene(nsecs_t time)141 void Scene::calculateScene(nsecs_t time) {
142   // Calculate time fractions for interpolation
143   int timeIdx = mHour / kTimeStep;
144   int nextTimeIdx = (timeIdx + 1) % (24 / kTimeStep);
145   const nsecs_t kOneHourInNsec = 1e9 * 60 * 60;
146   nsecs_t timeSinceIdx = (mHour - timeIdx * kTimeStep) * kOneHourInNsec + time;
147   float timeFrac = timeSinceIdx / (float)(kOneHourInNsec * kTimeStep);
148 
149   // Determine overall sunlight levels
150   float sunLux =
151       kSunlight[timeIdx] * (1 - timeFrac) + kSunlight[nextTimeIdx] * timeFrac;
152   ALOGV("Sun lux: %f", sunLux);
153 
154   float sunShadeLux = sunLux * (kDaylightShadeIllum / kDirectSunIllum);
155 
156   // Determine sun/shade illumination chromaticity
157   float currentSunXY[2];
158   float currentShadeXY[2];
159 
160   const float *prevSunXY, *nextSunXY;
161   const float *prevShadeXY, *nextShadeXY;
162   if (kSunlight[timeIdx] == kSunsetIllum ||
163       kSunlight[timeIdx] == kTwilightIllum) {
164     prevSunXY = kSunsetXY;
165     prevShadeXY = kSunsetXY;
166   } else {
167     prevSunXY = kDirectSunlightXY;
168     prevShadeXY = kDaylightXY;
169   }
170   if (kSunlight[nextTimeIdx] == kSunsetIllum ||
171       kSunlight[nextTimeIdx] == kTwilightIllum) {
172     nextSunXY = kSunsetXY;
173     nextShadeXY = kSunsetXY;
174   } else {
175     nextSunXY = kDirectSunlightXY;
176     nextShadeXY = kDaylightXY;
177   }
178   currentSunXY[0] = prevSunXY[0] * (1 - timeFrac) + nextSunXY[0] * timeFrac;
179   currentSunXY[1] = prevSunXY[1] * (1 - timeFrac) + nextSunXY[1] * timeFrac;
180 
181   currentShadeXY[0] =
182       prevShadeXY[0] * (1 - timeFrac) + nextShadeXY[0] * timeFrac;
183   currentShadeXY[1] =
184       prevShadeXY[1] * (1 - timeFrac) + nextShadeXY[1] * timeFrac;
185 
186   ALOGV("Sun XY: %f, %f, Shade XY: %f, %f", currentSunXY[0], currentSunXY[1],
187         currentShadeXY[0], currentShadeXY[1]);
188 
189   // Converting for xyY to XYZ:
190   // X = Y / y * x
191   // Y = Y
192   // Z = Y / y * (1 - x - y);
193   float sunXYZ[3] = {
194       sunLux / currentSunXY[1] * currentSunXY[0], sunLux,
195       sunLux / currentSunXY[1] * (1 - currentSunXY[0] - currentSunXY[1])};
196   float sunShadeXYZ[3] = {sunShadeLux / currentShadeXY[1] * currentShadeXY[0],
197                           sunShadeLux,
198                           sunShadeLux / currentShadeXY[1] *
199                               (1 - currentShadeXY[0] - currentShadeXY[1])};
200   ALOGV("Sun XYZ: %f, %f, %f", sunXYZ[0], sunXYZ[1], sunXYZ[2]);
201   ALOGV("Sun shade XYZ: %f, %f, %f", sunShadeXYZ[0], sunShadeXYZ[1],
202         sunShadeXYZ[2]);
203 
204   // Determine moonlight levels
205   float moonLux =
206       kMoonlight[timeIdx] * (1 - timeFrac) + kMoonlight[nextTimeIdx] * timeFrac;
207   float moonShadeLux = moonLux * (kDaylightShadeIllum / kDirectSunIllum);
208 
209   float moonXYZ[3] = {
210       moonLux / kMoonlightXY[1] * kMoonlightXY[0], moonLux,
211       moonLux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
212   float moonShadeXYZ[3] = {
213       moonShadeLux / kMoonlightXY[1] * kMoonlightXY[0], moonShadeLux,
214       moonShadeLux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
215 
216   // Determine starlight level
217   const float kClearNightXYZ[3] = {
218       kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0], kClearNightIllum,
219       kClearNightIllum / kMoonlightXY[1] *
220           (1 - kMoonlightXY[0] - kMoonlightXY[1])};
221 
222   // Calculate direct and shaded light
223   float directIllumXYZ[3] = {
224       sunXYZ[0] + moonXYZ[0] + kClearNightXYZ[0],
225       sunXYZ[1] + moonXYZ[1] + kClearNightXYZ[1],
226       sunXYZ[2] + moonXYZ[2] + kClearNightXYZ[2],
227   };
228 
229   float shadeIllumXYZ[3] = {kClearNightXYZ[0], kClearNightXYZ[1],
230                             kClearNightXYZ[2]};
231 
232   shadeIllumXYZ[0] += (mHour < kSunOverhead) ? sunXYZ[0] : sunShadeXYZ[0];
233   shadeIllumXYZ[1] += (mHour < kSunOverhead) ? sunXYZ[1] : sunShadeXYZ[1];
234   shadeIllumXYZ[2] += (mHour < kSunOverhead) ? sunXYZ[2] : sunShadeXYZ[2];
235 
236   // Moon up period covers 23->0 transition, shift for simplicity
237   int adjHour = (mHour + 12) % 24;
238   int adjMoonOverhead = (kMoonOverhead + 12) % 24;
239   shadeIllumXYZ[0] +=
240       (adjHour < adjMoonOverhead) ? moonXYZ[0] : moonShadeXYZ[0];
241   shadeIllumXYZ[1] +=
242       (adjHour < adjMoonOverhead) ? moonXYZ[1] : moonShadeXYZ[1];
243   shadeIllumXYZ[2] +=
244       (adjHour < adjMoonOverhead) ? moonXYZ[2] : moonShadeXYZ[2];
245 
246   ALOGV("Direct XYZ: %f, %f, %f", directIllumXYZ[0], directIllumXYZ[1],
247         directIllumXYZ[2]);
248   ALOGV("Shade XYZ: %f, %f, %f", shadeIllumXYZ[0], shadeIllumXYZ[1],
249         shadeIllumXYZ[2]);
250 
251   for (int i = 0; i < NUM_MATERIALS; i++) {
252     // Converting for xyY to XYZ:
253     // X = Y / y * x
254     // Y = Y
255     // Z = Y / y * (1 - x - y);
256     float matXYZ[3] = {
257         kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * kMaterials_xyY[i][0],
258         kMaterials_xyY[i][2],
259         kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
260             (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])};
261 
262     if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) {
263       matXYZ[0] *= directIllumXYZ[0];
264       matXYZ[1] *= directIllumXYZ[1];
265       matXYZ[2] *= directIllumXYZ[2];
266     } else if (kMaterialsFlags[i] & kShadowed) {
267       matXYZ[0] *= shadeIllumXYZ[0];
268       matXYZ[1] *= shadeIllumXYZ[1];
269       matXYZ[2] *= shadeIllumXYZ[2];
270     }  // else if (kMaterialsFlags[i] * kSelfLit), do nothing
271 
272     ALOGV("Mat %d XYZ: %f, %f, %f", i, matXYZ[0], matXYZ[1], matXYZ[2]);
273     float luxToElectrons =
274         mSensorSensitivity * mExposureDuration / (kAperture * kAperture);
275     mCurrentColors[i * NUM_CHANNELS + 0] =
276         (mFilterR[0] * matXYZ[0] + mFilterR[1] * matXYZ[1] +
277          mFilterR[2] * matXYZ[2]) *
278         luxToElectrons;
279     mCurrentColors[i * NUM_CHANNELS + 1] =
280         (mFilterGr[0] * matXYZ[0] + mFilterGr[1] * matXYZ[1] +
281          mFilterGr[2] * matXYZ[2]) *
282         luxToElectrons;
283     mCurrentColors[i * NUM_CHANNELS + 2] =
284         (mFilterGb[0] * matXYZ[0] + mFilterGb[1] * matXYZ[1] +
285          mFilterGb[2] * matXYZ[2]) *
286         luxToElectrons;
287     mCurrentColors[i * NUM_CHANNELS + 3] =
288         (mFilterB[0] * matXYZ[0] + mFilterB[1] * matXYZ[1] +
289          mFilterB[2] * matXYZ[2]) *
290         luxToElectrons;
291 
292     ALOGV("Color %d RGGB: %d, %d, %d, %d", i,
293           mCurrentColors[i * NUM_CHANNELS + 0],
294           mCurrentColors[i * NUM_CHANNELS + 1],
295           mCurrentColors[i * NUM_CHANNELS + 2],
296           mCurrentColors[i * NUM_CHANNELS + 3]);
297   }
298   // Shake viewpoint; horizontal and vertical sinusoids at roughly
299   // human handshake frequencies
300   mHandshakeX = (kFreq1Magnitude * std::sin(kHorizShakeFreq1 * timeSinceIdx) +
301                  kFreq2Magnitude * std::sin(kHorizShakeFreq2 * timeSinceIdx)) *
302                 mMapDiv * kShakeFraction;
303 
304   mHandshakeY = (kFreq1Magnitude * std::sin(kVertShakeFreq1 * timeSinceIdx) +
305                  kFreq2Magnitude * std::sin(kVertShakeFreq2 * timeSinceIdx)) *
306                 mMapDiv * kShakeFraction;
307 
308   // Set starting pixel
309   setReadoutPixel(0, 0);
310 }
311 
setReadoutPixel(int x,int y)312 void Scene::setReadoutPixel(int x, int y) {
313   mCurrentX = x;
314   mCurrentY = y;
315   mSubX = (x + mOffsetX + mHandshakeX) % mMapDiv;
316   mSubY = (y + mOffsetY + mHandshakeY) % mMapDiv;
317   mSceneX = (x + mOffsetX + mHandshakeX) / mMapDiv;
318   mSceneY = (y + mOffsetY + mHandshakeY) / mMapDiv;
319   mSceneIdx = mSceneY * kSceneWidth + mSceneX;
320   mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
321 }
322 
getPixelElectrons()323 const uint32_t *Scene::getPixelElectrons() {
324   const uint32_t *pixel = mCurrentSceneMaterial;
325   mCurrentX++;
326   mSubX++;
327   if (mCurrentX >= mSensorWidth) {
328     mCurrentX = 0;
329     mCurrentY++;
330     if (mCurrentY >= mSensorHeight) mCurrentY = 0;
331     setReadoutPixel(mCurrentX, mCurrentY);
332   } else if (mSubX > mMapDiv) {
333     mSceneIdx++;
334     mSceneX++;
335     mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
336     mSubX = 0;
337   }
338   return pixel;
339 }
340 
341 // Handshake model constants.
342 // Frequencies measured in a nanosecond timebase
343 const float Scene::kHorizShakeFreq1 = 2 * M_PI * 2 / 1e9;   // 2 Hz
344 const float Scene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9;  // 13 Hz
345 const float Scene::kVertShakeFreq1 = 2 * M_PI * 3 / 1e9;    // 3 Hz
346 const float Scene::kVertShakeFreq2 = 2 * M_PI * 11 / 1e9;   // 1 Hz
347 const float Scene::kFreq1Magnitude = 5;
348 const float Scene::kFreq2Magnitude = 1;
349 const float Scene::kShakeFraction = 0.03;  // As a fraction of a scene tile
350 
351 // RGB->YUV, Jpeg standard
352 const float Scene::kRgb2Yuv[12] = {
353     0.299f, 0.587f, 0.114f, 0.f,       -0.16874f, -0.33126f,
354     0.5f,   -128.f, 0.5f,   -0.41869f, -0.08131f, -128.f,
355 };
356 
357 // Aperture of imaging lens
358 const float Scene::kAperture = 2.8;
359 
360 // Sun illumination levels through the day
361 const float Scene::kSunlight[24 / kTimeStep] = {0,  // 00:00
362                                                 0,
363                                                 0,
364                                                 kTwilightIllum,  // 06:00
365                                                 kDirectSunIllum,
366                                                 kDirectSunIllum,
367                                                 kDirectSunIllum,  // 12:00
368                                                 kDirectSunIllum,
369                                                 kDirectSunIllum,
370                                                 kSunsetIllum,  // 18:00
371                                                 kTwilightIllum,
372                                                 0};
373 
374 // Moon illumination levels through the day
375 const float Scene::kMoonlight[24 / kTimeStep] = {kFullMoonIllum,  // 00:00
376                                                  kFullMoonIllum,
377                                                  0,
378                                                  0,  // 06:00
379                                                  0,
380                                                  0,
381                                                  0,  // 12:00
382                                                  0,
383                                                  0,
384                                                  0,  // 18:00
385                                                  0,
386                                                  kFullMoonIllum};
387 
388 const int Scene::kSunOverhead = 12;
389 const int Scene::kMoonOverhead = 0;
390 
391 // Used for sun illumination levels
392 const float Scene::kDirectSunIllum = 100000;
393 const float Scene::kSunsetIllum = 400;
394 const float Scene::kTwilightIllum = 4;
395 // Used for moon illumination levels
396 const float Scene::kFullMoonIllum = 1;
397 // Other illumination levels
398 const float Scene::kDaylightShadeIllum = 20000;
399 const float Scene::kClearNightIllum = 2e-3;
400 const float Scene::kStarIllum = 2e-6;
401 const float Scene::kLivingRoomIllum = 50;
402 
403 const float Scene::kIncandescentXY[2] = {0.44757f, 0.40745f};
404 const float Scene::kDirectSunlightXY[2] = {0.34842f, 0.35161f};
405 const float Scene::kDaylightXY[2] = {0.31271f, 0.32902f};
406 const float Scene::kNoonSkyXY[2] = {0.346f, 0.359f};
407 const float Scene::kMoonlightXY[2] = {0.34842f, 0.35161f};
408 const float Scene::kSunsetXY[2] = {0.527f, 0.413f};
409 
410 const uint8_t Scene::kSelfLit = 0x01;
411 const uint8_t Scene::kShadowed = 0x02;
412 const uint8_t Scene::kSky = 0x04;
413 
414 // For non-self-lit materials, the Y component is normalized with 1=full
415 // reflectance; for self-lit materials, it's the constant illuminance in lux.
416 const float Scene::kMaterials_xyY[Scene::NUM_MATERIALS][3] = {
417     {0.3688f, 0.4501f, .1329f},                                  // GRASS
418     {0.3688f, 0.4501f, .1329f},                                  // GRASS_SHADOW
419     {0.3986f, 0.5002f, .4440f},                                  // HILL
420     {0.3262f, 0.5040f, .2297f},                                  // WALL
421     {0.4336f, 0.3787f, .1029f},                                  // ROOF
422     {0.3316f, 0.2544f, .0639f},                                  // DOOR
423     {0.3425f, 0.3577f, .0887f},                                  // CHIMNEY
424     {kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum},  // WINDOW
425     {kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum},  // SUN
426     {kNoonSkyXY[0], kNoonSkyXY[1],
427      kDaylightShadeIllum / kDirectSunIllum},            // SKY
428     {kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum}  // MOON
429 };
430 
431 const uint8_t Scene::kMaterialsFlags[Scene::NUM_MATERIALS] = {
432     0,         kShadowed, kShadowed, kShadowed, kShadowed, kShadowed,
433     kShadowed, kSelfLit,  kSelfLit,  kSky,      kSelfLit,
434 };
435 
436 }  // namespace android
437