diff options
-rw-r--r-- | o3d/converter/cross/converter.cc | 6 | ||||
-rw-r--r-- | o3d/samples/o3djs/serialization.js | 125 | ||||
-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 | ||||
-rw-r--r-- | o3d/tests/selenium/tests/serialization-test.html | 117 |
6 files changed, 449 insertions, 67 deletions
diff --git a/o3d/converter/cross/converter.cc b/o3d/converter/cross/converter.cc index d2a9bda..e258780 100644 --- a/o3d/converter/cross/converter.cc +++ b/o3d/converter/cross/converter.cc @@ -238,7 +238,11 @@ bool Convert(const FilePath& in_filename, if (!options.pretty_print) { json_writer.BeginCompacting(); } - Serializer serializer(&service_locator, &json_writer, &archive_generator); + Serializer::Options serializer_options( + options.binary ? Serializer::Options::kBinaryOutputOn : + Serializer::Options::kBinaryOutputOff); + Serializer serializer( + &service_locator, &json_writer, &archive_generator, serializer_options); serializer.SerializePack(pack.Get()); json_writer.Close(); out_writer.Close(); diff --git a/o3d/samples/o3djs/serialization.js b/o3d/samples/o3djs/serialization.js index d917384..bb35ba9 100644 --- a/o3d/samples/o3djs/serialization.js +++ b/o3d/samples/o3djs/serialization.js @@ -56,6 +56,17 @@ o3djs.serialization = o3djs.serialization || {}; o3djs.serialization.supportedVersion = 5; /** + * These are the values the sample o3dConverter uses to identify curve key + * types. + * @type {!Object} + */ +o3djs.serialization.CURVE_KEY_TYPES = { + step: 1, + linear: 2, + bezier: 3, +}; + +/** * Options for deserialization. * * opt_animSource is an optional ParamFloat that will be bound as the source @@ -92,6 +103,49 @@ o3djs.serialization.Deserializer = function(pack, json) { this.archiveInfo = null; /** + * Deserializes a Buffer . + * @param {!o3djs.serialization.Deserializer} deserializer The deserializer. + * @param {!Object} json The json for this buffer. + * @param {string} type The type of buffer to create. + * @param {string} uri The uri of the file containing the binary data. + */ + function deserializeBuffer(deserializer, json, type, uri) { + var object = deserializer.pack.createObject(type); + if ('custom' in json) { + if ('fieldData' in json.custom) { + var fieldDataArray = json.custom.fieldData; + if (fieldDataArray.length > 0) { + var fields = []; + // First create all the fields + for (var ii = 0; ii < fieldDataArray.length; ++ii) { + var data = fieldDataArray[ii]; + var field = object.createField(data.type, data.numComponents); + fields.push(field); + deserializer.addObject(data.id, field); + } + var firstData = fieldDataArray[0]; + var numElements = firstData.data.length / firstData.numComponents; + object.allocateElements(numElements); + // Now set the data. + for (var ii = 0; ii < fieldDataArray.length; ++ii) { + var data = fieldDataArray[ii]; + fields[ii].setAt(0, data.data); + } + } + } else { + var rawData = deserializer.archiveInfo.getFileByURI(uri); + object.set(rawData, + json.custom.binaryRange[0], + json.custom.binaryRange[1] - json.custom.binaryRange[0]); + for (var i = 0; i < json.custom.fields.length; ++i) { + deserializer.addObject(json.custom.fields[i], object.fields[i]); + } + } + } + return object; + } + + /** * A map from classname to a function that will create * instances of objects. Add entries to support additional classes. * @type {!Object} @@ -112,48 +166,18 @@ o3djs.serialization.Deserializer = function(pack, json) { }, 'o3d.VertexBuffer': function(deserializer, json) { - var object = deserializer.pack.createObject('o3d.VertexBuffer'); - if ('custom' in json) { - var rawData = deserializer.archiveInfo.getFileByURI( - 'vertex-buffers.bin'); - object.set(rawData, - json.custom.binaryRange[0], - json.custom.binaryRange[1] - json.custom.binaryRange[0]); - for (var i = 0; i < json.custom.fields.length; ++i) { - deserializer.addObject(json.custom.fields[i], object.fields[i]); - } - } - return object; + return deserializeBuffer( + deserializer, json, 'o3d.VertexBuffer', 'vertex-buffers.bin'); }, 'o3d.SourceBuffer': function(deserializer, json) { - var object = deserializer.pack.createObject('o3d.SourceBuffer'); - if ('custom' in json) { - var rawData = deserializer.archiveInfo.getFileByURI( - 'vertex-buffers.bin'); - object.set(rawData, - json.custom.binaryRange[0], - json.custom.binaryRange[1] - json.custom.binaryRange[0]); - for (var i = 0; i < json.custom.fields.length; ++i) { - deserializer.addObject(json.custom.fields[i], object.fields[i]); - } - } - return object; + return deserializeBuffer( + deserializer, json, 'o3d.SourceBuffer', 'vertex-buffers.bin'); }, 'o3d.IndexBuffer': function(deserializer, json) { - var object = deserializer.pack.createObject('o3d.IndexBuffer'); - if ('custom' in json) { - var rawData = deserializer.archiveInfo.getFileByURI( - 'index-buffers.bin'); - object.set(rawData, - json.custom.binaryRange[0], - json.custom.binaryRange[1] - json.custom.binaryRange[0]); - for (var i = 0; i < json.custom.fields.length; ++i) { - deserializer.addObject(json.custom.fields[i], object.fields[i]); - } - } - return object; + return deserializeBuffer( + deserializer, json, 'o3d.IndexBuffer', 'index-buffers.bin'); }, 'o3d.Texture2D': function(deserializer, json) { @@ -201,10 +225,31 @@ o3djs.serialization.Deserializer = function(pack, json) { this.initCallbacks = { 'o3d.Curve': function(deserializer, object, json) { if ('custom' in json) { - var rawData = deserializer.archiveInfo.getFileByURI('curve-keys.bin'); - object.set(rawData, - json.custom.binaryRange[0], - json.custom.binaryRange[1] - json.custom.binaryRange[0]); + if ('keys' in json.custom) { + var keys = json.custom.keys; + var stepType = o3djs.serialization.CURVE_KEY_TYPES.step; + var linearType = o3djs.serialization.CURVE_KEY_TYPES.linear; + var bezierType = o3djs.serialization.CURVE_KEY_TYPES.bezier; + for (var ii = 0; ii < keys.length; ++ii) { + var key = keys[ii]; + switch (key[0]) { + case stepType: // Step + object.addStepKeys(key.slice(1)); + break; + case linearType: // Linear + object.addLinearKeys(key.slice(1)); + break; + case bezierType: // Bezier + object.addBezierKeys(key.slice(1)); + break; + } + } + } else { + var rawData = deserializer.archiveInfo.getFileByURI('curve-keys.bin'); + object.set(rawData, + json.custom.binaryRange[0], + json.custom.binaryRange[1] - json.custom.binaryRange[0]); + } } }, 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); diff --git a/o3d/tests/selenium/tests/serialization-test.html b/o3d/tests/selenium/tests/serialization-test.html index b62d757..1f822ad 100644 --- a/o3d/tests/selenium/tests/serialization-test.html +++ b/o3d/tests/selenium/tests/serialization-test.html @@ -929,6 +929,45 @@ g_suite.testShouldSetVertexBufferData = function() { g_test.assertEquals(12, field.size); }; +g_suite.testShouldSetVertexBufferDataNotBinary = function() { + var json = { + version: o3djs.serialization.supportedVersion, + objects: { + 'o3d.VertexBuffer': [ + { + custom: { + fieldData: [ + { + id: 55, + type: "o3d.FloatField", + numComponents: 1, + data: [1.25,-3] + } + ] + } + } + ] + } + }; + + var pack = g_client.createPack(); + var deserializer = o3djs.serialization.createDeserializer(pack, json); + deserializer.run(); + + g_test.assertEquals(1, pack.objects.length); + var buffer = pack.objects[0]; + g_test.assertEquals(2, buffer.numElements); + g_test.assertEquals(1, buffer.fields.length); + var field = buffer.fields[0]; + g_test.assertEquals('o3d.FloatField', field.className); + g_test.assertEquals(1, field.numComponents); + g_test.assertEquals(4, field.size); + var data = field.getAt(0, 2); + g_test.assertEquals(1.25, data[0]); + g_test.assertEquals(-3, data[1]); + +}; + g_suite.testShouldSetDestinationBufferData = function() { var json = { version: o3djs.serialization.supportedVersion, @@ -1050,6 +1089,46 @@ g_suite.testShouldSetCurveWithKeys = function() { g_test.assertEquals(14, keys.length); }; +g_suite.testShouldSetCurveWithKeysNotBinary = function() { + var json = { + version: o3djs.serialization.supportedVersion, + objects: { + 'o3d.Curve': [ + { + custom: { + keys: [ + [1,1,2], + [2,3,4], + [3,5,8,6,7,9,10] + ] + } + } + ] + } + }; + + var pack = g_client.createPack(); + var deserializer = o3djs.serialization.createDeserializer(pack, json); + deserializer.run(); + g_test.assertEquals(1, pack.objects.length); + var curve = pack.objects[0]; + var keys = curve.keys; + g_test.assertEquals(3, keys.length); + g_test.assertEquals('o3d.StepCurveKey', keys[0].className); + g_test.assertEquals('o3d.LinearCurveKey', keys[1].className); + g_test.assertEquals('o3d.BezierCurveKey', keys[2].className); + g_test.assertEquals(1, keys[0].input); + g_test.assertEquals(2, keys[0].output); + g_test.assertEquals(3, keys[1].input); + g_test.assertEquals(4, keys[1].output); + g_test.assertEquals(5, keys[2].input); + g_test.assertEquals(8, keys[2].output); + g_test.assertEquals(6, keys[2].inTangent[0]); + g_test.assertEquals(7, keys[2].inTangent[1]); + g_test.assertEquals(9, keys[2].outTangent[0]); + g_test.assertEquals(10, keys[2].outTangent[1]); +}; + g_suite.testShouldSetSkinEvalStreams = function() { var json = { version: o3djs.serialization.supportedVersion, @@ -1359,6 +1438,44 @@ g_suite.testShouldSetSkinData = function() { g_test.assertArrayEquals([2, 1], skin.influences[0]); }; +g_suite.testShouldSetSkinDataNotBinary = function() { + var json = { + version: o3djs.serialization.supportedVersion, + objects: { + 'o3d.Skin': [ + { + properties: { + influences: [[1, 2],[2, 3, 4, 5]], + inverseBindPoseMatrices: [ + [[1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12], + [13, 14, 15, 16]], + [[1, 2, 3, 4], + [5, 6, 7, 8.5], + [9, 10, 11, 12], + [13, 14, 15, 1]]] + } + } + ] + } + }; + + var pack = g_client.createPack(); + var deserializer = o3djs.serialization.createDeserializer(pack, json); + deserializer.run(); + + g_test.assertEquals(1, pack.objects.length); + var skin = pack.objects[0]; + g_test.assertEquals(2, skin.influences.length); + g_test.assertEquals(2, skin.influences[0].length); + g_test.assertEquals(4, skin.influences[1][2]); + g_test.assertArrayEquals([1, 2], skin.influences[0]); + g_test.assertArrayEquals([2, 3, 4, 5], skin.influences[1]); + g_test.assertEquals(2, skin.inverseBindPoseMatrices.length); + g_test.assertEquals(8.5, skin.inverseBindPoseMatrices[1][1][3]); +}; + g_suite.testExceptionIfEffectShaderCannotBeFound = function() { var json = { version: o3djs.serialization.supportedVersion, |