TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Map2D.h
Go to the documentation of this file.
1 
10 #ifndef G3D_Map2D_h
11 #define G3D_Map2D_h
12 
13 #include "G3D/platform.h"
14 #include "G3D/g3dmath.h"
15 #include "G3D/Array.h"
16 #include "G3D/vectorMath.h"
17 #include "G3D/Vector2int16.h"
18 #include "G3D/ReferenceCount.h"
19 #include "G3D/AtomicInt32.h"
20 #include "G3D/GThread.h"
21 #include "G3D/Rect2D.h"
22 #include "G3D/WrapMode.h"
23 
24 #include <string>
25 
26 namespace G3D {
27 namespace _internal {
28 
30 template<typename Storage> class _GetComputeType {
31 public:
32  typedef Storage Type;
33 };
34 
35 } // _internal
36 } // G3D
37 
38 // This weird syntax is needed to support VC6, which doesn't
39 // properly implement template overloading.
40 #define DECLARE_COMPUTE_TYPE(StorageType, ComputeType) \
41 namespace G3D { \
42  namespace _internal { \
43  template<> class _GetComputeType < StorageType > { \
44  public: \
45  typedef ComputeType Type; \
46  }; \
47  } \
48 }
49 
52 
55 DECLARE_COMPUTE_TYPE( int32, float64)
56 DECLARE_COMPUTE_TYPE( int64, float64)
57 
62 
63 DECLARE_COMPUTE_TYPE( Vector2, Vector2)
65 
66 DECLARE_COMPUTE_TYPE( Vector3, Vector3)
68 
69 DECLARE_COMPUTE_TYPE( Vector4, Vector4)
70 
71 DECLARE_COMPUTE_TYPE( Color3, Color3)
72 DECLARE_COMPUTE_TYPE( Color3uint8, Color3)
73 
74 DECLARE_COMPUTE_TYPE( Color4, Color4)
75 DECLARE_COMPUTE_TYPE( Color4uint8, Color4)
76 #undef DECLARE_COMPUTE_TYPE
77 
78 namespace G3D {
79 
169 template< typename Storage,
172 
173 //
174 // It doesn't make sense to automatically convert from Compute back to Storage
175 // because the rounding rule (and scaling) is application dependent.
176 // Thus the interpolation methods all return type Compute.
177 //
178 
179 public:
180 
181  typedef Storage StorageType;
182  typedef Compute ComputeType;
184  typedef shared_ptr<Map2D> Ref;
185 
186 protected:
187 
188  Storage ZERO;
189 
191  uint32 w;
192 
194  uint32 h;
195 
197 
201 
203 
205  const Storage& slowGet(int x, int y, WrapMode wrap) {
206  switch (wrap) {
207  case WrapMode::CLAMP:
208  return fastGet(iClamp(x, 0, w - 1), iClamp(y, 0, h - 1));
209 
210  case WrapMode::TILE:
211  return fastGet(iWrap(x, w), iWrap(y, h));
212 
213  case WrapMode::ZERO:
214  return ZERO;
215 
216  case WrapMode::ERROR:
217  alwaysAssertM(((uint32)x < w) && ((uint32)y < h),
218  format("Index out of bounds: (%d, %d), w = %d, h = %d",
219  x, y, w, h));
220 
221  // intentionally fall through
222  case WrapMode::IGNORE:
223  // intentionally fall through
224  default:
225  {
226  static Storage temp;
227  return temp;
228  }
229  }
230  }
231 
232 public:
233 
235  inline const Storage& fastGet(int x, int y) const {
236  debugAssert(((uint32)x < w) && ((uint32)y < h));
237  return data[x + y * w];
238  }
239 
241  inline void fastSet(int x, int y, const Storage& v) {
242  debugAssert(((uint32)x < w) && ((uint32)y < h));
243  data[x + y * w] = v;
244  }
245 
246 protected:
247 
251  Compute bicubic(const Compute* ctrl, double s) const {
252 
253  // f = B * S * ctrl'
254 
255  // B matrix: Catmull-Rom spline basis
256  static const double B[4][4] = {
257  { 0.0, -0.5, 1.0, -0.5},
258  { 1.0, 0.0, -2.5, 1.5},
259  { 0.0, 0.5, 2.0, -1.5},
260  { 0.0, 0.0, -0.5, 0.5}};
261 
262  // S: Powers of the fraction
263  double S[4];
264  double s2 = s * s;
265  S[0] = 1.0;
266  S[1] = s;
267  S[2] = s2;
268  S[3] = s2 * s;
269 
270  Compute sum(ZERO);
271 
272  for (int c = 0; c < 4; ++c) {
273  double coeff = 0.0;
274  for (int power = 0; power < 4; ++power) {
275  coeff += B[c][power] * S[power];
276  }
277  sum += ctrl[c] * coeff;
278  }
279 
280  return sum;
281  }
282 
283 
284  Map2D(int w, int h, WrapMode wrap) : w(0), h(0), _wrapMode(wrap), m_changed(1) {
285  ZERO = Storage(Compute(Storage()) * 0);
286  resize(w, h);
287  }
288 
289 public:
290 
297 
298  static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) {
299  return Ref(new Map2D(w, h, wrap));
300  }
301 
304  void resize(uint32 newW, uint32 newH) {
305  if ((newW != w) || (newH != h)) {
306  w = newW;
307  h = newH;
308  data.resize(w * h);
309  setChanged(true);
310  }
311  }
312 
318  bool changed() {
319  return m_changed.value() != 0;
320  }
321 
323  void setChanged(bool c) {
324  m_changed = c ? 1 : 0;
325  }
326 
329  Storage* getCArray() {
330  return data.getCArray();
331  }
332 
333 
334  const Storage* getCArray() const {
335  return data.getCArray();
336  }
337 
338 
341  return data;
342  }
343 
344 
345  const Array<Storage>& getArray() const {
346  return data;
347  }
348 
350  inline bool inBounds(int x, int y) const {
351  return (((uint32)x < w) && ((uint32)y < h));
352  }
353 
355  inline bool inBounds(const Vector2int16& v) const {
356  return inBounds(v.x, v.y);
357  }
358 
367  inline const Storage& get(int x, int y, WrapMode wrap) const {
368  if (((uint32)x < w) && ((uint32)y < h)) {
369  return data[x + y * w];
370  } else {
371  // Remove the const to allow a slowGet on this object
372  // (we're returning a const reference so this is ok)
373  return const_cast<Type*>(this)->slowGet(x, y, wrap);
374  }
375 # ifndef G3D_WINDOWS
376  // gcc gives a useless warning that the above code might reach the end of the function;
377  // we use this line to supress the warning.
378  return ZERO;
379 # endif
380  }
381 
382  inline const Storage& get(int x, int y) const {
383  return get(x, y, _wrapMode);
384  }
385 
386  inline const Storage& get(const Vector2int16& p) const {
387  return get(p.x, p.y, _wrapMode);
388  }
389 
390  inline const Storage& get(const Vector2int16& p, WrapMode wrap) const {
391  return get(p.x, p.y, wrap);
392  }
393 
394  inline Storage& get(int x, int y, WrapMode wrap) {
395  return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y, wrap));
396 # ifndef G3D_WINDOWS
397  // gcc gives a useless warning that the above code might reach the end of the function;
398  // we use this line to supress the warning.
399  return ZERO;
400 # endif
401  }
402 
403  inline Storage& get(int x, int y) {
404  return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y));
405 # ifndef G3D_WINDOWS
406  // gcc gives a useless warning that the above code might reach the end of the function;
407  // we use this line to supress the warning.
408  return ZERO;
409 # endif
410  }
411 
412  inline Storage& get(const Vector2int16& p) {
413  return get(p.x, p.y);
414  }
415 
417  inline void set(const Vector2int16& p, const Storage& v) {
418  set(p.x, p.y, v);
419  }
420 
422  void set(int x, int y, const Storage& v, WrapMode wrap) {
423  setChanged(true);
424  if (((uint32)x < w) && ((uint32)y < h)) {
425  // In bounds, wrapping isn't an issue.
426  data[x + y * w] = v;
427  } else {
428  const_cast<Storage&>(slowGet(x, y, wrap)) = v;
429  }
430  }
431 
432  void set(int x, int y, const Storage& v) {
433  set(x, y, v, _wrapMode);
434  }
435 
436 
437  void setAll(const Storage& v) {
438  for(int i = 0; i < data.size(); ++i) {
439  data[i] = v;
440  }
441  setChanged(true);
442  }
443 
445  template<class T>
446  void set(const shared_ptr<Map2D<Storage, T> >& src) {
447  debugAssert(src->width() == width());
448  debugAssert(src->height() == height());
449  const Array<Storage>& s = src->data;
450  int N = w * h;
451  for (int i = 0; i < N; ++i) {
452  data[i] = s[i];
453  }
454  setChanged(true);
455  }
456 
458  void maybeFlipVertical(bool flip) {
459  if (flip) {
460  flipVertical();
461  }
462  }
463 
464  virtual void flipVertical() {
465  int halfHeight = h/2;
466  Storage* d = data.getCArray();
467  for (int y = 0; y < halfHeight; ++y) {
468  int o1 = y * w;
469  int o2 = (h - y - 1) * w;
470  for (int x = 0; x < (int)w; ++x) {
471  int i1 = o1 + x;
472  int i2 = o2 + x;
473  Storage temp = d[i1];
474  d[i1] = d[i2];
475  d[i2] = temp;
476  }
477  }
478  setChanged(true);
479  }
480 
481  virtual void flipHorizontal() {
482  int halfWidth = w / 2;
483  Storage* d = data.getCArray();
484  for (int x = 0; x < halfWidth; ++x) {
485  for (int y = 0; y < (int)h; ++y) {
486  int i1 = y * w + x;
487  int i2 = y * w + (w - x - 1);
488  Storage temp = d[i1];
489  d[i1] = d[i2];
490  d[i2] = temp;
491  }
492  }
493  setChanged(true);
494  }
495 
499  virtual void crop(int newX, int newY, int newW, int newH) {
500  alwaysAssertM(newX + newW <= (int)w, "Cannot grow when cropping");
501  alwaysAssertM(newY + newH <= (int)h, "Cannot grow when cropping");
502  alwaysAssertM(newX >= 0 && newY >= 0, "Origin out of bounds.");
503 
504  // Always safe to copy towards the upper left, provided
505  // that we're iterating towards the lower right. This lets us avoid
506  // reallocating the underlying array.
507  for (int y = 0; y < newH; ++y) {
508  for (int x = 0; x < newW; ++x) {
509  data[x + y * newW] = data[(x + newX) + (y + newY) * w];
510  }
511  }
512 
513  resize(newW, newH);
514  }
515 
517  virtual void crop(const Rect2D& rect) {
518  crop(iRound(rect.x0()), iRound(rect.y0()), iRound(rect.x1()) - iRound(rect.x0()), iRound(rect.y1()) - iRound(rect.y0()));
519  }
520 
524  inline Compute nearest(float x, float y, WrapMode wrap) const {
525  int ix = iRound(x);
526  int iy = iRound(y);
527  return Compute(get(ix, iy, wrap));
528  }
529 
530  inline Compute nearest(float x, float y) const {
531  return nearest(x, y, _wrapMode);
532  }
533 
534  inline Compute nearest(const Vector2& p) const {
535  return nearest(p.x, p.y);
536  }
537 
539  Compute average() const {
540  if ((w == 0) || (h == 0)) {
541  return ZERO;
542  }
543 
544  // To avoid overflows, compute the average of row averages
545 
546  Compute rowSum = ZERO;
547  for (unsigned int y = 0; y < h; ++y) {
548  Compute sum = ZERO;
549  int offset = y * w;
550  for (unsigned int x = 0; x < w; ++x) {
551  sum += Compute(data[offset + x]);
552  }
553  rowSum += sum * (1.0f / w);
554  }
555 
556  return rowSum * (1.0f / h);
557  }
558 
566  Compute bilinear(float x, float y, WrapMode wrap) const {
567  const int i = iFloor(x);
568  const int j = iFloor(y);
569 
570  const float fX = x - i;
571  const float fY = y - j;
572 
573  // Horizontal interpolation, first row
574  const Compute& t0 = get(i, j, wrap);
575  const Compute& t1 = get(i + 1, j, wrap);
576 
577  // Horizontal interpolation, second row
578  const Compute& t2 = get(i, j + 1, wrap);
579  const Compute& t3 = get(i + 1, j + 1, wrap);
580 
581  const Compute& A = lerp(t0, t1, fX);
582  const Compute& B = lerp(t2, t3, fX);
583 
584  // Vertical interpolation
585  return lerp(A, B, fY);
586  }
587 
588  Compute bilinear(float x, float y) const {
589  return bilinear(x, y, _wrapMode);
590  }
591 
592  inline Compute bilinear(const Vector2& p) const {
593  return bilinear(p.x, p.y, _wrapMode);
594  }
595 
596  inline Compute bilinear(const Vector2& p, WrapMode wrap) const {
597  return bilinear(p.x, p.y, wrap);
598  }
599 
604  Compute bicubic(float x, float y, WrapMode wrap) const {
605  int i = iFloor(x);
606  int j = iFloor(y);
607  float fX = x - i;
608  float fY = y - j;
609 
610  Compute vsample[4];
611  for (int v = 0; v < 4; ++v) {
612 
613  // Horizontal interpolation
614  Compute hsample[4];
615  for (int u = 0; u < 4; ++u) {
616  hsample[u] = Compute(get(i + u - 1, j + v - 1, wrap));
617  }
618 
619  vsample[v] = bicubic(hsample, fX);
620  }
621 
622  // Vertical interpolation
623  return bicubic(vsample, fY);
624  }
625 
626  Compute bicubic(float x, float y) const {
627  return bicubic(x, y, _wrapMode);
628  }
629 
630  inline Compute bicubic(const Vector2& p, WrapMode wrap) const {
631  return bicubic(p.x, p.y, wrap);
632  }
633 
634  inline Compute bicubic(const Vector2& p) const {
635  return bicubic(p.x, p.y, _wrapMode);
636  }
637 
639  inline int32 width() const {
640  return (int32)w;
641  }
642 
643 
645  inline int32 height() const {
646  return (int32)h;
647  }
648 
649 
651  Vector2int16 size() const {
652  return Vector2int16(w, h);
653  }
654 
657  return Rect2D::xywh(0, 0, w, h);
658  }
659 
661  size_t sizeInMemory() const {
662  return data.size() * sizeof(Storage) + sizeof(*this);
663  }
664 
665 
666  WrapMode wrapMode() const {
667  return _wrapMode;
668  }
669 
670 
672  _wrapMode = m;
673  }
674 };
675 
676 
677 
678 }
679 
680 #endif // G3D_IMAGE_H
int32 height() const
Definition: Map2D.h:645
Map2D< Storage, Compute > Type
Definition: Map2D.h:183
Compute nearest(float x, float y, WrapMode wrap) const
Definition: Map2D.h:524
Storage ZERO
Definition: Map2D.h:188
void set(int x, int y, const Storage &v, WrapMode wrap)
Definition: Map2D.h:422
int8_t int8
Definition: Define.h:148
Compute bicubic(float x, float y, WrapMode wrap) const
Definition: Map2D.h:604
bool changed()
Definition: Map2D.h:318
size_t sizeInMemory() const
Definition: Map2D.h:661
Rect2D rect2DBounds() const
Definition: Map2D.h:656
void resize(size_t n, bool shrinkIfNecessary=true)
Definition: Array.h:490
float y0() const
Definition: Rect2D.h:184
Compute average() const
Definition: Map2D.h:539
Array< Storage > & getArray()
Definition: Map2D.h:340
int64_t int64
Definition: Define.h:145
#define DECLARE_COMPUTE_TYPE(StorageType, ComputeType)
Definition: Map2D.h:40
Definition: WrapMode.h:60
Vector2int16
Definition: Vector2int16.h:28
Vector2int16 size() const
Definition: Map2D.h:651
Mutual exclusion lock used for synchronization.
Definition: GMutex.h:76
Definition: WrapMode.h:61
Array< Storage > data
Definition: Map2D.h:202
double float64
Definition: g3dmath.h:173
int iRound(double fValue)
Definition: g3dmath.h:226
const Storage * getCArray() const
Definition: Map2D.h:334
T * getCArray()
Definition: Array.h:256
Definition: AABox.h:25
void maybeFlipVertical(bool flip)
Definition: Map2D.h:458
Definition: AtomicInt32.h:29
Definition: WrapMode.h:63
Definition: Map2D.h:30
int iFloor(double fValue)
Definition: g3dmath.h:603
Definition: Map2D.h:171
RET_TYPE Compute(float x, float y, float center_offset, float size)
Definition: GridDefines.h:177
virtual void crop(const Rect2D &rect)
Definition: Map2D.h:517
Storage Type
Definition: Map2D.h:32
Compute bilinear(float x, float y) const
Definition: Map2D.h:588
Definition: Rect2D.h:40
Compute bicubic(float x, float y) const
Definition: Map2D.h:626
GMutex mutex
Definition: Map2D.h:296
static Ref create(int w=0, int h=0, WrapMode wrap=WrapMode::ERROR)
Definition: Map2D.h:298
Compute bilinear(const Vector2 &p, WrapMode wrap) const
Definition: Map2D.h:596
float wrap(float t, float lo, float hi)
Definition: g3dmath.h:495
uint32 h
Definition: Map2D.h:194
void setAll(const Storage &v)
Definition: Map2D.h:437
float y
Definition: Vector2.h:50
float y1() const
Definition: Rect2D.h:188
Definition: ReferenceCount.h:24
const Storage & slowGet(int x, int y, WrapMode wrap)
Definition: Map2D.h:205
int32 width() const
Definition: Map2D.h:639
const Storage & fastGet(int x, int y) const
Definition: Map2D.h:235
Definition: WrapMode.h:59
shared_ptr< Map2D > Ref
Definition: Map2D.h:184
virtual void flipHorizontal()
Definition: Map2D.h:481
Definition: WrapMode.h:62
#define debugAssert(exp)
Definition: debugAssert.h:160
uint32 w
Definition: Map2D.h:191
float float32
Definition: g3dmath.h:172
WrapMode _wrapMode
Definition: Map2D.h:196
void set(int x, int y, const Storage &v)
Definition: Map2D.h:432
int32_t int32
Definition: Define.h:146
void fastSet(int x, int y, const Storage &v)
Definition: Map2D.h:241
Storage StorageType
Definition: Map2D.h:181
uint32_t uint32
Definition: Define.h:150
uint64_t uint64
Definition: Define.h:149
T * data
Definition: Array.h:103
G3D::int16 y
Definition: Vector2int16.h:38
uint16_t uint16
Definition: Define.h:151
float x0() const
Definition: Rect2D.h:176
float x
Definition: Vector2.h:49
Storage * getCArray()
Definition: Map2D.h:329
std::string __cdecl format(const char *fmt...) G3D_CHECK_PRINTF_ARGS
bool inBounds(const Vector2int16 &v) const
Definition: Map2D.h:355
int size() const
Definition: Array.h:430
Compute bicubic(const Vector2 &p, WrapMode wrap) const
Definition: Map2D.h:630
Map2D(int w, int h, WrapMode wrap)
Definition: Map2D.h:284
int32 value() const
Definition: AtomicInt32.h:67
void set(const shared_ptr< Map2D< Storage, T > > &src)
Definition: Map2D.h:446
void setWrapMode(WrapMode m)
Definition: Map2D.h:671
AtomicInt32 m_changed
Definition: Map2D.h:200
void setChanged(bool c)
Definition: Map2D.h:323
int iWrap(int val, int hi)
Definition: g3dmath.h:594
Compute ComputeType
Definition: Map2D.h:182
const Array< Storage > & getArray() const
Definition: Map2D.h:345
WrapMode wrapMode() const
Definition: Map2D.h:666
void set(const Vector2int16 &p, const Storage &v)
Definition: Map2D.h:417
Compute bicubic(const Compute *ctrl, double s) const
Definition: Map2D.h:251
uint8_t uint8
Definition: Define.h:152
Compute bilinear(float x, float y, WrapMode wrap) const
Definition: Map2D.h:566
double lerp(double a, double b, double f)
Definition: g3dmath.h:189
int16_t int16
Definition: Define.h:147
Compute bicubic(const Vector2 &p) const
Definition: Map2D.h:634
static Rect2D xywh(float x, float y, float w, float h)
Definition: Rect2D.h:260
uint32_t uint32
Definition: g3dmath.h:168
G3D::int16 x
Definition: Vector2int16.h:37
bool inBounds(int x, int y) const
Definition: Map2D.h:350
#define alwaysAssertM(exp, message)
Definition: debugAssert.h:165
int iClamp(int val, int low, int hi)
Definition: g3dmath.h:545
void resize(uint32 newW, uint32 newH)
Definition: Map2D.h:304
Compute nearest(const Vector2 &p) const
Definition: Map2D.h:534
Compute bilinear(const Vector2 &p) const
Definition: Map2D.h:592
Definition: Vector2int16.h:22
float x1() const
Definition: Rect2D.h:180
virtual void crop(int newX, int newY, int newW, int newH)
Definition: Map2D.h:499
virtual void flipVertical()
Definition: Map2D.h:464
Definition: WrapMode.h:55
Compute nearest(float x, float y) const
Definition: Map2D.h:530