sprite_resource.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "array.h"
  6. #include "compile_options.h"
  7. #include "config.h"
  8. #include "json_object.h"
  9. #include "reader_writer.h"
  10. #include "resource_manager.h"
  11. #include "sjson.h"
  12. #include "sprite_resource.h"
  13. #include "string_utils.h"
  14. #include "vector2.h"
  15. #include "vector4.h"
  16. namespace crown
  17. {
  18. namespace sprite_resource_internal
  19. {
  20. struct SpriteFrame
  21. {
  22. StringId32 name;
  23. Vector4 region; // [x0, y0, x1, y1]
  24. Vector2 scale; // [Sx, Sy]
  25. Vector2 offset; // [Ox, Oy]
  26. };
  27. void parse_frame(const char* json, SpriteFrame& frame)
  28. {
  29. TempAllocator512 ta;
  30. JsonObject obj(ta);
  31. sjson::parse(json, obj);
  32. frame.name = sjson::parse_string_id(obj["name"]);
  33. frame.region = sjson::parse_vector4(obj["region"]);
  34. frame.offset = sjson::parse_vector2(obj["offset"]);
  35. frame.scale = sjson::parse_vector2(obj["scale"]);
  36. }
  37. void compile(const char* path, CompileOptions& opts)
  38. {
  39. Buffer buf = opts.read(path);
  40. TempAllocator4096 ta;
  41. JsonObject object(ta);
  42. sjson::parse(buf, object);
  43. JsonArray frames(ta);
  44. sjson::parse_array(object["frames"], frames);
  45. // Read width/height
  46. const f32 width = sjson::parse_float(object["width" ]);
  47. const f32 height = sjson::parse_float(object["height"]);
  48. const u32 num_frames = array::size(frames);
  49. Array<f32> vertices(default_allocator());
  50. Array<u16> indices(default_allocator());
  51. u32 num_idx = 0;
  52. for (u32 i = 0; i < num_frames; ++i)
  53. {
  54. SpriteFrame frame;
  55. parse_frame(frames[i], frame);
  56. const SpriteFrame& fd = frame;
  57. // Compute uv coords
  58. const f32 u0 = fd.region.x / width;
  59. const f32 v0 = fd.region.y / height;
  60. const f32 u1 = (fd.region.x + fd.region.z) / width;
  61. const f32 v1 = (fd.region.y + fd.region.w) / height;
  62. // Compute positions
  63. const f32 w = fd.region.z / CROWN_DEFAULT_PIXELS_PER_METER;
  64. const f32 h = fd.region.w / CROWN_DEFAULT_PIXELS_PER_METER;
  65. const f32 x0 = fd.scale.x * (-w * 0.5f) + fd.offset.x;
  66. const f32 y0 = fd.scale.y * (-h * 0.5f) + fd.offset.y;
  67. const f32 x1 = fd.scale.x * ( w * 0.5f) + fd.offset.x;
  68. const f32 y1 = fd.scale.y * ( h * 0.5f) + fd.offset.y;
  69. array::push_back(vertices, x0); array::push_back(vertices, y0); // position
  70. array::push_back(vertices, u0); array::push_back(vertices, v0); // uv
  71. array::push_back(vertices, x1); array::push_back(vertices, y0); // position
  72. array::push_back(vertices, u1); array::push_back(vertices, v0); // uv
  73. array::push_back(vertices, x1); array::push_back(vertices, y1); // position
  74. array::push_back(vertices, u1); array::push_back(vertices, v1); // uv
  75. array::push_back(vertices, x0); array::push_back(vertices, y1); // position
  76. array::push_back(vertices, u0); array::push_back(vertices, v1); // uv
  77. array::push_back(indices, u16(num_idx)); array::push_back(indices, u16(num_idx + 1)); array::push_back(indices, u16(num_idx + 2));
  78. array::push_back(indices, u16(num_idx)); array::push_back(indices, u16(num_idx + 2)); array::push_back(indices, u16(num_idx + 3));
  79. num_idx += 4;
  80. }
  81. const u32 num_vertices = array::size(vertices) / 4; // 4 components per vertex
  82. const u32 num_indices = array::size(indices);
  83. // Write
  84. opts.write(RESOURCE_VERSION_SPRITE);
  85. opts.write(num_vertices);
  86. for (u32 i = 0; i < array::size(vertices); i++)
  87. {
  88. opts.write(vertices[i]);
  89. }
  90. opts.write(num_indices);
  91. for (u32 i = 0; i < array::size(indices); i++)
  92. {
  93. opts.write(indices[i]);
  94. }
  95. }
  96. void* load(File& file, Allocator& a)
  97. {
  98. BinaryReader br(file);
  99. u32 version;
  100. br.read(version);
  101. u32 num_verts;
  102. br.read(num_verts);
  103. const bgfx::Memory* vbmem = bgfx::alloc(num_verts * sizeof(f32) * 4);
  104. br.read(vbmem->data, num_verts * sizeof(f32) * 4);
  105. u32 num_inds;
  106. br.read(num_inds);
  107. const bgfx::Memory* ibmem = bgfx::alloc(num_inds * sizeof(u16));
  108. br.read(ibmem->data, num_inds * sizeof(u16));
  109. SpriteResource* so = (SpriteResource*) a.allocate(sizeof(SpriteResource));
  110. so->vbmem = vbmem;
  111. so->ibmem = ibmem;
  112. return so;
  113. }
  114. void online(StringId64 id, ResourceManager& rm)
  115. {
  116. SpriteResource* so = (SpriteResource*) rm.get(RESOURCE_TYPE_SPRITE, id);
  117. bgfx::VertexDecl decl;
  118. decl.begin()
  119. .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
  120. .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float, false)
  121. .end();
  122. so->vb = bgfx::createVertexBuffer(so->vbmem, decl);
  123. so->ib = bgfx::createIndexBuffer(so->ibmem);
  124. }
  125. void offline(StringId64 id, ResourceManager& rm)
  126. {
  127. SpriteResource* so = (SpriteResource*) rm.get(RESOURCE_TYPE_SPRITE, id);
  128. bgfx::destroyVertexBuffer(so->vb);
  129. bgfx::destroyIndexBuffer(so->ib);
  130. }
  131. void unload(Allocator& a, void* resource)
  132. {
  133. a.deallocate(resource);
  134. }
  135. } // namespace sprite_resource_internal
  136. namespace sprite_animation_resource_internal
  137. {
  138. void compile(const char* path, CompileOptions& opts)
  139. {
  140. Buffer buf = opts.read(path);
  141. TempAllocator4096 ta;
  142. JsonObject object(ta);
  143. JsonArray object_frames(ta);
  144. Array<u32> frames(default_allocator());
  145. float total_time = 0.0f;
  146. sjson::parse(buf, object);
  147. sjson::parse_array(object["frames"], object_frames);
  148. array::resize(frames, array::size(object_frames));
  149. for (u32 i = 0; i < array::size(object_frames); ++i)
  150. frames[i] = (u32)sjson::parse_float(object_frames[i]);
  151. total_time = sjson::parse_float(object["total_time"]);
  152. // Write
  153. SpriteAnimationResource sar;
  154. sar.version = RESOURCE_VERSION_SPRITE_ANIMATION;
  155. sar.num_frames = array::size(frames);
  156. sar.total_time = total_time;
  157. opts.write(sar.version);
  158. opts.write(sar.num_frames);
  159. opts.write(sar.total_time);
  160. for (u32 i = 0; i < array::size(frames); i++)
  161. opts.write(frames[i]);
  162. }
  163. void* load(File& file, Allocator& a)
  164. {
  165. const u32 file_size = file.size();
  166. void* res = a.allocate(file_size);
  167. file.read(res, file_size);
  168. CE_ASSERT(*(u32*)res == RESOURCE_VERSION_SPRITE, "Wrong version");
  169. return res;
  170. }
  171. void unload(Allocator& a, void* resource)
  172. {
  173. a.deallocate(resource);
  174. }
  175. } // namespace sprite_animation_resource_internal
  176. namespace sprite_animation_resource
  177. {
  178. const u32* frames(const SpriteAnimationResource* sar)
  179. {
  180. return (u32*)&sar[1];
  181. }
  182. } // namespace sprite_animation_resource
  183. } // namespace crown