diff options
Diffstat (limited to 'o3d/serializer')
-rw-r--r-- | o3d/serializer/cross/serializer.cc | 163 | ||||
-rw-r--r-- | o3d/serializer/cross/serializer.h | 18 | ||||
-rw-r--r-- | o3d/serializer/cross/serializer_test.cc | 87 |
3 files changed, 242 insertions, 26 deletions
diff --git a/o3d/serializer/cross/serializer.cc b/o3d/serializer/cross/serializer.cc index 5e70c67..f83f102 100644 --- a/o3d/serializer/cross/serializer.cc +++ b/o3d/serializer/cross/serializer.cc @@ -217,8 +217,13 @@ bool ParamIsSerialized(Param* param) { class PropertiesVisitor : public VisitorBase<PropertiesVisitor> { public: - explicit PropertiesVisitor(StructuredWriter* writer) - : writer_(writer) { + // Parameters: + // writer: The writer to use. + // binary: True to write parts that can be binary in binary. False for pure + // JSON. + PropertiesVisitor(StructuredWriter* writer, bool binary) + : writer_(writer), + binary_(binary) { Enable<Curve>(&PropertiesVisitor::Visit); Enable<Element>(&PropertiesVisitor::Visit); Enable<NamedObject>(&PropertiesVisitor::Visit); @@ -314,6 +319,25 @@ class PropertiesVisitor : public VisitorBase<PropertiesVisitor> { void Visit(Skin* skin) { Visit(static_cast<NamedObject*>(skin)); + if (!binary_) { + writer_->WritePropertyName("influences"); + writer_->BeginCompacting(); + writer_->OpenArray(); + const Skin::InfluencesArray& influences_array = skin->influences(); + for (int i = 0; i != influences_array.size(); ++i) { + const Skin::Influences& influences = influences_array[i]; + writer_->OpenArray(); + for (int j = 0; j != influences.size(); ++j) { + const Skin::Influence& influence = influences[j]; + Serialize(writer_, influence.matrix_index); + Serialize(writer_, influence.weight); + } + writer_->CloseArray(); + } + writer_->CloseArray(); + writer_->EndCompacting(); + } + writer_->WritePropertyName("inverseBindPoseMatrices"); writer_->BeginCompacting(); writer_->OpenArray(); @@ -346,12 +370,17 @@ class PropertiesVisitor : public VisitorBase<PropertiesVisitor> { } StructuredWriter* writer_; + bool binary_; }; class CustomVisitor : public VisitorBase<CustomVisitor> { public: - explicit CustomVisitor(StructuredWriter* writer, - BinaryArchiveManager* binary_archive_manager) + // Parameters: + // writer: The writer to use. + // binary_archive_manager: The binary archive manager to add binary data + // too. If this is NULL will write JSON instead where appropriate. + CustomVisitor(StructuredWriter* writer, + BinaryArchiveManager* binary_archive_manager) : writer_(writer), binary_archive_manager_(binary_archive_manager) { Enable<DestinationBuffer>(&CustomVisitor::Visit); @@ -363,6 +392,11 @@ class CustomVisitor : public VisitorBase<CustomVisitor> { Enable<StreamBank>(&CustomVisitor::Visit); Enable<Texture2D>(&CustomVisitor::Visit); Enable<TextureCUBE>(&CustomVisitor::Visit); + if (!binary_archive_manager) { + Enable<BezierCurveKey>(&CustomVisitor::Visit); + Enable<LinearCurveKey>(&CustomVisitor::Visit); + Enable<StepCurveKey>(&CustomVisitor::Visit); + } } private: @@ -394,21 +428,94 @@ class CustomVisitor : public VisitorBase<CustomVisitor> { void Visit(Buffer* buffer) { Visit(static_cast<NamedObject*>(buffer)); - writer_->WritePropertyName("fields"); - writer_->OpenArray(); - const FieldRefArray& fields = buffer->fields(); - for (size_t ii = 0; ii < fields.size(); ++ii) { - Field* field = fields[ii].Get(); - Serialize(writer_, field->id()); + if (binary_archive_manager_) { + writer_->WritePropertyName("fields"); + writer_->OpenArray(); + const FieldRefArray& fields = buffer->fields(); + for (size_t ii = 0; ii < fields.size(); ++ii) { + Field* field = fields[ii].Get(); + Serialize(writer_, field->id()); + } + writer_->CloseArray(); + + WriteObjectBinaryRange(buffer); + } else { + writer_->WritePropertyName("fieldData"); + writer_->OpenArray(); + const FieldRefArray& fields = buffer->fields(); + for (size_t ii = 0; ii < fields.size(); ++ii) { + Field* field = fields[ii].Get(); + writer_->BeginCompacting(); + writer_->OpenObject(); + writer_->WritePropertyName("id"); + Serialize(writer_, field->id()); + writer_->WritePropertyName("type"); + Serialize(writer_, field->GetClassName()); + writer_->WritePropertyName("numComponents"); + Serialize(writer_, field->num_components()); + writer_->WritePropertyName("data"); + writer_->OpenArray(); + Buffer* buffer = field->buffer(); + if (buffer) { + unsigned num_elements = buffer->num_elements(); + scoped_array<float> data( + new float[num_elements * field->num_components()]); + field->GetAsFloats( + 0, data.get(), field->num_components(), num_elements); + for (size_t jj = 0; jj < num_elements; ++jj) { + Serialize(writer_, data[jj]); + } + } + writer_->CloseArray(); + writer_->CloseObject(); + writer_->EndCompacting(); + } + writer_->CloseArray(); } - writer_->CloseArray(); + } - WriteObjectBinaryRange(buffer); + void Visit(BezierCurveKey* key) { + Serialize(writer_, CurveKey::TYPE_BEZIER); + Serialize(writer_, key->input()); + Serialize(writer_, key->output()); + Serialize(writer_, key->in_tangent()[0]); + Serialize(writer_, key->in_tangent()[1]); + Serialize(writer_, key->out_tangent()[0]); + Serialize(writer_, key->out_tangent()[1]); + } + + void Visit(LinearCurveKey* key) { + Serialize(writer_, CurveKey::TYPE_LINEAR); + Serialize(writer_, key->input()); + Serialize(writer_, key->output()); + } + + void Visit(StepCurveKey* key) { + Serialize(writer_, CurveKey::TYPE_STEP); + Serialize(writer_, key->input()); + Serialize(writer_, key->output()); } void Visit(Curve* curve) { Visit(static_cast<NamedObject*>(curve)); - WriteObjectBinaryRange(curve); + + if (binary_archive_manager_) { + WriteObjectBinaryRange(curve); + } else { + writer_->WritePropertyName("keys"); + writer_->BeginCompacting(); + writer_->OpenArray(); + const CurveKeyRefArray& keys = curve->keys(); + for (CurveKeyRefArray::const_iterator it = keys.begin(); + it != keys.end(); ++it) { + CurveKey* key = it->Get(); + writer_->OpenArray(); + Accept(key); + writer_->CloseArray(); + } + writer_->CloseArray(); + writer_->EndCompacting(); + } } void Visit(ObjectBase* object) { @@ -425,7 +532,9 @@ class CustomVisitor : public VisitorBase<CustomVisitor> { void Visit(Skin* skin) { Visit(static_cast<NamedObject*>(skin)); - WriteObjectBinaryRange(skin); + if (binary_archive_manager_) { + WriteObjectBinaryRange(skin); + } } void Visit(SkinEval* skin_eval) { @@ -719,17 +828,21 @@ bool NameStartsWithPrefix(const ObjectBase* object, Serializer::Serializer(ServiceLocator* service_locator, StructuredWriter* writer, - IArchiveGenerator* archive_generator) + IArchiveGenerator* archive_generator, + const Serializer::Options& options) : class_manager_(service_locator), writer_(writer), - archive_generator_(archive_generator) { + archive_generator_(archive_generator), + options_(options) { + bool binary = options.binary_output == Options::kBinaryOutputOn; sections_[PROPERTIES_SECTION].name_ = "properties"; - sections_[PROPERTIES_SECTION].visitor_ = new PropertiesVisitor(writer_); + sections_[PROPERTIES_SECTION].visitor_ = + new PropertiesVisitor(writer_, binary); sections_[CUSTOM_SECTION].name_ = "custom"; sections_[CUSTOM_SECTION].visitor_ = new CustomVisitor( - writer_, &binary_archive_manager_); + writer_, binary ? &binary_archive_manager_ : false); param_visitor_ = new ParamVisitor(writer_); - binary_visitor_ = new BinaryVisitor(&binary_archive_manager_); + binary_visitor_ = binary ? new BinaryVisitor(&binary_archive_manager_) : NULL; } Serializer::~Serializer() { @@ -737,7 +850,9 @@ Serializer::~Serializer() { delete sections_[i].visitor_; } delete param_visitor_; - delete binary_visitor_; + if (binary_visitor_) { + delete binary_visitor_; + } } void Serializer::SerializePack(Pack* pack) { @@ -798,9 +913,11 @@ void Serializer::SerializePack(Pack* pack) { } void Serializer::SerializePackBinary(Pack* pack) { - std::vector<ObjectBase*> objects = pack->GetByClass<ObjectBase>(); - for (std::vector<ObjectBase*>::size_type i = 0; i < objects.size(); ++i) { - binary_visitor_->Accept(objects[i]); + if (binary_visitor_) { + std::vector<ObjectBase*> objects = pack->GetByClass<ObjectBase>(); + for (std::vector<ObjectBase*>::size_type i = 0; i < objects.size(); ++i) { + binary_visitor_->Accept(objects[i]); + } } } diff --git a/o3d/serializer/cross/serializer.h b/o3d/serializer/cross/serializer.h index dbcaa8b..18aa20c 100644 --- a/o3d/serializer/cross/serializer.h +++ b/o3d/serializer/cross/serializer.h @@ -150,6 +150,20 @@ class Serializer { NUM_SECTIONS }; + // Serialization Options. + struct Options { + enum BinaryOutput { + kBinaryOutputOn, // output binary + kBinaryOutputOff, // don't output binary. + }; + + explicit Options(BinaryOutput in_binary_output) + : binary_output(in_binary_output) { + } + + BinaryOutput binary_output; + }; + // Any object that starts with this prefix will not be seralized // but a reference to it will be put at the top of the json object. static const char* ROOT_PREFIX; @@ -158,7 +172,8 @@ class Serializer { // given StructuredWriter and IArchiveGenerator. explicit Serializer(ServiceLocator* service_locator, StructuredWriter* writer, - IArchiveGenerator* archive_generator); + IArchiveGenerator* archive_generator, + const Options& options); ~Serializer(); // Serialize a Pack and all the objects contained by the pack @@ -181,6 +196,7 @@ class Serializer { ServiceDependency<IClassManager> class_manager_; StructuredWriter* writer_; IArchiveGenerator* archive_generator_; + Options options_; struct SectionConfig { const char* name_; diff --git a/o3d/serializer/cross/serializer_test.cc b/o3d/serializer/cross/serializer_test.cc index 3bd6893..3d21e41 100644 --- a/o3d/serializer/cross/serializer_test.cc +++ b/o3d/serializer/cross/serializer_test.cc @@ -105,7 +105,9 @@ class SerializerTest : public testing::Test { : object_manager_(g_service_locator), output_(StringWriter::CR_LF), json_writer_(&output_, 2), - serializer_(g_service_locator, &json_writer_, &archive_generator_) { + serializer_( + g_service_locator, &json_writer_, &archive_generator_, + Serializer::Options(Serializer::Options::kBinaryOutputOn)) { json_writer_.BeginCompacting(); } @@ -318,6 +320,37 @@ TEST_F(SerializerTest, ShouldSerializeCurveCustomSection) { EXPECT_EQ(expected.ToString(), output_.ToString()); } +TEST_F(SerializerTest, ShouldSerializeCurveCustomSectionNotBinary) { + Serializer serializer( + g_service_locator, &json_writer_, &archive_generator_, + Serializer::Options(Serializer::Options::kBinaryOutputOff)); + Curve* curve = pack_->Create<Curve>(); + + StepCurveKey* step_key = curve->Create<StepCurveKey>(); + step_key->SetInput(1); + step_key->SetOutput(2); + + LinearCurveKey* linear_key = curve->Create<LinearCurveKey>(); + linear_key->SetInput(3); + linear_key->SetOutput(4); + + BezierCurveKey* bezier_key = curve->Create<BezierCurveKey>(); + bezier_key->SetInput(5); + bezier_key->SetInTangent(Float2(6, 7)); + bezier_key->SetOutput(8); + bezier_key->SetOutTangent(Float2(9, 10)); + + serializer.SerializePackBinary(pack_); + serializer.SerializeSection(curve, Serializer::CUSTOM_SECTION); + + StringWriter expected(StringWriter::CR_LF); + expected.WriteFormatted( + "\"keys\":[[1,1,2],[2,3,4],[3,5,8,6,7,9,10]]"); + + EXPECT_EQ(expected.ToString(), output_.ToString()); + EXPECT_TRUE(archive_generator_.add_file_records_.empty()); +} + TEST_F(SerializerTest, ShouldSerializeCurveKeysToSingleBinaryFile) { // The purpose of this buffer is just to offset the following one in the // binary file. @@ -711,6 +744,26 @@ TEST_F(SerializerTest, ShouldSerializeSkinProperties) { output_.ToString()); } +TEST_F(SerializerTest, ShouldSerializeSkinPropertiesNotBinary) { + Serializer serializer( + g_service_locator, &json_writer_, &archive_generator_, + Serializer::Options(Serializer::Options::kBinaryOutputOff)); + Skin* skin = pack_->Create<Skin>(); + skin->SetInverseBindPoseMatrix(0, Matrix4::identity()); + Skin::Influences influences(1); + influences[0] = Skin::Influence(1, 2); + skin->SetVertexInfluences(0, influences); + + serializer.SerializeSection(skin, Serializer::PROPERTIES_SECTION); + + EXPECT_EQ( + "\"influences\":[[1,2]]," + "\"inverseBindPoseMatrices\":" + "[[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]]", + output_.ToString()); + EXPECT_TRUE(archive_generator_.add_file_records_.empty()); +} + TEST_F(SerializerTest, ShouldSerializeSkinCustomSection) { Skin* skin1 = pack_->Create<Skin>(); Skin::Influences influences(1); @@ -1037,7 +1090,37 @@ TEST_F(SerializerTest, SerializesVertexBuffer) { EXPECT_EQ(expected.ToString(), output_.ToString()); } -TEST_F(SerializerTest, SerializesAllVertexBufferBinaryToSingleFileInArchive) { +TEST_F(SerializerTest, SerializesVertexBufferNotBinary) { + Serializer serializer( + g_service_locator, &json_writer_, &archive_generator_, + Serializer::Options(Serializer::Options::kBinaryOutputOff)); + Buffer* buffer = pack_->Create<VertexBuffer>(); + Field* field = buffer->CreateField(FloatField::GetApparentClass(), 1); + buffer->AllocateElements(2); + { + BufferLockHelper locker(buffer); + float* data = locker.GetDataAs<float>(Buffer::WRITE_ONLY); + data[0] = 1.25f; + data[1] = -3.0f; + } + + serializer.SerializePackBinary(pack_); + serializer.SerializeSection(buffer, Serializer::CUSTOM_SECTION); + + StringWriter expected(StringWriter::CR_LF); + expected.WriteFormatted( + "\"fieldData\":[{" + "\"id\":%d," + "\"type\":\"o3d.FloatField\"," + "\"numComponents\":1,\"data\":[1.25,-3]}]", + field->id(), field->id()); + + EXPECT_EQ(expected.ToString(), output_.ToString()); + EXPECT_TRUE(archive_generator_.add_file_records_.empty()); +} + +TEST_F(SerializerTest, + SerializesAllVertexBufferBinaryToSingleFileInArchive) { Buffer* buffer1 = pack_->Create<VertexBuffer>(); buffer1->CreateField(FloatField::GetApparentClass(), 1); buffer1->AllocateElements(2); |