Line data Source code
1 0 : /*
2 :
3 : OOConvertCubeMapToLatLong.m
4 :
5 : Convert a cube map texture to a lat/long texture.
6 :
7 :
8 : Copyright (C) 2010-2013 Jens Ayton
9 :
10 : Permission is hereby granted, free of charge, to any person obtaining a copy
11 : of this software and associated documentation files (the "Software"), to deal
12 : in the Software without restriction, including without limitation the rights
13 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 : copies of the Software, and to permit persons to whom the Software is
15 : furnished to do so, subject to the following conditions:
16 :
17 : The above copyright notice and this permission notice shall be included in all
18 : copies or substantial portions of the Software.
19 :
20 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 : SOFTWARE.
27 :
28 : */
29 :
30 : #import "OOConvertCubeMapToLatLong.h"
31 : #import "OOTextureScaling.h"
32 :
33 :
34 0 : #define kPiF (3.14159265358979323846264338327950288f)
35 :
36 :
37 0 : OOPixMap OOConvertCubeMapToLatLong(OOPixMap sourcePixMap, OOPixMapDimension height, BOOL leaveSpaceForMipMaps)
38 : {
39 : if (!OOIsValidPixMap(sourcePixMap) || sourcePixMap.format != kOOPixMapRGBA || sourcePixMap.height != sourcePixMap.width * 6)
40 : {
41 : return kOONullPixMap;
42 : }
43 :
44 : NSCParameterAssert(height > 0);
45 :
46 : height *= 2;
47 : OOPixMapDimension width = height * 2;
48 : OOPixMap outPixMap = OOAllocatePixMap(width, height, 4, 0, 0);
49 : if (!OOIsValidPixMap(outPixMap)) return kOONullPixMap;
50 :
51 : OOPixMapDimension x, y;
52 : uint32_t *pixel = outPixMap.pixels;
53 : float fheight = height;
54 : float rheight = 1.0f / fheight;
55 :
56 : float halfSize = (sourcePixMap.width - 1) * 0.5f;
57 : uint8_t *srcBytes = sourcePixMap.pixels;
58 :
59 : // Build tables of sin/cos of longitude.
60 : float sinTable[width];
61 : float cosTable[width];
62 : for (x = 0; x < width; x++)
63 : {
64 : float lon = ((float)x * rheight) * kPiF;
65 : sinTable[x] = sin(lon);
66 : cosTable[x] = cos(lon);
67 : }
68 :
69 : for (y = 0; y < height; y++)
70 : {
71 : // Calcuate sin/cos of latitude.
72 : /*
73 : Clang static analyzer (Xcode 3.2.5 version, through to Xcode 4.4
74 : and freestanding checker-268 at least) says:
75 : "Assigned value is garbage or undefined."
76 : Memsetting sinTable to all-zeros moves this to the cosTable line.
77 : Since every value in each of those tables is in fact defined, this
78 : is an error in the analyzer.
79 : -- Ahruman 2011-01-25/2012-09-14
80 : */
81 : float cy = -sinTable[width * 3 / 4 - y];
82 : float lac = -cosTable[width * 3 / 4 - y];
83 : float ay = fabs(cy);
84 :
85 : for (x = 0; x < width; x++)
86 : {
87 : float cx = sinTable[x] * lac;
88 : float cz = cosTable[x] * lac;
89 :
90 : float ax = fabs(cx);
91 : float az = fabs(cz);
92 :
93 : // Y offset of start of this face in image.
94 : OOPixMapDimension yOffset;
95 :
96 : // Coordinates within selected face.
97 : float x, y, r;
98 :
99 : // Select source face.
100 : if (ax >= ay && ax >= az)
101 : {
102 : x = cz;
103 : y = -cy;
104 : r = ax;
105 : if (0.0f < cx)
106 : {
107 : yOffset = 0;
108 : }
109 : else
110 : {
111 : x = -x;
112 : yOffset = 1;
113 : }
114 : }
115 : else if (ay >= ax && ay >= az)
116 : {
117 : x = cx;
118 : y = cz;
119 : r = ay;
120 : if (0.0f < cy)
121 : {
122 : y = -y;
123 : yOffset = 2;
124 : }
125 : else
126 : {
127 : yOffset = 3;
128 : }
129 : }
130 : else
131 : {
132 : x = cx;
133 : y = -cy;
134 : r = az;
135 : if (0.0f < cz)
136 : {
137 : x = -x;
138 : yOffset = 5;
139 : }
140 : else
141 : {
142 : yOffset = 4;
143 : }
144 : }
145 :
146 : // Scale coordinates.
147 : r = 1.0f / r;
148 : OOPixMapDimension ix = (x * r + 1.0f) * halfSize;
149 : OOPixMapDimension iy = (y * r + 1.0f) * halfSize;
150 :
151 : #ifndef NDEBUG
152 : assert(ix < sourcePixMap.width && iy < sourcePixMap.width);
153 : #endif
154 :
155 : // Look up pixel.
156 : iy += sourcePixMap.width * yOffset;
157 :
158 : uint32_t *row = (uint32_t *)(srcBytes + iy * sourcePixMap.rowBytes);
159 : *pixel++ = row[ix];
160 : }
161 : }
162 :
163 : // Scale to half size for supersamplingness.
164 : return OOScalePixMap(outPixMap, width / 2, height / 2, leaveSpaceForMipMaps);
165 : }
|