summaryrefslogtreecommitdiffstats
path: root/o3d/serializer
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/serializer')
-rw-r--r--o3d/serializer/cross/serializer.cc163
-rw-r--r--o3d/serializer/cross/serializer.h18
-rw-r--r--o3d/serializer/cross/serializer_test.cc87
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);