CloudAtlas.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include <string.h>
  2. #include <kapusha/render/Texture.h>
  3. #include "CloudAtlas.h"
  4. CloudAtlas::CloudAtlas(kapusha::vec2i size)
  5. : size_(size)
  6. , pix2tex_(1.f / size.x, 1.f / size.y)
  7. , pixels_(new lmap_texel_t[size_.x * size_.y])
  8. {
  9. for (int i = 0; i < (size_.x * size_.y); ++i)
  10. #if LIGHTMAP_FORMAT == 1
  11. pixels_[i] = 0xf800;
  12. #else
  13. *reinterpret_cast<kapusha::vec4<kapusha::u8>*>(pixels_+i) =
  14. kapusha::vec4<kapusha::u8>(255, 0, 0, 0);
  15. #endif
  16. root_ = new Node(kapusha::rect2i(size_));
  17. }
  18. CloudAtlas::~CloudAtlas(void)
  19. {
  20. for(Node *n = root_; n != 0;)
  21. {
  22. Node *next = n->next;
  23. delete n;
  24. n = next;
  25. }
  26. delete pixels_;
  27. }
  28. kapusha::Texture *CloudAtlas::texture() const
  29. {
  30. kapusha::Texture *ret = new kapusha::Texture();
  31. #if LIGHTMAP_FORMAT == 1
  32. kapusha::Texture::Meta::PixelFormat format = kapusha::Texture::Meta::RGB565;
  33. //! \todo #elif LIGHTMAP_FORMAT == 2
  34. // ETC1
  35. #else
  36. kapusha::Texture::Meta::PixelFormat format = kapusha::Texture::Meta::RGBA8888;
  37. #endif
  38. ret->upload(kapusha::Texture::Meta(size_, format),
  39. pixels_);
  40. return ret;
  41. }
  42. kapusha::rect2f CloudAtlas::addImage(kapusha::vec2i size, const void *data)
  43. {
  44. for(Node *n = root_;;)
  45. {
  46. if (n->insert(size))
  47. {
  48. kapusha::rect2i r = n->rect;
  49. KP_ASSERT(r.size() == size);
  50. if (n == root_)
  51. root_ = n->next;
  52. if (n->prev)
  53. n->prev->next = n->next;
  54. if (n->next)
  55. n->next->prev = n->prev;
  56. delete n;
  57. const kapusha::vec4<kapusha::u8> *p_in =
  58. reinterpret_cast<const kapusha::vec4<kapusha::u8>*>(data);
  59. lmap_texel_t *p_out = pixels_ + r.bottom() * size_.x + r.left();
  60. for (int y = 0; y < size.y; ++y, p_out += size_.x, p_in += size.x)
  61. {
  62. #if LIGHTMAP_FORMAT == 1
  63. for (int x = 0; x < size.x; ++x)
  64. p_out[x] =
  65. ((p_in[x].x&0xf8) << 8) |
  66. ((p_in[x].y&0xfc) << 3) |
  67. (p_in[x].z >> 3);
  68. #else
  69. memcpy(p_out, p_in, sizeof(lmap_texel_t) * size.x);
  70. #endif
  71. }
  72. return kapusha::rect2f(kapusha::vec2f(r.left()+.5f, r.top()) * pix2tex_,
  73. kapusha::vec2f(r.right(), r.bottom()+.5f) * pix2tex_);
  74. }
  75. if (!n->next)
  76. break;
  77. // detect unlink
  78. if (n->next->prev != n)
  79. {
  80. if (n == root_)
  81. root_ = n->next;
  82. Node *t = n->next;
  83. if (n->prev)
  84. n->prev->next = t;
  85. if (n->next)
  86. n->next->prev = n->prev;
  87. delete n;
  88. n = t;
  89. } else {
  90. n = n->next;
  91. }
  92. }
  93. return kapusha::rect2f(-1.f);
  94. }
  95. bool CloudAtlas::Node::insert(kapusha::vec2i size)
  96. {
  97. // early check whether it'll fit
  98. if (rect.width() < size.x || rect.height() < size.y)
  99. return false;
  100. // if it fits exactly, return it
  101. if (rect.size() == size)
  102. return true;
  103. // split
  104. kapusha::vec2i diff = rect.size() - size;
  105. kapusha::rect2i r[2];
  106. if (diff.x > diff.y)
  107. {
  108. r[0] = kapusha::rect2i(rect.left(), rect.bottom(),
  109. rect.right() - diff.x, rect.top());
  110. r[1] = kapusha::rect2i(rect.right() - diff.x, rect.bottom(),
  111. rect.right(), rect.top());
  112. } else {
  113. r[0] = kapusha::rect2i(rect.left(), rect.bottom(),
  114. rect.right(), rect.top() - diff.y);
  115. r[1] = kapusha::rect2i(rect.left(), rect.top() - diff.y,
  116. rect.right(), rect.top());
  117. }
  118. // the insertage
  119. Node *newn[2];
  120. newn[0] = new Node(r[0]);
  121. newn[1] = new Node(r[1]);
  122. newn[0]->next = newn[1];
  123. newn[1]->prev = newn[0];
  124. if (prev)
  125. {
  126. prev->next = newn[0];
  127. newn[0]->prev = prev;
  128. }
  129. if (next)
  130. {
  131. next->prev = newn[1];
  132. newn[1]->next = next;
  133. }
  134. next = newn[0];
  135. return false;
  136. }