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 47using namespace std; 48using namespace Imath; 49 50namespace Imf { 51namespace LatLongMap { 52 53V2f 54latLong (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 68V2f 69latLong (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 99V2f 100pixelPosition (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 110V2f 111pixelPosition (const Box2i &dataWindow, const V3f &direction) 112{ 113 return pixelPosition (dataWindow, latLong (direction)); 114} 115 116 117V3f 118direction (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 130namespace CubeMap { 131 132int 133sizeOfFace (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 140Box2i 141dataWindowForFace (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 156V2f 157pixelPosition (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 205void 206faceAndPixelPosition (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 260V3f 261direction (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