Commit 34f464fb authored by gman@google.com's avatar gman@google.com

Add o3djs.DestinationBuffer to converter.

I named it o3djs.DestinationBuffer because it has nothing to do 
with O3D. It's purely part of our sample serialization example.

Review URL: http://codereview.chromium.org/149236

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20013 0039d316-1c4b-4281-b951-d872f2087c98
parent e8b80d81
...@@ -94,6 +94,7 @@ bool Convert(const FilePath& in_filename, ...@@ -94,6 +94,7 @@ bool Convert(const FilePath& in_filename,
ErrorStatus error_status(&service_locator); ErrorStatus error_status(&service_locator);
Features features(&service_locator); Features features(&service_locator);
Collada::Init(&service_locator);
features.Init("MaxCapabilities"); features.Init("MaxCapabilities");
// Collect error messages. // Collect error messages.
...@@ -119,7 +120,8 @@ bool Convert(const FilePath& in_filename, ...@@ -119,7 +120,8 @@ bool Convert(const FilePath& in_filename,
collada_options.base_path = options.base_path; collada_options.base_path = options.base_path;
collada_options.up_axis = options.up_axis; collada_options.up_axis = options.up_axis;
Collada collada(pack.Get(), collada_options); Collada collada(pack.Get(), collada_options);
if (!collada.ImportFile(in_filename, root, param_float)) { bool result = collada.ImportFile(in_filename, root, param_float);
if (!result || !error_collector.errors().empty()) {
if (error_messages) { if (error_messages) {
*error_messages += error_collector.errors(); *error_messages += error_collector.errors();
} }
......
...@@ -44,6 +44,16 @@ ObjectBase::Class ObjectBase::class_ = { ...@@ -44,6 +44,16 @@ ObjectBase::Class ObjectBase::class_ = {
O3D_STRING_CONSTANT("ObjectBase"), NULL O3D_STRING_CONSTANT("ObjectBase"), NULL
}; };
const char* ObjectBase::Class::unqualified_name() const {
if (strncmp(
name_,
O3D_NAMESPACE O3D_NAMESPACE_SEPARATOR,
sizeof(O3D_NAMESPACE) + sizeof(O3D_NAMESPACE_SEPARATOR) - 2) == 0) {
return name_ + sizeof(O3D_NAMESPACE) + sizeof(O3D_NAMESPACE_SEPARATOR) - 2;
}
return name_;
}
ObjectBase::ObjectBase(ServiceLocator *service_locator) ObjectBase::ObjectBase(ServiceLocator *service_locator)
: id_(IdManager::CreateId()), : id_(IdManager::CreateId()),
service_locator_(service_locator) { service_locator_(service_locator) {
......
...@@ -50,11 +50,12 @@ ...@@ -50,11 +50,12 @@
#define O3D_STRING_CONSTANT(value) \ #define O3D_STRING_CONSTANT(value) \
(O3D_NAMESPACE O3D_NAMESPACE_SEPARATOR value) (O3D_NAMESPACE O3D_NAMESPACE_SEPARATOR value)
// This macro declares the necessary functions for the type mechanism to work. // This macro declares the necessary functions for the type mechanism to work.
// It needs to be used in each of the definition of any class that derives from // It needs to be used in each of the definition of any class that derives from
// ObjectBase. // ObjectBase.
// CLASS is the class being defined, BASE is its base class. // CLASS is the class being defined, BASE is its base class.
#define O3D_DECL_CLASS(CLASS, BASE) \ #define O3D_OBJECT_BASE_DECL_CLASS(CLASS, BASE) \
public: \ public: \
static const ObjectBase::Class *GetApparentClass() { return &class_; } \ static const ObjectBase::Class *GetApparentClass() { return &class_; } \
static const String GetApparentClassName() { \ static const String GetApparentClassName() { \
...@@ -72,10 +73,24 @@ ...@@ -72,10 +73,24 @@
// This macro defines the class descriptor for the type mechanism. It needs to // This macro defines the class descriptor for the type mechanism. It needs to
// be used once in the definition file of any class that derives from // be used once in the definition file of any class that derives from
// ObjectBase. // ObjectBase.
// CLASSNAME is the name to use to identify the class.
// CLASS is the class being defined.
// BASE is its base class.
#define O3D_OBJECT_BASE_DEFN_CLASS(CLASSNAME, CLASS, BASE) \
ObjectBase::Class CLASS::class_ = { CLASSNAME, BASE::GetApparentClass() };
// This macro declares the necessary functions for the type mechanism to work.
// It needs to be used in each of the definition of any class that derives from
// ObjectBase.
// CLASS is the class being defined, BASE is its base class. // CLASS is the class being defined, BASE is its base class.
#define O3D_DEFN_CLASS(CLASS, BASE) \ #define O3D_DECL_CLASS(CLASS, BASE) O3D_OBJECT_BASE_DECL_CLASS(CLASS, BASE)
ObjectBase::Class CLASS::class_ = \
{ O3D_STRING_CONSTANT(#CLASS), BASE::GetApparentClass() }; // This macro defines the class descriptor for the type mechanism. It needs to
// be used once in the definition file of any class that derives from
// ObjectBase.
// CLASS is the class being defined, BASE is its base class.
#define O3D_DEFN_CLASS(CLASS, BASE) \
O3D_OBJECT_BASE_DEFN_CLASS(O3D_STRING_CONSTANT(#CLASS), CLASS, BASE)
namespace o3d { namespace o3d {
...@@ -142,10 +157,7 @@ class ObjectBase : public RefCounted { ...@@ -142,10 +157,7 @@ class ObjectBase : public RefCounted {
return name_; return name_;
} }
const char* unqualified_name() const { const char* unqualified_name() const;
return name_ + sizeof(O3D_NAMESPACE) +
sizeof(O3D_NAMESPACE_SEPARATOR) - 2;
}
public: public:
// The name of the class. // The name of the class.
......
...@@ -89,6 +89,9 @@ bool StreamBank::SetVertexStream(Stream::Semantic stream_semantic, ...@@ -89,6 +89,9 @@ bool StreamBank::SetVertexStream(Stream::Semantic stream_semantic,
O3D_ERROR(service_locator()) << "No buffer on field"; O3D_ERROR(service_locator()) << "No buffer on field";
return false; return false;
} }
// Check that this buffer is renderable. StreamBanks are used to submit
// data to GPU so we can only allow GPU accessible buffers through here.
if (!buffer->IsA(VertexBuffer::GetApparentClass())) { if (!buffer->IsA(VertexBuffer::GetApparentClass())) {
O3D_ERROR(service_locator()) << "Buffer is not a VertexBuffer"; O3D_ERROR(service_locator()) << "Buffer is not a VertexBuffer";
return false; return false;
......
...@@ -64,6 +64,7 @@ else: ...@@ -64,6 +64,7 @@ else:
collada_inputs = [ collada_inputs = [
'cross/collada.cc', 'cross/collada.cc',
'cross/collada_zip_archive.cc', 'cross/collada_zip_archive.cc',
'cross/destination_buffer.cc',
'cross/zip_archive.cc', 'cross/zip_archive.cc',
'cross/gz_compressor.cc', 'cross/gz_compressor.cc',
'cross/file_output_stream_processor.cc', 'cross/file_output_stream_processor.cc',
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "base/file_path.h" #include "base/file_path.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "core/cross/class_manager.h"
#include "core/cross/curve.h" #include "core/cross/curve.h"
#include "core/cross/error.h" #include "core/cross/error.h"
#include "core/cross/function.h" #include "core/cross/function.h"
...@@ -53,6 +54,7 @@ ...@@ -53,6 +54,7 @@
#include "import/cross/collada.h" #include "import/cross/collada.h"
#include "import/cross/collada_conditioner.h" #include "import/cross/collada_conditioner.h"
#include "import/cross/collada_zip_archive.h" #include "import/cross/collada_zip_archive.h"
#include "import/cross/destination_buffer.h"
#include "utils/cross/file_path_utils.h" #include "utils/cross/file_path_utils.h"
#define COLLADA_NAMESPACE "collada" #define COLLADA_NAMESPACE "collada"
...@@ -147,6 +149,12 @@ bool Collada::Import(Pack* pack, ...@@ -147,6 +149,12 @@ bool Collada::Import(Pack* pack,
options); options);
} }
void Collada::Init(ServiceLocator* service_locator) {
ClassManager* class_manager=
service_locator->GetService<o3d::ClassManager>();
class_manager->AddTypedClass<DestinationBuffer>();
}
// Parameters: // Parameters:
// pack: The pack into which the scene objects will be placed. // pack: The pack into which the scene objects will be placed.
// Returns true on success. // Returns true on success.
...@@ -391,11 +399,13 @@ bool Collada::ImportDAEDocument(FCDocument* doc, ...@@ -391,11 +399,13 @@ bool Collada::ImportDAEDocument(FCDocument* doc,
FCDSceneNode* scene = doc->GetVisualSceneInstance(); FCDSceneNode* scene = doc->GetVisualSceneInstance();
if (scene) { if (scene) {
instance_root_ = CreateInstanceTree(scene); instance_root_ = CreateInstanceTree(scene);
ImportTree(instance_root_, parent, animation_input); if (ImportTree(instance_root_, parent, animation_input)) {
ImportTreeInstances(doc, instance_root_); if (ImportTreeInstances(doc, instance_root_)) {
status = true;
}
}
delete instance_root_; delete instance_root_;
instance_root_ = NULL; instance_root_ = NULL;
status = true;
} }
} }
} }
...@@ -796,7 +806,7 @@ NodeInstance *Collada::FindNodeInstanceFast(FCDSceneNode *node) { ...@@ -796,7 +806,7 @@ NodeInstance *Collada::FindNodeInstanceFast(FCDSceneNode *node) {
// animation_input: The float parameter used as the input to the animation // animation_input: The float parameter used as the input to the animation
// (if present). This is usually time. This can be null // (if present). This is usually time. This can be null
// if there is no animation. // if there is no animation.
void Collada::ImportTree(NodeInstance *instance, bool Collada::ImportTree(NodeInstance *instance,
Transform* parent_transform, Transform* parent_transform,
ParamFloat* animation_input) { ParamFloat* animation_input) {
FCDSceneNode *node = instance->node(); FCDSceneNode *node = instance->node();
...@@ -807,17 +817,22 @@ void Collada::ImportTree(NodeInstance *instance, ...@@ -807,17 +817,22 @@ void Collada::ImportTree(NodeInstance *instance,
// recursively import the rest of the nodes in the tree // recursively import the rest of the nodes in the tree
const NodeInstance::NodeInstanceList &children = instance->children(); const NodeInstance::NodeInstanceList &children = instance->children();
for (size_t i = 0; i < children.size(); ++i) { for (size_t i = 0; i < children.size(); ++i) {
ImportTree(children[i], transform, animation_input); if (!ImportTree(children[i], transform, animation_input)) {
return false;
}
} }
return true;
} }
void Collada::ImportTreeInstances(FCDocument* doc, bool Collada::ImportTreeInstances(FCDocument* doc,
NodeInstance *node_instance) { NodeInstance *node_instance) {
FCDSceneNode *node = node_instance->node(); FCDSceneNode *node = node_instance->node();
// recursively import the rest of the nodes in the tree // recursively import the rest of the nodes in the tree
const NodeInstance::NodeInstanceList &children = node_instance->children(); const NodeInstance::NodeInstanceList &children = node_instance->children();
for (size_t i = 0; i < children.size(); ++i) { for (size_t i = 0; i < children.size(); ++i) {
ImportTreeInstances(doc, children[i]); if (!ImportTreeInstances(doc, children[i])) {
return false;
}
} }
Transform* transform = node_instance->transform(); Transform* transform = node_instance->transform();
...@@ -847,9 +862,19 @@ void Collada::ImportTreeInstances(FCDocument* doc, ...@@ -847,9 +862,19 @@ void Collada::ImportTreeInstances(FCDocument* doc,
case FCDEntity::CONTROLLER: { case FCDEntity::CONTROLLER: {
FCDControllerInstance* controller_instance = FCDControllerInstance* controller_instance =
static_cast<FCDControllerInstance*> (instance); static_cast<FCDControllerInstance*> (instance);
Shape* shape = GetSkinnedShape(doc, controller_instance, node_instance); FCDController* controller =
if (shape) { static_cast<FCDController*>(controller_instance->GetEntity());
transform->AddShape(shape); if (controller) {
if (controller->IsSkin()) {
Shape* shape = GetSkinnedShape(doc,
controller_instance,
node_instance);
if (shape) {
transform->AddShape(shape);
} else {
return false;
}
}
} }
break; break;
} }
...@@ -858,6 +883,7 @@ void Collada::ImportTreeInstances(FCDocument* doc, ...@@ -858,6 +883,7 @@ void Collada::ImportTreeInstances(FCDocument* doc,
break; break;
} }
} }
return true;
} }
// Converts an FCollada vertex attribute semantic into an O3D // Converts an FCollada vertex attribute semantic into an O3D
...@@ -1318,9 +1344,23 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, ...@@ -1318,9 +1344,23 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc,
// skin everything. This is actually what was BuildShape was doing at the // skin everything. This is actually what was BuildShape was doing at the
// time this code was written. // time this code was written.
const ElementRefArray& elements = shape->GetElementRefs(); const ElementRefArray& elements = shape->GetElementRefs();
if (elements.empty() || !elements[0]->IsA(Primitive::GetApparentClass())) { if (elements.empty()) {
return NULL; return NULL;
} }
// check that they all use the same StreamBank and are all Primitives
for (unsigned ii = 0; ii < elements.size(); ++ii) {
if (!elements[ii]->IsA(Primitive::GetApparentClass())) {
O3D_ERROR(service_locator_)
<< "Element in Shape '" << shape->name() << "' is not a Primitive.";
return NULL;
}
if (down_cast<Primitive*>(elements[ii].Get())->stream_bank() !=
down_cast<Primitive*>(elements[0].Get())->stream_bank()) {
O3D_ERROR(service_locator_)
<< "More than one StreamBank in Shape '" << shape->name() << "'.";
return NULL;
}
}
Primitive* primitive = down_cast<Primitive*>(elements[0].Get()); Primitive* primitive = down_cast<Primitive*>(elements[0].Get());
String controller_name = WideToUTF8(controller->GetName().c_str()); String controller_name = WideToUTF8(controller->GetName().c_str());
...@@ -1412,16 +1452,29 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, ...@@ -1412,16 +1452,29 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc,
// so we can store the skinned vertices for the second instance. But we'd // so we can store the skinned vertices for the second instance. But we'd
// like to share the COLOR and TEXCOORDS. To do that they need to be in // like to share the COLOR and TEXCOORDS. To do that they need to be in
// a separate VertexBuffer. // a separate VertexBuffer.
StreamBank* stream_bank = primitive->stream_bank(); StreamBank* old_stream_bank = primitive->stream_bank();
SourceBuffer* buffer = pack_->Create<SourceBuffer>(); StreamBank* new_stream_bank = pack_->Create<StreamBank>();
new_stream_bank->set_name(String("skinned_") + old_stream_bank->name());
Buffer* old_buffer = NULL;
SourceBuffer* source_buffer = pack_->Create<SourceBuffer>();
VertexBuffer* shared_buffer = pack_->Create<VertexBuffer>(); VertexBuffer* shared_buffer = pack_->Create<VertexBuffer>();
DestinationBuffer* dest_buffer = pack_->Create<DestinationBuffer>();
const StreamParamVector& source_stream_params = const StreamParamVector& source_stream_params =
stream_bank->vertex_stream_params(); old_stream_bank->vertex_stream_params();
std::vector<Field*> new_fields(source_stream_params.size(), NULL); std::vector<Field*> source_fields(source_stream_params.size(), NULL);
std::vector<Field*> dest_fields(source_stream_params.size(), NULL);
// first make all the fields. // first make all the fields.
for (unsigned ii = 0; ii < source_stream_params.size(); ++ii) { for (unsigned ii = 0; ii < source_stream_params.size(); ++ii) {
const Stream& source_stream = source_stream_params[ii]->stream(); const Stream& source_stream = source_stream_params[ii]->stream();
const Field& field = source_stream.field(); const Field& field = source_stream.field();
if (old_buffer == NULL) {
old_buffer = field.buffer();
} else if (old_buffer != field.buffer()) {
O3D_ERROR(service_locator_)
<< "More than 1 buffer used by StreamBank '"
<< old_stream_bank->name().c_str()
<< "' which the collada importer does not currently support";
}
bool copied = false; bool copied = false;
if (field.IsA(FloatField::GetApparentClass()) && if (field.IsA(FloatField::GetApparentClass()) &&
(field.num_components() == 3 || (field.num_components() == 3 ||
...@@ -1437,25 +1490,44 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, ...@@ -1437,25 +1490,44 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc,
if (num_source_vertices != num_vertices) { if (num_source_vertices != num_vertices) {
O3D_ERROR(service_locator_) O3D_ERROR(service_locator_)
<< "Number of vertices in stream_bank '" << "Number of vertices in stream_bank '"
<< stream_bank->name().c_str() << old_stream_bank->name().c_str()
<< "' does not equal the number of vertices in the Skin '" << "' does not equal the number of vertices in the Skin '"
<< skin->name().c_str() << "'"; << skin->name().c_str() << "'";
return NULL; return NULL;
} }
new_fields[ii] = buffer->CreateField(FloatField::GetApparentClass(), source_fields[ii] = source_buffer->CreateField(
num_source_components); FloatField::GetApparentClass(), num_source_components);
DCHECK(source_fields[ii]);
dest_fields[ii] = dest_buffer->CreateField(
FloatField::GetApparentClass(), num_source_components);
DCHECK(dest_fields[ii]);
if (!new_stream_bank->SetVertexStream(
source_stream.semantic(),
source_stream.semantic_index(),
dest_fields[ii],
0)) {
O3D_ERROR(service_locator_)
<< "could not SetVertexStream on StreamBank '"
<< new_stream_bank->name() << "'";
return NULL;
}
} }
} }
} }
if (!copied) { if (!copied) {
// It's a shared field, copy it to the shared buffer. // It's a shared field, copy it to the shared buffer.
new_fields[ii] = shared_buffer->CreateField(field.GetClass(), source_fields[ii] = shared_buffer->CreateField(field.GetClass(),
field.num_components()); field.num_components());
new_stream_bank->SetVertexStream(source_stream.semantic(),
source_stream.semantic_index(),
source_fields[ii],
0);
} }
} }
if (!buffer->AllocateElements(num_vertices) || if (!source_buffer->AllocateElements(num_vertices) ||
!shared_buffer->AllocateElements(num_vertices)) { !shared_buffer->AllocateElements(num_vertices) ||
!dest_buffer->AllocateElements(num_vertices)) {
O3D_ERROR(service_locator_) O3D_ERROR(service_locator_)
<< "Failed to allocate destination vertex buffer"; << "Failed to allocate destination vertex buffer";
return NULL; return NULL;
...@@ -1475,7 +1547,7 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, ...@@ -1475,7 +1547,7 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc,
case Stream::TANGENT: { case Stream::TANGENT: {
copied = true; copied = true;
unsigned num_source_components = field.num_components(); unsigned num_source_components = field.num_components();
Field* new_field = new_fields[ii]; Field* source_field = source_fields[ii];
std::vector<float> data(num_vertices * num_source_components); std::vector<float> data(num_vertices * num_source_components);
field.GetAsFloats(0, &data[0], num_source_components, field.GetAsFloats(0, &data[0], num_source_components,
...@@ -1516,30 +1588,38 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, ...@@ -1516,30 +1588,38 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc,
} }
} }
} }
new_field->SetFromFloats(&data[0], num_source_components, 0, source_field->SetFromFloats(&data[0], num_source_components, 0,
num_vertices); num_vertices);
// Bind streams // Bind streams
skin_eval->SetVertexStream(source_stream.semantic(), skin_eval->SetVertexStream(source_stream.semantic(),
source_stream.semantic_index(), source_stream.semantic_index(),
new_field, source_field,
0); 0);
stream_bank->BindStream(skin_eval, new_stream_bank->BindStream(skin_eval,
source_stream.semantic(), source_stream.semantic(),
source_stream.semantic_index()); source_stream.semantic_index());
break; break;
} }
} }
} }
if (!copied) { if (!copied) {
Field* new_field = new_fields[ii]; Field* source_field = source_fields[ii];
new_field->Copy(field); source_field->Copy(field);
field.buffer()->RemoveField(&source_stream.field());
stream_bank->SetVertexStream(source_stream.semantic(),
source_stream.semantic_index(),
new_field,
0);
} }
} }
// Set all primitives to use new stream bank.
for (unsigned ii = 0; ii < elements.size(); ++ii) {
down_cast<Primitive*>(elements[ii].Get())->set_stream_bank(
new_stream_bank);
}
pack_->RemoveObject(old_stream_bank);
if (old_buffer) {
source_buffer->set_name(String("source_") + old_buffer->name());
dest_buffer->set_name(String("skinned_") + old_buffer->name());
shared_buffer->set_name(String("shared_") + old_buffer->name());
pack_->RemoveObject(old_buffer);
}
} }
return shape; return shape;
} }
......
...@@ -66,6 +66,7 @@ class FilePath; ...@@ -66,6 +66,7 @@ class FilePath;
namespace o3d { namespace o3d {
class ClassManager;
class ColladaZipArchive; class ColladaZipArchive;
class Effect; class Effect;
class IErrorStatus; class IErrorStatus;
...@@ -221,6 +222,9 @@ class Collada { ...@@ -221,6 +222,9 @@ class Collada {
std::vector<FilePath> GetOriginalDataFilenames() const; std::vector<FilePath> GetOriginalDataFilenames() const;
const std::string& GetOriginalData(const FilePath& filename) const; const std::string& GetOriginalData(const FilePath& filename) const;
// Init the Collada Importer.
static void Init(ServiceLocator* service_locator);
private: private:
// Imports the given ZIP file into the given pack. // Imports the given ZIP file into the given pack.
bool ImportZIP(const FilePath& filename, Transform* parent, bool ImportZIP(const FilePath& filename, Transform* parent,
...@@ -244,7 +248,7 @@ class Collada { ...@@ -244,7 +248,7 @@ class Collada {
// Recursively imports a tree of nodes from FCollada, rooted at the // Recursively imports a tree of nodes from FCollada, rooted at the
// given node, into the O3D scene. // given node, into the O3D scene.
void ImportTree(NodeInstance *instance, bool ImportTree(NodeInstance *instance,
Transform* parent, Transform* parent,
ParamFloat* animation_input); ParamFloat* animation_input);
...@@ -252,7 +256,7 @@ class Collada { ...@@ -252,7 +256,7 @@ class Collada {
// rooted at the given node, into the O3D scene. This is a separate step // rooted at the given node, into the O3D scene. This is a separate step
// from ImportTree because various kinds of instances can reference other // from ImportTree because various kinds of instances can reference other
// parts of the tree. // parts of the tree.
void ImportTreeInstances(FCDocument* doc, bool ImportTreeInstances(FCDocument* doc,
NodeInstance* instance); NodeInstance* instance);
bool BuildFloatAnimation(ParamFloat* result, bool BuildFloatAnimation(ParamFloat* result,
......
/*
* Copyright 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "import/cross/destination_buffer.h"
namespace o3d {
O3D_OBJECT_BASE_DEFN_CLASS(
"o3djs.DestinationBuffer", DestinationBuffer, VertexBuffer);
DestinationBuffer::DestinationBuffer(ServiceLocator* service_locator)
: VertexBuffer(service_locator),
buffer_() {
}
DestinationBuffer::~DestinationBuffer() {
ConcreteFree();
}
void DestinationBuffer::ConcreteFree() {
buffer_.reset();
}
bool DestinationBuffer::ConcreteAllocate(size_t size_in_bytes) {
ConcreteFree();
buffer_.reset(new char[size_in_bytes]);
return true;
}
bool DestinationBuffer::ConcreteLock(AccessMode access_mode,
void **buffer_data) {
if (!buffer_.get()) {
return false;
}
*buffer_data = reinterpret_cast<void*>(buffer_.get());
return true;
}
bool DestinationBuffer::ConcreteUnlock() {
return buffer_.get() != NULL;
}
ObjectBase::Ref DestinationBuffer::Create(ServiceLocator* service_locator) {
return ObjectBase::Ref(new DestinationBuffer(service_locator));
}
} // namespace o3d
/*
* Copyright 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This file declares the DestinationBuffer class.
#ifndef O3D_IMPORT_CROSS_DESTINATION_BUFFER_H_
#define O3D_IMPORT_CROSS_DESTINATION_BUFFER_H_
#include "core/cross/buffer.h"
namespace o3d {
// DestinationBuffer is a used for serialization only and is not part of the
// normal O3D plugin. It is used for Skinning to distinguish between a normal
// VertexBuffer that needs to have its contents serialized and a
// DestinationBuffer that only needs to know its structure but not its
// contents.
class DestinationBuffer : public VertexBuffer {
public:
typedef SmartPointer<DestinationBuffer> Ref;
~DestinationBuffer();
protected:
// Overridden from Buffer.
virtual bool ConcreteAllocate(size_t size_in_bytes);
// Overridden from Buffer.
virtual bool ConcreteLock(AccessMode access_mode, void **buffer_data);
// Overridden from Buffer.
virtual bool ConcreteUnlock();
explicit DestinationBuffer(ServiceLocator* service_locator);
protected:
// Frees the buffer if it exists.
void ConcreteFree();
private:
friend class IClassManager;
static ObjectBase::Ref Create(ServiceLocator* service_locator);
scoped_array<char> buffer_; // The actual data for this buffer.
O3D_OBJECT_BASE_DECL_CLASS(DestinationBuffer, VertexBuffer);
DISALLOW_COPY_AND_ASSIGN(DestinationBuffer);
};
} // namespace o3d
#endif // O3D_IMPORT_CROSS_DESTINATION_BUFFER_H_
/*
* Copyright 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "tests/common/win/testing_common.h"
#include "import/cross/destination_buffer.h"
#include "core/cross/class_manager.h"
#include "core/cross/object_manager.h"
#include "core/cross/pack.h"
#include "core/cross/service_dependency.h"
namespace o3d {
class DestinationBufferTest : public testing::Test {
protected:
DestinationBufferTest()
: class_manager_(g_service_locator),
object_manager_(g_service_locator) {
class_manager_->AddTypedClass<DestinationBuffer>();
}
virtual void SetUp();
virtual void TearDown();
Pack* pack() { return pack_; }
private:
ServiceDependency<ClassManager> class_manager_;
ServiceDependency<ObjectManager> object_manager_;
Pack* pack_;
};
void DestinationBufferTest::SetUp() {
pack_ = object_manager_->CreatePack();
}
void DestinationBufferTest::TearDown() {
object_manager_->DestroyPack(pack_);
}
// Creates a Destination buffer, tests basic properties, and checks that writing
// then reading data works.
TEST_F(DestinationBufferTest, TestDestinationBuffer) {
Buffer *buffer = pack()->Create<DestinationBuffer>();
EXPECT_TRUE(buffer->IsA(DestinationBuffer::GetApparentClass()));
EXPECT_TRUE(buffer->IsA(VertexBuffer::GetApparentClass()));
EXPECT_TRUE(buffer->IsA(Buffer::GetApparentClass()));
const size_t kSize = 100;
Field* field = buffer->CreateField(UInt32Field::GetApparentClass(), 1);
ASSERT_TRUE(field != NULL);
ASSERT_TRUE(buffer->AllocateElements(kSize));
EXPECT_EQ(kSize * sizeof(uint32), buffer->GetSizeInBytes()); // NOLINT
// Put some data into the buffer.
uint32 *data = NULL;
ASSERT_TRUE(buffer->LockAs(Buffer::WRITE_ONLY, &data));
ASSERT_TRUE(data != NULL);
for (uint32 i = 0; i < kSize; ++i) {
data[i] = i;
}
ASSERT_TRUE(buffer->Unlock());
data = NULL;
// Read the data from the buffer, checks that it's the expected values.
ASSERT_TRUE(buffer->LockAs(Buffer::READ_ONLY, &data));
ASSERT_TRUE(data != NULL);
for (uint32 i = 0; i < kSize; ++i) {
EXPECT_EQ(i, data[i]);
}
ASSERT_TRUE(buffer->Unlock());
}
} // namespace o3d
...@@ -96,6 +96,20 @@ o3djs.serialization.Deserializer = function(pack, json) { ...@@ -96,6 +96,20 @@ o3djs.serialization.Deserializer = function(pack, json) {
* @type {!Object} * @type {!Object}
*/ */
this.createCallbacks = { this.createCallbacks = {
'o3djs.DestinationBuffer': function(deserializer, json) {
var object = deserializer.pack.createObject('o3d.VertexBuffer');
if ('custom' in json) {
for (var i = 0; i < json.custom.fields.length; ++i) {
var fieldInfo = json.custom.fields[i]
var field = object.createField(fieldInfo.type,
fieldInfo.numComponents);
deserializer.addObject(fieldInfo.id, field);
}
object.allocateElements(json.custom.numElements);
}
return object;
},
'o3d.VertexBuffer': function(deserializer, json) { 'o3d.VertexBuffer': function(deserializer, json) {
var object = deserializer.pack.createObject('o3d.VertexBuffer'); var object = deserializer.pack.createObject('o3d.VertexBuffer');
if ('custom' in json) { if ('custom' in json) {
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "core/cross/skin.h" #include "core/cross/skin.h"
#include "core/cross/texture.h" #include "core/cross/texture.h"
#include "core/cross/transform.h" #include "core/cross/transform.h"
#include "import/cross/destination_buffer.h"
#include "import/cross/iarchive_generator.h" #include "import/cross/iarchive_generator.h"
#include "import/cross/memory_buffer.h" #include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h" #include "import/cross/memory_stream.h"
...@@ -345,6 +346,7 @@ class CustomVisitor : public VisitorBase<CustomVisitor> { ...@@ -345,6 +346,7 @@ class CustomVisitor : public VisitorBase<CustomVisitor> {
BinaryArchiveManager* binary_archive_manager) BinaryArchiveManager* binary_archive_manager)
: writer_(writer), : writer_(writer),
binary_archive_manager_(binary_archive_manager) { binary_archive_manager_(binary_archive_manager) {
Enable<DestinationBuffer>(&CustomVisitor::Visit);
Enable<Buffer>(&CustomVisitor::Visit); Enable<Buffer>(&CustomVisitor::Visit);
Enable<Curve>(&CustomVisitor::Visit); Enable<Curve>(&CustomVisitor::Visit);
Enable<Primitive>(&CustomVisitor::Visit); Enable<Primitive>(&CustomVisitor::Visit);
...@@ -356,6 +358,31 @@ class CustomVisitor : public VisitorBase<CustomVisitor> { ...@@ -356,6 +358,31 @@ class CustomVisitor : public VisitorBase<CustomVisitor> {
} }
private: private:
void Visit(DestinationBuffer* buffer) {
// NOTE: We don't call Visit<VertexBuffer*> because we don't want to
// serialize the contents of the Buffer. We only serialize its structure.
Visit(static_cast<NamedObject*>(buffer));
writer_->WritePropertyName("numElements");
Serialize(writer_, buffer->num_elements());
writer_->WritePropertyName("fields");
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_->CloseObject();
writer_->EndCompacting();
}
writer_->CloseArray();
}
void Visit(Buffer* buffer) { void Visit(Buffer* buffer) {
Visit(static_cast<NamedObject*>(buffer)); Visit(static_cast<NamedObject*>(buffer));
...@@ -585,6 +612,7 @@ class BinaryVisitor : public VisitorBase<BinaryVisitor> { ...@@ -585,6 +612,7 @@ class BinaryVisitor : public VisitorBase<BinaryVisitor> {
: binary_archive_manager_(binary_archive_manager) { : binary_archive_manager_(binary_archive_manager) {
Enable<Curve>(&BinaryVisitor::Visit); Enable<Curve>(&BinaryVisitor::Visit);
Enable<IndexBuffer>(&BinaryVisitor::Visit); Enable<IndexBuffer>(&BinaryVisitor::Visit);
Enable<DestinationBuffer>(&BinaryVisitor::Visit);
Enable<VertexBufferBase>(&BinaryVisitor::Visit); Enable<VertexBufferBase>(&BinaryVisitor::Visit);
Enable<Skin>(&BinaryVisitor::Visit); Enable<Skin>(&BinaryVisitor::Visit);
} }
...@@ -608,6 +636,11 @@ class BinaryVisitor : public VisitorBase<BinaryVisitor> { ...@@ -608,6 +636,11 @@ class BinaryVisitor : public VisitorBase<BinaryVisitor> {
serialized_data.GetLength()); serialized_data.GetLength());
} }
void Visit(DestinationBuffer* buffer) {
// Destination buffers should NOT have their contents serialized.
Visit(static_cast<Buffer*>(buffer));
}
void Visit(IndexBuffer* buffer) { void Visit(IndexBuffer* buffer) {
Visit(static_cast<Buffer*>(buffer)); Visit(static_cast<Buffer*>(buffer));
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define O3D_SERIALIZER_CROSS_VERSION_H_ #define O3D_SERIALIZER_CROSS_VERSION_H_
namespace o3d { namespace o3d {
const int kSerializerVersion = 5; const int kSerializerVersion = 6;
} }
#endif // O3D_SERIALIZER_CROSS_VERSION_H_ #endif // O3D_SERIALIZER_CROSS_VERSION_H_
...@@ -217,6 +217,7 @@ tests = [ ...@@ -217,6 +217,7 @@ tests = [
'core/cross/vertex_source_test.cc', 'core/cross/vertex_source_test.cc',
'core/cross/visitor_base_test.cc', 'core/cross/visitor_base_test.cc',
'core/cross/weak_ptr_test.cc', 'core/cross/weak_ptr_test.cc',
'import/cross/destination_buffer_test.cc',
'import/cross/gz_compressor_test.cc', 'import/cross/gz_compressor_test.cc',
'import/cross/gz_decompressor_test.cc', 'import/cross/gz_decompressor_test.cc',
'import/cross/memory_buffer_test.cc', 'import/cross/memory_buffer_test.cc',
...@@ -458,10 +459,10 @@ if ARGUMENTS.get('SYSTEM_TESTS_ENABLED', False): ...@@ -458,10 +459,10 @@ if ARGUMENTS.get('SYSTEM_TESTS_ENABLED', False):
# Also require gl related libraries based on variant. # Also require gl related libraries based on variant.
system_tests_req += gl_requirements system_tests_req += gl_requirements
# Require SwiftShader (only if it is available). # Require SwiftShader (only if it is available).
system_tests_req += swiftshader_install system_tests_req += swiftshader_install
# Add requirements for system_tests. # Add requirements for system_tests.
env.Requires(system_tests_install, system_tests_req) env.Requires(system_tests_install, system_tests_req)
...@@ -542,7 +543,7 @@ selenium_good_to_go = True ...@@ -542,7 +543,7 @@ selenium_good_to_go = True
if run_env.Bit('mac'): if run_env.Bit('mac'):
plugin_path = '$ARTIFACTS_DIR/O3D.plugin' plugin_path = '$ARTIFACTS_DIR/O3D.plugin'
if run_env['MAC_HERMETIC_FIREFOX_DIR']: if run_env['MAC_HERMETIC_FIREFOX_DIR']:
# if we have a hermetic version of Firefox, then run it # if we have a hermetic version of Firefox, then run it
if os.path.exists(run_env.subst('$MAC_HERMETIC_FIREFOX_DIR')): if os.path.exists(run_env.subst('$MAC_HERMETIC_FIREFOX_DIR')):
...@@ -579,7 +580,7 @@ if run_env.Bit('mac'): ...@@ -579,7 +580,7 @@ if run_env.Bit('mac'):
cleanup_steps = [ cleanup_steps = [
'rm -rf "$MAC_FIREFOX_DIR"', 'rm -rf "$MAC_FIREFOX_DIR"',
] ]
def DeferSelenium(env): def DeferSelenium(env):
if not selenium_good_to_go: if not selenium_good_to_go:
...@@ -604,7 +605,7 @@ def DeferSelenium(env): ...@@ -604,7 +605,7 @@ def DeferSelenium(env):
'--screenshotsdir=$ARTIFACTS_DIR/selenium/screenshots_firefox'])] + '--screenshotsdir=$ARTIFACTS_DIR/selenium/screenshots_firefox'])] +
cleanup_steps, cleanup_steps,
) )
# Require SwiftShader (only if it is available). # Require SwiftShader (only if it is available).
run_env.Requires(run_selenium_firefox, swiftshader_install) run_env.Requires(run_selenium_firefox, swiftshader_install)
......
...@@ -929,6 +929,44 @@ g_suite.testShouldSetVertexBufferData = function() { ...@@ -929,6 +929,44 @@ g_suite.testShouldSetVertexBufferData = function() {
g_test.assertEquals(12, field.size); g_test.assertEquals(12, field.size);
}; };
g_suite.testShouldSetDestinationBufferData = function() {
var json = {
version: o3djs.serialization.supportedVersion,
objects: {
'o3djs.DestinationBuffer': [
{
'custom':{
'numElements':1398,
'fields':[
{
'id':197809,
'type':'o3d.FloatField',
'numComponents':3},
{
'id':197813,
'type':'o3d.FloatField',
'numComponents':3}]
}
}
]
}
};
var pack = g_client.createPack();
var deserializer = o3djs.serialization.createDeserializer(pack, json);
deserializer.archiveInfo = g_archiveInfo;
deserializer.run();
g_test.assertEquals(1, pack.objects.length);
var buffer = pack.objects[0];
g_test.assertEquals(1398, buffer.numElements);
g_test.assertEquals(2, buffer.fields.length);
var field = buffer.fields[0];
g_test.assertEquals('o3d.FloatField', field.className);
g_test.assertEquals(3, field.numComponents);
g_test.assertEquals(12, field.size);
};
g_suite.testShouldSetSourceBufferData = function() { g_suite.testShouldSetSourceBufferData = function() {
var json = { var json = {
version: o3djs.serialization.supportedVersion, version: o3djs.serialization.supportedVersion,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment