diff options
Diffstat (limited to 'o3d/import')
-rw-r--r-- | o3d/import/cross/collada.cc | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/o3d/import/cross/collada.cc b/o3d/import/cross/collada.cc index b62ae8f..64d39fc 100644 --- a/o3d/import/cross/collada.cc +++ b/o3d/import/cross/collada.cc @@ -1378,8 +1378,23 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, Matrix4 matrix(bind_shape_matrix); // Copy shape->primitive buffers. + // Here we need to also split the original vertex buffer. The issue is + // the original VertexBuffer might contain POSITION, NORMAL, TEXCOORD, + // COLOR. Of those, only POSITION and NORMAL are copied to the SourceBuffer. + // The VertexBuffer still contains POSITON, NORMAL, TEXCOORD, and COLOR so + // two issues come up + // + // 1) If we serialize that VertexBuffer, POSITION and NORMAL are stored + // twice. Once in the SourceBuffer, again in the VertexBuffer. That's a lot + // of data to download just to throw it away. + // + // 2) If we want to instance the skin we'll need to make a new VertexBuffer + // 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>(); + VertexBuffer* shared_buffer = pack_->Create<VertexBuffer>(); const StreamParamVector& source_stream_params = stream_bank->vertex_stream_params(); std::vector<Field*> new_fields(source_stream_params.size(), NULL); @@ -1387,6 +1402,7 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, 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(); + bool copied = false; if (field.IsA(FloatField::GetApparentClass()) && (field.num_components() == 3 || field.num_components() == 4)) { @@ -1395,6 +1411,7 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, case Stream::NORMAL: case Stream::BINORMAL: case Stream::TANGENT: { + copied = true; unsigned num_source_components = field.num_components(); unsigned num_source_vertices = source_stream.GetMaxVertices(); if (num_source_vertices != num_vertices) { @@ -1410,9 +1427,15 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, } } } + if (!copied) { + // It's a shared field, copy it to the shared buffer. + new_fields[ii] = shared_buffer->CreateField(field.GetClass(), + field.num_components()); + } } - if (!buffer->AllocateElements(num_vertices)) { + if (!buffer->AllocateElements(num_vertices) || + !shared_buffer->AllocateElements(num_vertices)) { O3D_ERROR(service_locator_) << "Failed to allocate destination vertex buffer"; return NULL; @@ -1421,6 +1444,7 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, 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(); + bool copied = false; if (field.IsA(FloatField::GetApparentClass()) && (field.num_components() == 3 || field.num_components() == 4)) { @@ -1429,6 +1453,7 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, case Stream::NORMAL: case Stream::BINORMAL: case Stream::TANGENT: { + copied = true; unsigned num_source_components = field.num_components(); Field* new_field = new_fields[ii]; @@ -1485,6 +1510,15 @@ Shape* Collada::BuildSkinnedShape(FCDocument* doc, } } } + 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); + } } } return shape; |