| Index: import/cross/collada.cc
|
| ===================================================================
|
| --- import/cross/collada.cc (revision 19848)
|
| +++ import/cross/collada.cc (working copy)
|
| @@ -36,6 +36,7 @@
|
| #include "base/file_path.h"
|
| #include "base/file_util.h"
|
| #include "base/string_util.h"
|
| +#include "core/cross/class_manager.h"
|
| #include "core/cross/curve.h"
|
| #include "core/cross/error.h"
|
| #include "core/cross/function.h"
|
| @@ -53,6 +54,7 @@
|
| #include "import/cross/collada.h"
|
| #include "import/cross/collada_conditioner.h"
|
| #include "import/cross/collada_zip_archive.h"
|
| +#include "import/cross/destination_buffer.h"
|
| #include "utils/cross/file_path_utils.h"
|
|
|
| #define COLLADA_NAMESPACE "collada"
|
| @@ -147,6 +149,12 @@
|
| options);
|
| }
|
|
|
| +void Collada::Init(ServiceLocator* service_locator) {
|
| + ClassManager* class_manager=
|
| + service_locator->GetService<o3d::ClassManager>();
|
| + class_manager->AddTypedClass<DestinationBuffer>();
|
| +}
|
| +
|
| // Parameters:
|
| // pack: The pack into which the scene objects will be placed.
|
| // Returns true on success.
|
| @@ -391,11 +399,13 @@
|
| FCDSceneNode* scene = doc->GetVisualSceneInstance();
|
| if (scene) {
|
| instance_root_ = CreateInstanceTree(scene);
|
| - ImportTree(instance_root_, parent, animation_input);
|
| - ImportTreeInstances(doc, instance_root_);
|
| + if (ImportTree(instance_root_, parent, animation_input)) {
|
| + if (ImportTreeInstances(doc, instance_root_)) {
|
| + status = true;
|
| + }
|
| + }
|
| delete instance_root_;
|
| instance_root_ = NULL;
|
| - status = true;
|
| }
|
| }
|
| }
|
| @@ -796,7 +806,7 @@
|
| // animation_input: The float parameter used as the input to the animation
|
| // (if present). This is usually time. This can be null
|
| // if there is no animation.
|
| -void Collada::ImportTree(NodeInstance *instance,
|
| +bool Collada::ImportTree(NodeInstance *instance,
|
| Transform* parent_transform,
|
| ParamFloat* animation_input) {
|
| FCDSceneNode *node = instance->node();
|
| @@ -807,17 +817,22 @@
|
| // recursively import the rest of the nodes in the tree
|
| const NodeInstance::NodeInstanceList &children = instance->children();
|
| 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) {
|
| FCDSceneNode *node = node_instance->node();
|
| // recursively import the rest of the nodes in the tree
|
| const NodeInstance::NodeInstanceList &children = node_instance->children();
|
| 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();
|
| @@ -847,9 +862,19 @@
|
| case FCDEntity::CONTROLLER: {
|
| FCDControllerInstance* controller_instance =
|
| static_cast<FCDControllerInstance*> (instance);
|
| - Shape* shape = GetSkinnedShape(doc, controller_instance, node_instance);
|
| - if (shape) {
|
| - transform->AddShape(shape);
|
| + FCDController* controller =
|
| + static_cast<FCDController*>(controller_instance->GetEntity());
|
| + if (controller) {
|
| + if (controller->IsSkin()) {
|
| + Shape* shape = GetSkinnedShape(doc,
|
| + controller_instance,
|
| + node_instance);
|
| + if (shape) {
|
| + transform->AddShape(shape);
|
| + } else {
|
| + return false;
|
| + }
|
| + }
|
| }
|
| break;
|
| }
|
| @@ -858,6 +883,7 @@
|
| break;
|
| }
|
| }
|
| + return true;
|
| }
|
|
|
| // Converts an FCollada vertex attribute semantic into an O3D
|
| @@ -1318,9 +1344,23 @@
|
| // skin everything. This is actually what was BuildShape was doing at the
|
| // time this code was written.
|
| const ElementRefArray& elements = shape->GetElementRefs();
|
| - if (elements.empty() || !elements[0]->IsA(Primitive::GetApparentClass())) {
|
| + if (elements.empty()) {
|
| 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());
|
|
|
| String controller_name = WideToUTF8(controller->GetName().c_str());
|
| @@ -1412,16 +1452,29 @@
|
| // 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
|
| // a separate VertexBuffer.
|
| - StreamBank* stream_bank = primitive->stream_bank();
|
| - SourceBuffer* buffer = pack_->Create<SourceBuffer>();
|
| + StreamBank* old_stream_bank = primitive->stream_bank();
|
| + 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>();
|
| + DestinationBuffer* dest_buffer = pack_->Create<DestinationBuffer>();
|
| const StreamParamVector& source_stream_params =
|
| - stream_bank->vertex_stream_params();
|
| - std::vector<Field*> new_fields(source_stream_params.size(), NULL);
|
| + old_stream_bank->vertex_stream_params();
|
| + 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.
|
| for (unsigned ii = 0; ii < source_stream_params.size(); ++ii) {
|
| const Stream& source_stream = source_stream_params[ii]->stream();
|
| 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;
|
| if (field.IsA(FloatField::GetApparentClass()) &&
|
| (field.num_components() == 3 ||
|
| @@ -1437,25 +1490,44 @@
|
| if (num_source_vertices != num_vertices) {
|
| O3D_ERROR(service_locator_)
|
| << "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 '"
|
| << skin->name().c_str() << "'";
|
| return NULL;
|
| }
|
| - new_fields[ii] = buffer->CreateField(FloatField::GetApparentClass(),
|
| - num_source_components);
|
| + source_fields[ii] = source_buffer->CreateField(
|
| + 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) {
|
| // It's a shared field, copy it to the shared buffer.
|
| - new_fields[ii] = shared_buffer->CreateField(field.GetClass(),
|
| - field.num_components());
|
| + source_fields[ii] = shared_buffer->CreateField(field.GetClass(),
|
| + field.num_components());
|
| + new_stream_bank->SetVertexStream(source_stream.semantic(),
|
| + source_stream.semantic_index(),
|
| + source_fields[ii],
|
| + 0);
|
| }
|
| }
|
|
|
| - if (!buffer->AllocateElements(num_vertices) ||
|
| - !shared_buffer->AllocateElements(num_vertices)) {
|
| + if (!source_buffer->AllocateElements(num_vertices) ||
|
| + !shared_buffer->AllocateElements(num_vertices) ||
|
| + !dest_buffer->AllocateElements(num_vertices)) {
|
| O3D_ERROR(service_locator_)
|
| << "Failed to allocate destination vertex buffer";
|
| return NULL;
|
| @@ -1475,7 +1547,7 @@
|
| case Stream::TANGENT: {
|
| copied = true;
|
| 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);
|
| field.GetAsFloats(0, &data[0], num_source_components,
|
| @@ -1516,30 +1588,38 @@
|
| }
|
| }
|
| }
|
| - new_field->SetFromFloats(&data[0], num_source_components, 0,
|
| - num_vertices);
|
| + source_field->SetFromFloats(&data[0], num_source_components, 0,
|
| + num_vertices);
|
| // Bind streams
|
| skin_eval->SetVertexStream(source_stream.semantic(),
|
| source_stream.semantic_index(),
|
| - new_field,
|
| + source_field,
|
| 0);
|
| - stream_bank->BindStream(skin_eval,
|
| - source_stream.semantic(),
|
| - source_stream.semantic_index());
|
| + new_stream_bank->BindStream(skin_eval,
|
| + source_stream.semantic(),
|
| + source_stream.semantic_index());
|
| break;
|
| }
|
| }
|
| }
|
| if (!copied) {
|
| - Field* new_field = new_fields[ii];
|
| - new_field->Copy(field);
|
| - field.buffer()->RemoveField(&source_stream.field());
|
| - stream_bank->SetVertexStream(source_stream.semantic(),
|
| - source_stream.semantic_index(),
|
| - new_field,
|
| - 0);
|
| + Field* source_field = source_fields[ii];
|
| + source_field->Copy(field);
|
| }
|
| }
|
| +
|
| + // 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;
|
| }
|
|
|