Path: blob/master/3rdparty/openexr/IlmImf/ImfEnvmap.cpp
16337 views
///////////////////////////////////////////////////////////////////////////1//2// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas3// Digital Ltd. LLC4//5// All rights reserved.6//7// Redistribution and use in source and binary forms, with or without8// modification, are permitted provided that the following conditions are9// met:10// * Redistributions of source code must retain the above copyright11// notice, this list of conditions and the following disclaimer.12// * Redistributions in binary form must reproduce the above13// copyright notice, this list of conditions and the following disclaimer14// in the documentation and/or other materials provided with the15// distribution.16// * Neither the name of Industrial Light & Magic nor the names of17// its contributors may be used to endorse or promote products derived18// from this software without specific prior written permission.19//20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31//32///////////////////////////////////////////////////////////////////////////333435//-----------------------------------------------------------------------------36//37// Environment maps38//39//-----------------------------------------------------------------------------4041#include <ImfEnvmap.h>42#include "ImathFun.h"43#include <algorithm>44#include <math.h>4546using namespace std;47using namespace Imath;4849namespace Imf {50namespace LatLongMap {5152V2f53latLong (const V3f &dir)54{55float r = sqrt (dir.z * dir.z + dir.x * dir.x);5657float latitude = (r < abs (dir.y))?58acos (r / dir.length()) * sign (dir.y):59asin (dir.y / dir.length());6061float longitude = (dir.z == 0 && dir.x == 0)? 0: atan2 (dir.x, dir.z);6263return V2f (latitude, longitude);64}656667V2f68latLong (const Box2i &dataWindow, const V2f &pixelPosition)69{70float latitude, longitude;7172if (dataWindow.max.y > dataWindow.min.y)73{74latitude = -M_PI *75((pixelPosition.y - dataWindow.min.y) /76(dataWindow.max.y - dataWindow.min.y) - 0.5f);77}78else79{80latitude = 0;81}8283if (dataWindow.max.x > dataWindow.min.x)84{85longitude = -2 * M_PI *86((pixelPosition.x - dataWindow.min.x) /87(dataWindow.max.x - dataWindow.min.x) - 0.5f);88}89else90{91longitude = 0;92}9394return V2f (latitude, longitude);95}969798V2f99pixelPosition (const Box2i &dataWindow, const V2f &latLong)100{101float x = latLong.y / (-2 * M_PI) + 0.5f;102float y = latLong.x / -M_PI + 0.5f;103104return V2f (x * (dataWindow.max.x - dataWindow.min.x) + dataWindow.min.x,105y * (dataWindow.max.y - dataWindow.min.y) + dataWindow.min.y);106}107108109V2f110pixelPosition (const Box2i &dataWindow, const V3f &direction)111{112return pixelPosition (dataWindow, latLong (direction));113}114115116V3f117direction (const Box2i &dataWindow, const V2f &pixelPosition)118{119V2f ll = latLong (dataWindow, pixelPosition);120121return V3f (sin (ll.y) * cos (ll.x),122sin (ll.x),123cos (ll.y) * cos (ll.x));124}125126} // namespace LatLongMap127128129namespace CubeMap {130131int132sizeOfFace (const Box2i &dataWindow)133{134return min ((dataWindow.max.x - dataWindow.min.x + 1),135(dataWindow.max.y - dataWindow.min.y + 1) / 6);136}137138139Box2i140dataWindowForFace (CubeMapFace face, const Box2i &dataWindow)141{142int sof = sizeOfFace (dataWindow);143Box2i dwf;144145dwf.min.x = 0;146dwf.min.y = int (face) * sof;147148dwf.max.x = dwf.min.x + sof - 1;149dwf.max.y = dwf.min.y + sof - 1;150151return dwf;152}153154155V2f156pixelPosition (CubeMapFace face, const Box2i &dataWindow, V2f positionInFace)157{158Box2i dwf = dataWindowForFace (face, dataWindow);159V2f pos (0, 0);160161switch (face)162{163case CUBEFACE_POS_X:164165pos.x = dwf.min.x + positionInFace.y;166pos.y = dwf.max.y - positionInFace.x;167break;168169case CUBEFACE_NEG_X:170171pos.x = dwf.max.x - positionInFace.y;172pos.y = dwf.max.y - positionInFace.x;173break;174175case CUBEFACE_POS_Y:176177pos.x = dwf.min.x + positionInFace.x;178pos.y = dwf.max.y - positionInFace.y;179break;180181case CUBEFACE_NEG_Y:182183pos.x = dwf.min.x + positionInFace.x;184pos.y = dwf.min.y + positionInFace.y;185break;186187case CUBEFACE_POS_Z:188189pos.x = dwf.max.x - positionInFace.x;190pos.y = dwf.max.y - positionInFace.y;191break;192193case CUBEFACE_NEG_Z:194195pos.x = dwf.min.x + positionInFace.x;196pos.y = dwf.max.y - positionInFace.y;197break;198}199200return pos;201}202203204void205faceAndPixelPosition (const V3f &direction,206const Box2i &dataWindow,207CubeMapFace &face,208V2f &pif)209{210int sof = sizeOfFace (dataWindow);211float absx = abs (direction.x);212float absy = abs (direction.y);213float absz = abs (direction.z);214215if (absx >= absy && absx >= absz)216{217if (absx == 0)218{219//220// Special case - direction is (0, 0, 0)221//222223face = CUBEFACE_POS_X;224pif = V2f (0, 0);225return;226}227228pif.x = (direction.y / absx + 1) / 2 * (sof - 1);229pif.y = (direction.z / absx + 1) / 2 * (sof - 1);230231if (direction.x > 0)232face = CUBEFACE_POS_X;233else234face = CUBEFACE_NEG_X;235}236else if (absy >= absz)237{238pif.x = (direction.x / absy + 1) / 2 * (sof - 1);239pif.y = (direction.z / absy + 1) / 2 * (sof - 1);240241if (direction.y > 0)242face = CUBEFACE_POS_Y;243else244face = CUBEFACE_NEG_Y;245}246else247{248pif.x = (direction.x / absz + 1) / 2 * (sof - 1);249pif.y = (direction.y / absz + 1) / 2 * (sof - 1);250251if (direction.z > 0)252face = CUBEFACE_POS_Z;253else254face = CUBEFACE_NEG_Z;255}256}257258259V3f260direction (CubeMapFace face, const Box2i &dataWindow, const V2f &positionInFace)261{262int sof = sizeOfFace (dataWindow);263264V2f pos;265266if (sof > 1)267{268pos = V2f (positionInFace.x / (sof - 1) * 2 - 1,269positionInFace.y / (sof - 1) * 2 - 1);270}271else272{273pos = V2f (0, 0);274}275276V3f dir (1, 0, 0);277278switch (face)279{280case CUBEFACE_POS_X:281282dir.x = 1;283dir.y = pos.x;284dir.z = pos.y;285break;286287case CUBEFACE_NEG_X:288289dir.x = -1;290dir.y = pos.x;291dir.z = pos.y;292break;293294case CUBEFACE_POS_Y:295296dir.x = pos.x;297dir.y = 1;298dir.z = pos.y;299break;300301case CUBEFACE_NEG_Y:302303dir.x = pos.x;304dir.y = -1;305dir.z = pos.y;306break;307308case CUBEFACE_POS_Z:309310dir.x = pos.x;311dir.y = pos.y;312dir.z = 1;313break;314315case CUBEFACE_NEG_Z:316317dir.x = pos.x;318dir.y = pos.y;319dir.z = -1;320break;321}322323return dir;324}325326} // namespace CubeMap327} // namespace Imf328329330