Home | History | Annotate | Download | only in IlmImf
      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
     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
     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
    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
    111 pixelPosition (const Box2i &dataWindow, const V3f &direction)
    112 {
    113     return pixelPosition (dataWindow, latLong (direction));
    114 }
    115 
    116 
    117 V3f
    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
    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
    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
    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
    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
    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