123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- ///////////////////////////////////////////////////////////////////////////
- //
- // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
- // Digital Ltd. LLC
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Industrial Light & Magic nor the names of
- // its contributors may be used to endorse or promote products derived
- // from this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- //
- ///////////////////////////////////////////////////////////////////////////
- //-----------------------------------------------------------------------------
- //
- // Environment maps
- //
- //-----------------------------------------------------------------------------
- #include "ImfEnvmap.h"
- #include "ImathFun.h"
- #include "ImfNamespace.h"
- #include <algorithm>
- #include <math.h>
- using namespace std;
- using namespace IMATH_NAMESPACE;
- OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
- namespace LatLongMap {
- V2f
- latLong (const V3f &dir)
- {
- float r = sqrt (dir.z * dir.z + dir.x * dir.x);
- float latitude = (r < abs (dir.y))?
- acos (r / dir.length()) * sign (dir.y):
- asin (dir.y / dir.length());
- float longitude = (dir.z == 0 && dir.x == 0)? 0: atan2 (dir.x, dir.z);
- return V2f (latitude, longitude);
- }
- V2f
- latLong (const Box2i &dataWindow, const V2f &pixelPosition)
- {
- float latitude, longitude;
- if (dataWindow.max.y > dataWindow.min.y)
- {
- latitude = -1 * float(M_PI) *
- ((pixelPosition.y - dataWindow.min.y) /
- (dataWindow.max.y - dataWindow.min.y) - 0.5f);
- }
- else
- {
- latitude = 0;
- }
- if (dataWindow.max.x > dataWindow.min.x)
- {
- longitude = -2 * float(M_PI) *
- ((pixelPosition.x - dataWindow.min.x) /
- (dataWindow.max.x - dataWindow.min.x) - 0.5f);
- }
- else
- {
- longitude = 0;
- }
- return V2f (latitude, longitude);
- }
- V2f
- pixelPosition (const Box2i &dataWindow, const V2f &latLong)
- {
- float x = latLong.y / (-2 * float(M_PI)) + 0.5f;
- float y = latLong.x / (-1 * float(M_PI)) + 0.5f;
- return V2f (x * (dataWindow.max.x - dataWindow.min.x) + dataWindow.min.x,
- y * (dataWindow.max.y - dataWindow.min.y) + dataWindow.min.y);
- }
- V2f
- pixelPosition (const Box2i &dataWindow, const V3f &direction)
- {
- return pixelPosition (dataWindow, latLong (direction));
- }
- V3f
- direction (const Box2i &dataWindow, const V2f &pixelPosition)
- {
- V2f ll = latLong (dataWindow, pixelPosition);
- return V3f (sin (ll.y) * cos (ll.x),
- sin (ll.x),
- cos (ll.y) * cos (ll.x));
- }
- } // namespace LatLongMap
- namespace CubeMap {
- int
- sizeOfFace (const Box2i &dataWindow)
- {
- return min ((dataWindow.max.x - dataWindow.min.x + 1),
- (dataWindow.max.y - dataWindow.min.y + 1) / 6);
- }
- Box2i
- dataWindowForFace (CubeMapFace face, const Box2i &dataWindow)
- {
- int sof = sizeOfFace (dataWindow);
- Box2i dwf;
- dwf.min.x = 0;
- dwf.min.y = int (face) * sof;
- dwf.max.x = dwf.min.x + sof - 1;
- dwf.max.y = dwf.min.y + sof - 1;
- return dwf;
- }
- V2f
- pixelPosition (CubeMapFace face, const Box2i &dataWindow, V2f positionInFace)
- {
- Box2i dwf = dataWindowForFace (face, dataWindow);
- V2f pos (0, 0);
- switch (face)
- {
- case CUBEFACE_POS_X:
- pos.x = dwf.min.x + positionInFace.y;
- pos.y = dwf.max.y - positionInFace.x;
- break;
- case CUBEFACE_NEG_X:
- pos.x = dwf.max.x - positionInFace.y;
- pos.y = dwf.max.y - positionInFace.x;
- break;
- case CUBEFACE_POS_Y:
- pos.x = dwf.min.x + positionInFace.x;
- pos.y = dwf.max.y - positionInFace.y;
- break;
- case CUBEFACE_NEG_Y:
- pos.x = dwf.min.x + positionInFace.x;
- pos.y = dwf.min.y + positionInFace.y;
- break;
- case CUBEFACE_POS_Z:
- pos.x = dwf.max.x - positionInFace.x;
- pos.y = dwf.max.y - positionInFace.y;
- break;
- case CUBEFACE_NEG_Z:
- pos.x = dwf.min.x + positionInFace.x;
- pos.y = dwf.max.y - positionInFace.y;
- break;
- }
- return pos;
- }
- void
- faceAndPixelPosition (const V3f &direction,
- const Box2i &dataWindow,
- CubeMapFace &face,
- V2f &pif)
- {
- int sof = sizeOfFace (dataWindow);
- float absx = abs (direction.x);
- float absy = abs (direction.y);
- float absz = abs (direction.z);
- if (absx >= absy && absx >= absz)
- {
- if (absx == 0)
- {
- //
- // Special case - direction is (0, 0, 0)
- //
- face = CUBEFACE_POS_X;
- pif = V2f (0, 0);
- return;
- }
- pif.x = (direction.y / absx + 1) / 2 * (sof - 1);
- pif.y = (direction.z / absx + 1) / 2 * (sof - 1);
- if (direction.x > 0)
- face = CUBEFACE_POS_X;
- else
- face = CUBEFACE_NEG_X;
- }
- else if (absy >= absz)
- {
- pif.x = (direction.x / absy + 1) / 2 * (sof - 1);
- pif.y = (direction.z / absy + 1) / 2 * (sof - 1);
- if (direction.y > 0)
- face = CUBEFACE_POS_Y;
- else
- face = CUBEFACE_NEG_Y;
- }
- else
- {
- pif.x = (direction.x / absz + 1) / 2 * (sof - 1);
- pif.y = (direction.y / absz + 1) / 2 * (sof - 1);
- if (direction.z > 0)
- face = CUBEFACE_POS_Z;
- else
- face = CUBEFACE_NEG_Z;
- }
- }
- V3f
- direction (CubeMapFace face, const Box2i &dataWindow, const V2f &positionInFace)
- {
- int sof = sizeOfFace (dataWindow);
- V2f pos;
-
- if (sof > 1)
- {
- pos = V2f (positionInFace.x / (sof - 1) * 2 - 1,
- positionInFace.y / (sof - 1) * 2 - 1);
- }
- else
- {
- pos = V2f (0, 0);
- }
- V3f dir (1, 0, 0);
- switch (face)
- {
- case CUBEFACE_POS_X:
- dir.x = 1;
- dir.y = pos.x;
- dir.z = pos.y;
- break;
- case CUBEFACE_NEG_X:
- dir.x = -1;
- dir.y = pos.x;
- dir.z = pos.y;
- break;
- case CUBEFACE_POS_Y:
- dir.x = pos.x;
- dir.y = 1;
- dir.z = pos.y;
- break;
- case CUBEFACE_NEG_Y:
- dir.x = pos.x;
- dir.y = -1;
- dir.z = pos.y;
- break;
- case CUBEFACE_POS_Z:
- dir.x = pos.x;
- dir.y = pos.y;
- dir.z = 1;
- break;
- case CUBEFACE_NEG_Z:
- dir.x = pos.x;
- dir.y = pos.y;
- dir.z = -1;
- break;
- }
- return dir;
- }
- } // namespace CubeMap
- OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
|