0031478: Visualization, TKOpenGl - allow uploading Cubemap in compressed DDS format...
[occt.git] / src / Graphic3d / Graphic3d_CubeMapPacked.cxx
1 // Author: Ilya Khramov
2 // Copyright (c) 2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <Graphic3d_CubeMapPacked.hxx>
16
17 #include <Image_AlienPixMap.hxx>
18 #include <Image_DDSParser.hxx>
19
20 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CubeMapPacked, Graphic3d_CubeMap)
21
22 // =======================================================================
23 // function : Graphic3d_CubeMapPacked
24 // purpose  :
25 // =======================================================================
26 Graphic3d_CubeMapPacked::Graphic3d_CubeMapPacked (const TCollection_AsciiString&        theFilePath,
27                                                   const Graphic3d_ValidatedCubeMapOrder theOrder)
28   :
29   Graphic3d_CubeMap (theFilePath),
30   myOrder           (theOrder),
31   myTileNumberX     (1)
32 {}
33
34 // =======================================================================
35 // function : Graphic3d_CubeMapPacked
36 // purpose  :
37 // =======================================================================
38 Graphic3d_CubeMapPacked::Graphic3d_CubeMapPacked (const Handle(Image_PixMap)&           theImage,
39                                                   const Graphic3d_ValidatedCubeMapOrder theOrder)
40   :
41   Graphic3d_CubeMap (Handle(Image_PixMap)()),
42   myOrder           (theOrder),
43   myTileNumberX     (1)
44 {
45   if (checkImage (theImage, myTileNumberX))
46   {
47     myPixMap = theImage;
48   }
49 }
50
51 // =======================================================================
52 // function : CompressedValue
53 // purpose  :
54 // =======================================================================
55 Handle(Image_CompressedPixMap) Graphic3d_CubeMapPacked::CompressedValue (const Handle(Image_SupportedFormats)& theSupported)
56 {
57   if (myTileNumberX == 0
58   || !myPixMap.IsNull())
59   {
60     return Handle(Image_CompressedPixMap)();
61   }
62
63   TCollection_AsciiString aFilePath;
64   myPath.SystemName (aFilePath);
65   if (!aFilePath.IsEmpty())
66   {
67     const unsigned int aTileIndex = myOrder[myCurrentSide];
68     Handle(Image_CompressedPixMap) anImage = Image_DDSParser::Load (theSupported, aFilePath, (Standard_Integer )aTileIndex);
69     if (!anImage.IsNull()
70       && anImage->NbFaces() == 6
71       && anImage->SizeX() == anImage->SizeY())
72     {
73       myIsTopDown = anImage->IsTopDown();
74       return anImage;
75     }
76   }
77   return Handle(Image_CompressedPixMap)();
78 }
79
80 // =======================================================================
81 // function : Value
82 // purpose  :
83 // =======================================================================
84 Handle(Image_PixMap) Graphic3d_CubeMapPacked::Value (const Handle(Image_SupportedFormats)& theSupported)
85 {
86   if (myTileNumberX != 0)
87   {
88     if (myPixMap.IsNull())
89     {
90       TCollection_AsciiString aFilePath;
91       myPath.SystemName (aFilePath);
92       if (!aFilePath.IsEmpty())
93       {
94         tryLoadImage (theSupported, aFilePath);
95       }
96     }
97
98     if (!myPixMap.IsNull())
99     {
100       Handle(Image_PixMap) aWrapper = new Image_PixMap();
101
102       Standard_Size aTileSize = myPixMap->SizeX() / myTileNumberX;
103
104       myIsTopDown = myPixMap->IsTopDown();
105
106       Graphic3d_CubeMapOrder anOrder = myOrder;
107
108       if (!myIsTopDown)
109       {
110         myPixMap->SetTopDown (true);
111         anOrder.Swap (Graphic3d_CMS_POS_Y, Graphic3d_CMS_NEG_Y);
112       }
113
114       unsigned int aTileIndexX = anOrder[myCurrentSide] % myTileNumberX;
115       unsigned int aTileIndexY = anOrder[myCurrentSide] / myTileNumberX;
116
117       aTileIndexY = myIsTopDown ? aTileIndexY : (6 / myTileNumberX - 1 - aTileIndexY);
118
119       if (aWrapper->InitWrapper (myPixMap->Format(),
120                                  myPixMap->ChangeRawValue(aTileIndexY * aTileSize, aTileIndexX * aTileSize),
121                                  aTileSize,
122                                  aTileSize,
123                                  myPixMap->SizeRowBytes()))
124       {
125         myPixMap->SetTopDown (myIsTopDown);
126         return aWrapper;
127       }
128       else
129       {
130         myPixMap->SetTopDown(myIsTopDown);
131       }
132     }
133   }
134
135   return Handle(Image_PixMap)();
136 }
137
138 // =======================================================================
139 // function : checkOrder
140 // purpose  :
141 // =======================================================================
142 Standard_Boolean Graphic3d_CubeMapPacked::checkOrder (const NCollection_Array1<unsigned int>& theOrder)
143 {
144   Standard_Boolean anOrderIsValid = Standard_True;
145
146   if (theOrder.Size() != 6)
147   {
148     anOrderIsValid = Standard_False;
149   }
150   else
151   {
152     for (unsigned int i = 0; i < 6 && anOrderIsValid; ++i)
153     {
154       if (theOrder[i] > 5)
155       {
156         anOrderIsValid = Standard_False;
157         break;
158       }
159
160       for (unsigned int j = i + 1; j < 6; ++j)
161       {
162         if (theOrder[i] == theOrder[j])
163         {
164           anOrderIsValid =  Standard_False;
165           break;
166         }
167       }
168     }
169   }
170
171   if (!anOrderIsValid)
172   {
173     throw Standard_Failure ("Ivalid order format in tiles of Graphic3d_CubeMapPacked");
174   }
175
176   return anOrderIsValid;
177 }
178
179 // =======================================================================
180 // function : checkImage
181 // purpose  :
182 // =======================================================================
183 Standard_Boolean Graphic3d_CubeMapPacked::checkImage (const Handle(Image_PixMap)& theImage,
184                                                       unsigned int&               theTileNumberX)
185 {
186   Standard_Size aSizeX = theImage->SizeX();
187   Standard_Size aSizeY = theImage->SizeY();
188
189   if ((aSizeY % aSizeX == 0) && (aSizeY / aSizeX == 6))
190   {
191     theTileNumberX = 1;
192   }
193   else if ((aSizeX % aSizeY == 0) && (aSizeX / aSizeY == 6))
194   {
195     theTileNumberX = 6;
196   }
197   else if ((aSizeX % 2 == 0) && (aSizeY % 3 == 0) && (aSizeX / 2 == aSizeY / 3))
198   {
199     theTileNumberX = 2;
200   }
201   else if ((aSizeX % 3 == 0) && (aSizeY % 2 == 0) && (aSizeX / 3 == aSizeY / 2))
202   {
203     theTileNumberX = 3;
204   }
205   else
206   {
207     return Standard_False;
208   }
209
210   return Standard_True;
211 }
212
213 // =======================================================================
214 // function : tryLoadImage
215 // purpose  :
216 // =======================================================================
217 void Graphic3d_CubeMapPacked::tryLoadImage (const Handle(Image_SupportedFormats)& theSupported,
218                                             const TCollection_AsciiString& theFilePath)
219 {
220   Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap;
221   if (anImage->Load (theFilePath))
222   {
223     if (checkImage (anImage, myTileNumberX))
224     {
225       convertToCompatible (theSupported, anImage);
226       myPixMap = anImage;
227     }
228   }
229 }