NTrace
GPU ray tracing framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TextureAtlas.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2011, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "3d/TextureAtlas.hpp"
29 #include "base/Sort.hpp"
30 
31 using namespace FW;
32 
33 //------------------------------------------------------------------------
34 
36 : m_format (format),
37  m_atlasSize (0)
38 {
39 }
40 
41 //------------------------------------------------------------------------
42 
44 {
45 }
46 
47 //------------------------------------------------------------------------
48 
50 {
51  if (m_items.getSize())
52  {
53  m_items.reset();
54  m_itemHash.clear();
55  m_atlasTexture = Texture();
56  }
57 }
58 
59 //------------------------------------------------------------------------
60 
61 bool TextureAtlas::addTexture(const Texture& tex, int border, bool wrap)
62 {
63  FW_ASSERT(border >= 0);
64  const Image* image = tex.getImage();
65  if (!image || min(image->getSize()) <= 0 || m_itemHash.contains(image))
66  return false;
67 
68  m_itemHash.add(image, m_items.getSize());
69  Item& item = m_items.add();
70  item.texture = tex;
71  item.border = border;
72  item.wrap = wrap;
73  item.size = image->getSize() + border * 2;
74  m_atlasTexture = Texture();
75  return true;
76 }
77 
78 //------------------------------------------------------------------------
79 
81 {
82  validate();
83  S32* found = m_itemHash.search(tex.getImage());
84  if (!found)
85  return 0;
86 
87  const Item& item = m_items[*found];
88  return item.pos + item.border;
89 }
90 
91 //------------------------------------------------------------------------
92 
94 {
95  validate();
96  S32* found = m_itemHash.search(tex.getImage());
97  if(!found)
98  return 0;
99 
100  const Item& item = m_items[*found];
101  return item.size;
102 }
103 
104 //------------------------------------------------------------------------
105 
107 {
108  validate();
109  S32* found = m_itemHash.search(tex.getImage());
110  if (!found)
111  return 0;
112 
113  const Item& item = m_items[*found];
114  Vec2i size = getAtlasSize();
115  Vec2i pos = item.pos + item.border;
116  return Vec2f((F32)(pos.x) / (F32)(size.x), (F32)(pos.y) / (F32)(size.y));
117 }
118 
119 //------------------------------------------------------------------------
120 
122 {
123  validate();
124  S32* found = m_itemHash.search(tex.getImage());
125  if(!found)
126  return 0;
127 
128  const Item& item = m_items[*found];
129  Vec2i size = getAtlasSize();
130  return Vec2f((F32)(item.size.x) / (F32)(size.x), (F32)(item.size.y) / (F32)(size.y));
131 }
132 
133 //------------------------------------------------------------------------
134 
135 void TextureAtlas::validate(void)
136 {
137  if (!m_atlasTexture.exists())
138  {
139  layoutItems();
140  if (!hasError())
141  createAtlas();
142  }
143 }
144 
145 //------------------------------------------------------------------------
146 
147 void TextureAtlas::layoutItems(void)
148 {
149  // Select initial size.
150 
151  S32 totalArea = 0;
152  for (int i = 0; i < m_items.getSize(); i++)
153  totalArea += m_items[i].size.x * m_items[i].size.y;
154  Vec2i canvas = (int)sqrt((F32)totalArea);
155 
156  // Sort items in descending order of height.
157 
158  Array<Vec2i> order(NULL, m_items.getSize());
159  for (int i = 0; i < m_items.getSize(); i++)
160  order[i] = Vec2i(-m_items[i].size.y, i);
161  FW_SORT_ARRAY(order, Vec2i, a.x < b.x || (a.x == b.x && a.y < b.y));
162 
163  // Add items iteratively.
164 
165  Array<Vec4i> maxRects(Vec4i(0, 0, FW_S32_MAX, FW_S32_MAX));
166  for (int itemIdx = 0; itemIdx < m_items.getSize(); itemIdx++)
167  {
168  Item& item = m_items[order[itemIdx].y];
169  const Vec2i& s = item.size;
170 
171  // Select position.
172 
173  Vec2i bestPos = 0;
174  Vec3i bestCost = FW_S32_MAX;
175  for (int i = 0; i < maxRects.getSize(); i++)
176  {
177  const Vec4i& r = maxRects[i];
178  if (r.x + s.x > r.z || r.y + s.y > r.w)
179  continue;
180 
181  Vec3i cost;
182  cost.x = max(canvas.x, r.x + s.x) * max(canvas.y, r.y + s.y); // Minimize canvas.
183  cost.y = r.y + s.y; // Minimize Y.
184  cost.z = r.x + s.x; // Minimize X.
185 
186  if (cost.x < bestCost.x || (cost.x == bestCost.x && (cost.y < bestCost.y || (cost.y == bestCost.y && cost.z < bestCost.z))))
187  {
188  bestPos = r.getXY();
189  bestCost = cost;
190  }
191  }
192 
193  item.pos = bestPos;
194  canvas = max(canvas, bestPos + s);
195  Vec4i t(bestPos, bestPos + s);
196 
197  // Split maximal rectangles.
198 
199  for (int i = maxRects.getSize() - 1; i >= 0; i--)
200  {
201  Vec4i r = maxRects[i];
202  if (t.x >= r.z || t.y >= r.w || t.z <= r.x || t.w <= r.y)
203  continue;
204 
205  maxRects.removeSwap(i);
206  if (t.x > r.x) maxRects.add(Vec4i(r.x, r.y, t.x, r.w));
207  if (t.y > r.y) maxRects.add(Vec4i(r.x, r.y, r.z, t.y));
208  if (t.z < r.z) maxRects.add(Vec4i(t.z, r.y, r.z, r.w));
209  if (t.w < r.w) maxRects.add(Vec4i(r.x, t.w, r.z, r.w));
210  }
211 
212  // Remove duplicates.
213 
214  for (int i = maxRects.getSize() - 1; i >= 0; i--)
215  {
216  const Vec4i& a = maxRects[i];
217  for (int j = 0; j < maxRects.getSize(); j++)
218  {
219  const Vec4i& b = maxRects[j];
220  if (i != j && a.x >= b.x && a.y >= b.y && a.z <= b.z && a.w <= b.w)
221  {
222  maxRects.removeSwap(i);
223  break;
224  }
225  }
226  }
227  }
228 
229  // Determine final size.
230 
231  m_atlasSize = 1;
232  for (int i = 0; i < m_items.getSize(); i++)
233  m_atlasSize = max(m_atlasSize, m_items[i].pos + m_items[i].size);
234 }
235 
236 //------------------------------------------------------------------------
237 
238 void TextureAtlas::createAtlas(void)
239 {
240  Image* image = new Image(m_atlasSize, m_format);
241  m_atlasTexture = Texture(image);
242  image->clear();
243 
244  for (int i = 0; i < m_items.getSize(); i++)
245  {
246  const Item& item = m_items[i];
247  Vec2i pos = item.pos + item.border;
248  Vec2i size = item.size - item.border * 2;
249  Vec2i wrap = (item.wrap) ? size - 1 : 0;
250 
251  image->set(pos, *item.texture.getImage(), 0, size);
252  for (int j = 0; j < item.border; j++)
253  {
254  image->set(pos + Vec2i(-1, 0), *image, pos + Vec2i(wrap.x, 0), Vec2i(1, size.y));
255  image->set(pos + Vec2i(size.x, 0), *image, pos + Vec2i(size.x - 1 - wrap.x, 0), Vec2i(1, size.y));
256  image->set(pos + Vec2i(-1, -1), *image, pos + Vec2i(-1, wrap.y), Vec2i(size.x + 2, 1));
257  image->set(pos + Vec2i(-1, size.y), *image, pos + Vec2i(-1, size.y - 1 - wrap.y), Vec2i(size.x + 2, 1));
258  pos -= 1;
259  size += 2;
260  }
261  }
262 }
263 
264 //------------------------------------------------------------------------
#define NULL
Definition: Defs.hpp:39
void clear(U32 abgr=0)
Definition: Image.hpp:160
const Image * getImage(void) const
Definition: Texture.hpp:64
#define FW_S32_MAX
Definition: Defs.hpp:113
Vec2f getTextureSizeF(const Texture &tex)
void clear(void)
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint param GLuint GLenum GLint param GLhandleARB programObj GLenum GLenum GLsizei GLsizei height GLenum GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: DLLImports.inl:349
#define FW_SORT_ARRAY(ARRAY, TYPE, COMPARE)
Definition: Sort.hpp:103
FW_CUDA_FUNC F32 sqrt(F32 a)
Definition: Math.hpp:39
Vec2f getTexturePosF(const Texture &tex)
bool addTexture(const Texture &tex, int border=1, bool wrap=true)
void reset(S size=0)
Definition: Array.hpp:317
float F32
Definition: Defs.hpp:89
void set(const Vec2i &dstPos, const Image &src, const Vec2i &srcPos, const Vec2i &size)
Definition: Image.hpp:157
FW_CUDA_FUNC T min(const VectorBase< T, L, S > &v)
Definition: Math.hpp:461
FW_CUDA_FUNC T max(const VectorBase< T, L, S > &v)
Definition: Math.hpp:462
#define FW_ASSERT(X)
Definition: Defs.hpp:67
signed int S32
Definition: Defs.hpp:88
Vec2i getTextureSize(const Texture &tex)
FW_CUDA_FUNC Vec2i getXY(void) const
Definition: Math.hpp:291
Vec2i getAtlasSize(void)
bool exists(void) const
Definition: Texture.hpp:62
T & add(void)
Definition: Array.hpp:384
bool hasError(void)
Definition: Defs.cpp:289
const Vec2i & getSize(void) const
Definition: Image.hpp:143
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint param GLuint GLenum GLint param GLhandleARB programObj GLenum GLenum GLsizei GLsizei height GLenum GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: DLLImports.inl:349
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void * image
Definition: DLLImports.inl:60
Vec2i getTexturePos(const Texture &tex)
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr size
Definition: DLLImports.inl:319
S getSize(void) const
Definition: Array.hpp:188
TextureAtlas(const ImageFormat &format=ImageFormat::ABGR_8888)