Adding deserialization of index buffer.
diff --git a/include/rive/core/binary_reader.hpp b/include/rive/core/binary_reader.hpp
index 69e37c1..4894bad 100644
--- a/include/rive/core/binary_reader.hpp
+++ b/include/rive/core/binary_reader.hpp
@@ -9,15 +9,16 @@
namespace rive {
class BinaryReader {
private:
- uint8_t* m_Position;
- uint8_t* m_End;
+ const uint8_t* m_Position;
+ const uint8_t* m_End;
bool m_Overflowed;
size_t m_Length;
void overflow();
public:
- BinaryReader(uint8_t* bytes, size_t length);
+ BinaryReader(const uint8_t* bytes, size_t length);
+ BinaryReader(Span<const uint8_t> span);
bool didOverflow() const;
bool reachedEnd() const;
diff --git a/include/rive/shapes/mesh.hpp b/include/rive/shapes/mesh.hpp
index 7816827..1f7761d 100644
--- a/include/rive/shapes/mesh.hpp
+++ b/include/rive/shapes/mesh.hpp
@@ -2,12 +2,17 @@
#define _RIVE_MESH_HPP_
#include "rive/generated/shapes/mesh_base.hpp"
#include "rive/span.hpp"
+#include "rive/refcnt.hpp"
namespace rive {
class MeshVertex;
+
class Mesh : public MeshBase {
+
protected:
+ class IndexBuffer : public std::vector<uint16_t>, public RefCnt {};
std::vector<MeshVertex*> m_Vertices;
+ rcp<IndexBuffer> m_IndexBuffer;
public:
StatusCode onAddedDirty(CoreContext* context) override;
@@ -17,6 +22,7 @@
void copyTriangleIndexBytes(const MeshBase& object) override;
#ifdef TESTING
std::vector<MeshVertex*>& vertices() { return m_Vertices; }
+ rcp<IndexBuffer> indices() { return m_IndexBuffer; }
#endif
};
} // namespace rive
diff --git a/src/core/binary_reader.cpp b/src/core/binary_reader.cpp
index d16ee13..b115e65 100644
--- a/src/core/binary_reader.cpp
+++ b/src/core/binary_reader.cpp
@@ -5,7 +5,10 @@
using namespace rive;
-BinaryReader::BinaryReader(uint8_t* bytes, size_t length) :
+BinaryReader::BinaryReader(Span<const uint8_t> span) :
+ BinaryReader(span.begin(), span.size()) {}
+
+BinaryReader::BinaryReader(const uint8_t* bytes, size_t length) :
m_Position(bytes),
m_End(bytes + length),
m_Overflowed(false),
@@ -57,7 +60,7 @@
return Span<const uint8_t>(m_Position, 0);
}
- uint8_t* start = m_Position;
+ const uint8_t* start = m_Position;
m_Position += length;
return Span<const uint8_t>(start, length);
}
diff --git a/src/shapes/mesh.cpp b/src/shapes/mesh.cpp
index b72a515..f8b41d4 100644
--- a/src/shapes/mesh.cpp
+++ b/src/shapes/mesh.cpp
@@ -1,5 +1,7 @@
#include "rive/shapes/mesh.hpp"
#include "rive/shapes/image.hpp"
+#include <limits>
+#include <cassert>
using namespace rive;
@@ -25,8 +27,17 @@
void Mesh::decodeTriangleIndexBytes(Span<const uint8_t> value) {
// decode the triangle index bytes
+ rcp<IndexBuffer> buffer = rcp<IndexBuffer>(new IndexBuffer());
+
+ BinaryReader reader(value);
+ while (!reader.reachedEnd()) {
+ uint64_t index = reader.readVarUint64();
+ assert(index < std::numeric_limits<uint16_t>::max());
+ buffer->push_back(index);
+ }
+ m_IndexBuffer = buffer;
}
void Mesh::copyTriangleIndexBytes(const MeshBase& object) {
- // copy the triangle indices from object
+ m_IndexBuffer = object.as<Mesh>()->m_IndexBuffer;
}
\ No newline at end of file
diff --git a/test/image_mesh_test.cpp b/test/image_mesh_test.cpp
index 3a983c7..d1575f2 100644
--- a/test/image_mesh_test.cpp
+++ b/test/image_mesh_test.cpp
@@ -12,7 +12,7 @@
#include <catch.hpp>
#include <cstdio>
-TEST_CASE("image with mesh loads correctly", "[assets]") {
+TEST_CASE("image with mesh loads correctly", "[mesh]") {
RiveFileReader reader("../../test/assets/tape.riv");
auto file = reader.file();
@@ -24,4 +24,42 @@
REQUIRE(tape->imageAsset()->decodedByteSize == 70903);
REQUIRE(tape->mesh() != nullptr);
REQUIRE(tape->mesh()->vertices().size() == 24);
+ REQUIRE(tape->mesh()->indices()->size() == 31 * 3); // Expect 31 triangles.
+}
+
+TEST_CASE("duplicating a mesh shares the indices", "[mesh]") {
+ RiveFileReader reader("../../test/assets/tape.riv");
+ auto file = reader.file();
+
+ auto instance1 = file->artboard()->instance();
+ auto instance2 = file->artboard()->instance();
+ auto instance3 = file->artboard()->instance();
+
+ auto node1 = instance1->find("Tape body.png");
+ auto node2 = instance2->find("Tape body.png");
+ auto node3 = instance3->find("Tape body.png");
+ REQUIRE(node1 != nullptr);
+ REQUIRE(node2 != nullptr);
+ REQUIRE(node3 != nullptr);
+ REQUIRE(node1->is<rive::Image>());
+ REQUIRE(node2->is<rive::Image>());
+ REQUIRE(node3->is<rive::Image>());
+
+ auto tape1 = node1->as<rive::Image>();
+ auto tape2 = node2->as<rive::Image>();
+ auto tape3 = node3->as<rive::Image>();
+ REQUIRE(tape1->imageAsset() != nullptr);
+ REQUIRE(tape1->mesh() != nullptr);
+ REQUIRE(tape2->imageAsset() != nullptr);
+ REQUIRE(tape2->mesh() != nullptr);
+ REQUIRE(tape3->imageAsset() != nullptr);
+ REQUIRE(tape3->mesh() != nullptr);
+
+ REQUIRE(tape1->mesh()->indices()->size() == 31 * 3);
+ REQUIRE(tape2->mesh()->indices()->size() == 31 * 3);
+ REQUIRE(tape3->mesh()->indices()->size() == 31 * 3);
+
+ // Important part, make sure they're all actually the same reference.
+ REQUIRE(tape1->mesh()->indices() == tape2->mesh()->indices());
+ REQUIRE(tape2->mesh()->indices() == tape3->mesh()->indices());
}