1// tCubemap.cpp 
2// 
3// A cubemap is simply a collection of 6 tTextures. By convention each tTexture has layers of the same pixel format. A 
4// tCubemap may be created from a dds file (assuming the dds file contains a cubemap) or from multiple tTextures. When 
5// construction from a dds is performed, it chooses a different image to load into the tTexture for each cubemap side. 
6// When constructing from tTextures directly it is the user's responsibility to supply the necessary tTextures in the 
7// correct format before constructing a tCubemap. tCubemaps can also save and load themselves into a tChunk-based 
8// format. They do this by looping through their tTextures and calling their individual Save/Load functions. 
9// 
10// ATI has a tool called CubeMapGen 1.1 which is useful for making your own cube map dds files. Its installer also 
11// installs some example dds cube maps to play with. The CubeMapGen tool (as of v1.1) does NOT generate valid DXT1 
12// compressed cubemap files. The header is incorrect and the data is not compressed. 
13// 
14// nVidia's DDS tools can also generate dds cubemaps straight from photoshop. Just pull down the combo-box that usually 
15// says "2D TEXTURE" and there'll be an option for cubemaps. The nVidia dds plugin for photoshop does not have this 
16// issues with texture compression and cubemaps. 
17// 
18// The order of the images for a cubemap are +x -x +y -y +z -z. In the CubeMapGen tool the option for OpenGL and DX 
19// coord systems only affects the export of cube map faces -- it does not, apparently, affect the output dds cubemap. 
20// i.e. It seems the faces should always be specified using a LH coord system. The OpenGL calls for specifying a 
21// cubemap are also left handed which is inconsistent with other parts of the OpenGL API. 
22// 
23// Copyright (c) 2006, 2017, 2019, 2020 Tristan Grimmer. 
24// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
25// granted, provided that the above copyright notice and this permission notice appear in all copies. 
26// 
27// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
29// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
30// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
31// PERFORMANCE OF THIS SOFTWARE. 
32 
33#include "Image/tCubemap.h" 
34#if 0 
35using namespace tImage; 
36 
37 
38bool tCubemap::IsValid() const 
39
40 for (int side = 0; side < int(tSide::NumSides); side++) 
41 if ((Sides[side].Side != tSide::Invalid) && Sides[side].Texture.IsValid()) 
42 return true
43 
44 return false
45
46 
47 
48bool tCubemap::AllSidesOpaque() const 
49
50 for (int side = 0; side < int(tSide::NumSides); side++) 
51 if ((Sides[side].Side != tSide::Invalid) && Sides[side].Texture.IsValid() && !Sides[side].Texture.IsOpaque()) 
52 return false
53 
54 return true
55
56 
57 
58void tCubemap::Clear() 
59
60 for (int side = 0; side < int(tSide::NumSides); side++) 
61
62 Sides[side].Side = tSide::Invalid; 
63 Sides[side].Texture.Clear(); 
64
65
66 
67 
68bool tCubemap::Load(const tString& ddsFile, bool reverseRowOrder) 
69
70 Clear(); 
71 if ((tSystem::tGetFileType(ddsFile) != tSystem::tFileType::DDS) || !tSystem::tFileExists(ddsFile)) 
72 return false
73 
74 tImageDDS::LoadParams loadParams; 
75 loadParams.Flags = tImageDDS::LoadFlag_ReverseRowOrder; 
76 tImageDDS dds(ddsFile, loadParams); 
77 if (!dds.IsValid() || !dds.IsCubemap()) 
78 return false
79 
80 return Set(dds); 
81
82 
83 
84bool tCubemap::Set(tImageDDS& dds) 
85
86 Clear(); 
87 if (!dds.IsValid() || !dds.IsCubemap()) 
88 return false
89 
90 tList<tLayer> layerSet[tImageDDS::tSurfIndex_NumSurfaces]; 
91 tStaticAssert(int(tSide::NumSides) == tImageDDS::tSurfIndex_NumSurfaces); 
92 dds.StealCubemapLayers(layerSet); 
93 
94 for (int side = 0; side < int(tSide::NumSides); side++) 
95
96 Sides[side].Side = tSide(side); 
97 Sides[side].Texture.Set(layerSet[side]); 
98
99 
100 if (!IsValid()) 
101
102 Clear(); 
103 return false
104
105 
106 return true
107
108 
109 
110bool tCubemap::Load 
111
112 const tString& imageFilePosX, const tString& imageFileNegX, 
113 const tString& imageFilePosY, const tString& imageFileNegY, 
114 const tString& imageFilePosZ, const tString& imageFileNegZ, 
115 bool generateMipMaps, tPixelFormat pixelFormat, tTexture::tQuality quality, int forceWidth, int forceHeight 
116
117
118 Clear(); 
119 tPicture posX(imageFilePosX); tPicture negX(imageFileNegX); 
120 tPicture posY(imageFilePosY); tPicture negY(imageFileNegY); 
121 tPicture posZ(imageFilePosZ); tPicture negZ(imageFileNegZ); 
122 return Set 
123
124 posX, negX, posY, negY, posZ, negZ, 
125 generateMipMaps, pixelFormat, quality, forceWidth, forceHeight 
126 ); 
127
128 
129 
130bool tCubemap::Set 
131
132 tPicture& imagePosX, tPicture& imageNegX, 
133 tPicture& imagePosY, tPicture& imageNegY, 
134 tPicture& imagePosZ, tPicture& imageNegZ, 
135 bool generateMipMaps, tPixelFormat pixelFormat, tTexture::tQuality quality, int forceWidth, int forceHeight 
136
137
138 Clear(); 
139 
140 tTexture textures[int(tSide::NumSides)]; 
141 textures[0].Set(imagePosX, generateMipMaps, pixelFormat, quality, forceWidth, forceHeight); 
142 textures[1].Set(imageNegX, generateMipMaps, pixelFormat, quality, forceWidth, forceHeight); 
143 textures[2].Set(imagePosY, generateMipMaps, pixelFormat, quality, forceWidth, forceHeight); 
144 textures[3].Set(imageNegY, generateMipMaps, pixelFormat, quality, forceWidth, forceHeight); 
145 textures[4].Set(imagePosZ, generateMipMaps, pixelFormat, quality, forceWidth, forceHeight); 
146 textures[5].Set(imageNegZ, generateMipMaps, pixelFormat, quality, forceWidth, forceHeight); 
147 
148 for (int side = 0; side < int(tSide::NumSides); side++) 
149
150 Sides[side].Side = textures[side].IsValid() ? tSide(side) : tSide::Invalid; 
151 
152 // Steal the layers from the texture and give them to the cubemap. 
153 tList<tLayer> layers; 
154 textures[side].StealLayers(layers); 
155 Sides[side].Texture.Set(layers); 
156
157 
158 if (!IsValid()) 
159
160 Clear(); 
161 return false
162
163 
164 return true
165
166 
167 
168tTexture* tCubemap::GetSide(tSide side) 
169
170 if (!IsValid()) 
171 return nullptr
172 
173 return &Sides[int(side)].Texture; 
174
175 
176 
177void tCubemap::Save(tChunkWriter& chunk) const 
178
179 chunk.Begin(tChunkID::Image_Cubemap); 
180
181 chunk.Begin(tChunkID::Image_CubemapProperties); 
182
183 chunk.Write( AllSidesOpaque() ); 
184
185 chunk.End(); 
186 
187 chunk.Begin(tChunkID::Image_CubemapSides); 
188
189 for (int side = 0; side < int(tSide::NumSides); side++) 
190
191 if ((Sides[side].Side == tSide::Invalid) || !Sides[side].Texture.IsValid()) 
192 continue
193 
194 chunk.Begin(tChunkID::Image_CubemapSide); 
195
196 chunk.Begin(tChunkID::Image_CubemapSideProperties); 
197
198 chunk.Write(tSide(side)); 
199
200 chunk.End(); 
201 
202 Sides[side].Texture.Save(chunk); 
203
204 chunk.End(); 
205
206
207 chunk.End(); 
208
209 chunk.End(); 
210
211 
212 
213void tCubemap::Load(const tChunk& chunk) 
214
215 Clear(); 
216 if (chunk.ID() != tChunkID::Image_Cubemap) 
217 return
218 
219 for (tChunk ch = chunk.First(); ch.IsValid(); ch = ch.Next()) 
220
221 switch (ch.ID()) 
222
223 case tChunkID::Image_CubemapProperties: 
224
225 bool allOpaque = false
226 ch.GetItem(allOpaque); 
227 break
228
229 
230 case tChunkID::Image_CubemapSides: 
231
232 for (tChunk sideChunk = ch.First(); sideChunk.IsValid(); sideChunk = sideChunk.Next()) 
233
234 tAssert(sideChunk.ID() == tChunkID::Image_CubemapSide); 
235 tSide side = tSide::Invalid; 
236 for (tChunk sideSub = sideChunk.First(); sideSub.IsValid(); sideSub = sideSub.Next()) 
237
238 switch (sideSub.ID()) 
239
240 case tChunkID::Image_CubemapSideProperties: 
241 sideSub.GetItem(side); 
242 break
243 
244 case tChunkID::Image_Texture: 
245 tAssert(side != tSide::Invalid); 
246 Sides[int(side)].Side = side; 
247 Sides[int(side)].Texture.Load(sideSub); 
248 break
249
250
251
252 break
253
254
255
256
257 
258 
259bool tCubemap::operator==(const tCubemap& src) const 
260
261 if (!IsValid() || !src.IsValid()) 
262 return false
263 
264 for (int side = 0; side < int(tSide::NumSides); side++) 
265
266 if (Sides[side].Side != src.Sides[side].Side) 
267 return false
268 
269 if (Sides[side].Texture != src.Sides[side].Texture) 
270 return false
271
272 
273 return true
274
275#endif 
276