• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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