1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // * Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34
35
36 //-----------------------------------------------------------------------------
37 //
38 // Environment maps
39 //
40 //-----------------------------------------------------------------------------
41
42 #include <ImfEnvmap.h>
43 #include "ImathFun.h"
44 #include <algorithm>
45 #include <math.h>
46
47 using namespace std;
48 using namespace Imath;
49
50 namespace Imf {
51 namespace LatLongMap {
52
53 V2f
latLong(const V3f & dir)54 latLong (const V3f &dir)
55 {
56 float r = sqrt (dir.z * dir.z + dir.x * dir.x);
57
58 float latitude = (r < abs (dir.y))?
59 acos (r / dir.length()) * sign (dir.y):
60 asin (dir.y / dir.length());
61
62 float longitude = (dir.z == 0 && dir.x == 0)? 0: atan2 (dir.x, dir.z);
63
64 return V2f (latitude, longitude);
65 }
66
67
68 V2f
latLong(const Box2i & dataWindow,const V2f & pixelPosition)69 latLong (const Box2i &dataWindow, const V2f &pixelPosition)
70 {
71 float latitude, longitude;
72
73 if (dataWindow.max.y > dataWindow.min.y)
74 {
75 latitude = -M_PI *
76 ((pixelPosition.y - dataWindow.min.y) /
77 (dataWindow.max.y - dataWindow.min.y) - 0.5f);
78 }
79 else
80 {
81 latitude = 0;
82 }
83
84 if (dataWindow.max.x > dataWindow.min.x)
85 {
86 longitude = -2 * M_PI *
87 ((pixelPosition.x - dataWindow.min.x) /
88 (dataWindow.max.x - dataWindow.min.x) - 0.5f);
89 }
90 else
91 {
92 longitude = 0;
93 }
94
95 return V2f (latitude, longitude);
96 }
97
98
99 V2f
pixelPosition(const Box2i & dataWindow,const V2f & latLong)100 pixelPosition (const Box2i &dataWindow, const V2f &latLong)
101 {
102 float x = latLong.y / (-2 * M_PI) + 0.5f;
103 float y = latLong.x / -M_PI + 0.5f;
104
105 return V2f (x * (dataWindow.max.x - dataWindow.min.x) + dataWindow.min.x,
106 y * (dataWindow.max.y - dataWindow.min.y) + dataWindow.min.y);
107 }
108
109
110 V2f
pixelPosition(const Box2i & dataWindow,const V3f & direction)111 pixelPosition (const Box2i &dataWindow, const V3f &direction)
112 {
113 return pixelPosition (dataWindow, latLong (direction));
114 }
115
116
117 V3f
direction(const Box2i & dataWindow,const V2f & pixelPosition)118 direction (const Box2i &dataWindow, const V2f &pixelPosition)
119 {
120 V2f ll = latLong (dataWindow, pixelPosition);
121
122 return V3f (sin (ll.y) * cos (ll.x),
123 sin (ll.x),
124 cos (ll.y) * cos (ll.x));
125 }
126
127 } // namespace LatLongMap
128
129
130 namespace CubeMap {
131
132 int
sizeOfFace(const Box2i & dataWindow)133 sizeOfFace (const Box2i &dataWindow)
134 {
135 return min ((dataWindow.max.x - dataWindow.min.x + 1),
136 (dataWindow.max.y - dataWindow.min.y + 1) / 6);
137 }
138
139
140 Box2i
dataWindowForFace(CubeMapFace face,const Box2i & dataWindow)141 dataWindowForFace (CubeMapFace face, const Box2i &dataWindow)
142 {
143 int sof = sizeOfFace (dataWindow);
144 Box2i dwf;
145
146 dwf.min.x = 0;
147 dwf.min.y = int (face) * sof;
148
149 dwf.max.x = dwf.min.x + sof - 1;
150 dwf.max.y = dwf.min.y + sof - 1;
151
152 return dwf;
153 }
154
155
156 V2f
pixelPosition(CubeMapFace face,const Box2i & dataWindow,V2f positionInFace)157 pixelPosition (CubeMapFace face, const Box2i &dataWindow, V2f positionInFace)
158 {
159 Box2i dwf = dataWindowForFace (face, dataWindow);
160 V2f pos (0, 0);
161
162 switch (face)
163 {
164 case CUBEFACE_POS_X:
165
166 pos.x = dwf.min.x + positionInFace.y;
167 pos.y = dwf.max.y - positionInFace.x;
168 break;
169
170 case CUBEFACE_NEG_X:
171
172 pos.x = dwf.max.x - positionInFace.y;
173 pos.y = dwf.max.y - positionInFace.x;
174 break;
175
176 case CUBEFACE_POS_Y:
177
178 pos.x = dwf.min.x + positionInFace.x;
179 pos.y = dwf.max.y - positionInFace.y;
180 break;
181
182 case CUBEFACE_NEG_Y:
183
184 pos.x = dwf.min.x + positionInFace.x;
185 pos.y = dwf.min.y + positionInFace.y;
186 break;
187
188 case CUBEFACE_POS_Z:
189
190 pos.x = dwf.max.x - positionInFace.x;
191 pos.y = dwf.max.y - positionInFace.y;
192 break;
193
194 case CUBEFACE_NEG_Z:
195
196 pos.x = dwf.min.x + positionInFace.x;
197 pos.y = dwf.max.y - positionInFace.y;
198 break;
199 }
200
201 return pos;
202 }
203
204
205 void
faceAndPixelPosition(const V3f & direction,const Box2i & dataWindow,CubeMapFace & face,V2f & pif)206 faceAndPixelPosition (const V3f &direction,
207 const Box2i &dataWindow,
208 CubeMapFace &face,
209 V2f &pif)
210 {
211 int sof = sizeOfFace (dataWindow);
212 float absx = abs (direction.x);
213 float absy = abs (direction.y);
214 float absz = abs (direction.z);
215
216 if (absx >= absy && absx >= absz)
217 {
218 if (absx == 0)
219 {
220 //
221 // Special case - direction is (0, 0, 0)
222 //
223
224 face = CUBEFACE_POS_X;
225 pif = V2f (0, 0);
226 return;
227 }
228
229 pif.x = (direction.y / absx + 1) / 2 * (sof - 1);
230 pif.y = (direction.z / absx + 1) / 2 * (sof - 1);
231
232 if (direction.x > 0)
233 face = CUBEFACE_POS_X;
234 else
235 face = CUBEFACE_NEG_X;
236 }
237 else if (absy >= absz)
238 {
239 pif.x = (direction.x / absy + 1) / 2 * (sof - 1);
240 pif.y = (direction.z / absy + 1) / 2 * (sof - 1);
241
242 if (direction.y > 0)
243 face = CUBEFACE_POS_Y;
244 else
245 face = CUBEFACE_NEG_Y;
246 }
247 else
248 {
249 pif.x = (direction.x / absz + 1) / 2 * (sof - 1);
250 pif.y = (direction.y / absz + 1) / 2 * (sof - 1);
251
252 if (direction.z > 0)
253 face = CUBEFACE_POS_Z;
254 else
255 face = CUBEFACE_NEG_Z;
256 }
257 }
258
259
260 V3f
direction(CubeMapFace face,const Box2i & dataWindow,const V2f & positionInFace)261 direction (CubeMapFace face, const Box2i &dataWindow, const V2f &positionInFace)
262 {
263 int sof = sizeOfFace (dataWindow);
264
265 V2f pos;
266
267 if (sof > 1)
268 {
269 pos = V2f (positionInFace.x / (sof - 1) * 2 - 1,
270 positionInFace.y / (sof - 1) * 2 - 1);
271 }
272 else
273 {
274 pos = V2f (0, 0);
275 }
276
277 V3f dir (1, 0, 0);
278
279 switch (face)
280 {
281 case CUBEFACE_POS_X:
282
283 dir.x = 1;
284 dir.y = pos.x;
285 dir.z = pos.y;
286 break;
287
288 case CUBEFACE_NEG_X:
289
290 dir.x = -1;
291 dir.y = pos.x;
292 dir.z = pos.y;
293 break;
294
295 case CUBEFACE_POS_Y:
296
297 dir.x = pos.x;
298 dir.y = 1;
299 dir.z = pos.y;
300 break;
301
302 case CUBEFACE_NEG_Y:
303
304 dir.x = pos.x;
305 dir.y = -1;
306 dir.z = pos.y;
307 break;
308
309 case CUBEFACE_POS_Z:
310
311 dir.x = pos.x;
312 dir.y = pos.y;
313 dir.z = 1;
314 break;
315
316 case CUBEFACE_NEG_Z:
317
318 dir.x = pos.x;
319 dir.y = pos.y;
320 dir.z = -1;
321 break;
322 }
323
324 return dir;
325 }
326
327 } // namespace CubeMap
328 } // namespace Imf
329