summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
Diffstat (limited to 'o3d')
-rw-r--r--o3d/core/cross/buffer_test.cc2
-rw-r--r--o3d/core/cross/field.cc59
-rw-r--r--o3d/core/cross/field.h34
-rw-r--r--o3d/core/cross/field_test.cc51
-rw-r--r--o3d/core/cross/stream.h2
-rw-r--r--o3d/core/cross/stream_test.cc2
-rw-r--r--o3d/import/cross/collada.cc36
-rw-r--r--o3d/serializer/cross/serializer_binary.cc8
8 files changed, 174 insertions, 20 deletions
diff --git a/o3d/core/cross/buffer_test.cc b/o3d/core/cross/buffer_test.cc
index 002c955..7e4561e 100644
--- a/o3d/core/cross/buffer_test.cc
+++ b/o3d/core/cross/buffer_test.cc
@@ -551,7 +551,7 @@ TEST_F(BufferTest, TestVertexBufferFromRawData) {
0, &buffer_float_data[0], 3, kNumElements);
down_cast<UInt32Field*>(buffer->fields()[1].Get())->GetAsUInt32s(
0, &buffer_int_data[0], 2, kNumElements);
- down_cast<UByteNField*>(buffer->fields()[2].Get())->GetAsBytes(
+ down_cast<UByteNField*>(buffer->fields()[2].Get())->GetAsUByteNs(
0, &buffer_byte_data[0], 4, kNumElements);
for (int i = 0; i < kNumElements; ++i) {
diff --git a/o3d/core/cross/field.cc b/o3d/core/cross/field.cc
index c85c9d3..1ccbfde 100644
--- a/o3d/core/cross/field.cc
+++ b/o3d/core/cross/field.cc
@@ -34,6 +34,7 @@
// IndexBuffer.
#include "core/cross/precompile.h"
+#include <vector>
#include "core/cross/field.h"
#include "core/cross/error.h"
#include "core/cross/buffer.h"
@@ -283,6 +284,23 @@ bool Field::RangeValid(unsigned int start_index, unsigned int num_elements) {
return true;
}
+void Field::Copy(const Field& source) {
+ if (!source.IsA(GetClass())) {
+ O3D_ERROR(service_locator())
+ << "source field of type " << source.GetClassName()
+ << " is not compatible with field of type " << GetClassName();
+ return;
+ }
+ if (!source.buffer()) {
+ O3D_ERROR(service_locator()) << "source buffer is null";
+ return;
+ }
+ if (!buffer()) {
+ O3D_ERROR(service_locator()) << "destination buffer is null";
+ return;
+ }
+ ConcreteCopy(source);
+}
// FloatField -------------------
@@ -361,6 +379,16 @@ void FloatField::GetAsFloats(unsigned source_start_index,
num_elements);
}
+void FloatField::ConcreteCopy(const Field& source) {
+ DCHECK(source.IsA(GetClass()));
+ DCHECK(source.buffer());
+ unsigned num_components = source.num_components();
+ unsigned num_elements = source.buffer()->num_elements();
+ scoped_array<float> temp(new float[num_components * num_elements]);
+ source.GetAsFloats(0, temp.get(), num_components, num_elements);
+ SetFromFloats(temp.get(), num_components, 0, num_elements);
+}
+
Field::Ref FloatField::Create(ServiceLocator* service_locator,
Buffer* buffer,
unsigned num_components,
@@ -454,6 +482,17 @@ void UInt32Field::GetAsUInt32s(unsigned source_start_index,
num_elements);
}
+void UInt32Field::ConcreteCopy(const Field& source) {
+ DCHECK(source.IsA(GetClass()));
+ DCHECK(source.buffer());
+ unsigned num_components = source.num_components();
+ unsigned num_elements = source.buffer()->num_elements();
+ scoped_array<uint32> temp(new uint32[num_components * num_elements]);
+ down_cast<const UInt32Field*>(&source)->GetAsUInt32s(
+ 0, temp.get(), num_components, num_elements);
+ SetFromUInt32s(temp.get(), num_components, 0, num_elements);
+}
+
Field::Ref UInt32Field::Create(ServiceLocator* service_locator,
Buffer* buffer,
unsigned num_components,
@@ -543,10 +582,10 @@ void UByteNField::GetAsFloats(unsigned source_start_index,
swizzle_table_);
}
-void UByteNField::GetAsBytes(unsigned source_start_index,
- uint8* destination,
- unsigned destination_stride,
- unsigned num_elements) const {
+void UByteNField::GetAsUByteNs(unsigned source_start_index,
+ uint8* destination,
+ unsigned destination_stride,
+ unsigned num_elements) const {
GetAsWithSwizzle<const uint8, uint8, ConvertUByteNToUByteN>(
this,
source_start_index,
@@ -556,6 +595,18 @@ void UByteNField::GetAsBytes(unsigned source_start_index,
swizzle_table_);
}
+void UByteNField::ConcreteCopy(const Field& source) {
+ DCHECK(source.IsA(GetClass()));
+ DCHECK(source.buffer());
+ unsigned num_components = source.num_components();
+ unsigned num_elements = source.buffer()->num_elements();
+ scoped_array<uint8> temp(new uint8[num_components * num_elements]);
+ down_cast<const UByteNField*>(&source)->GetAsUByteNs(
+ 0, temp.get(), num_components, num_elements);
+ SetFromUByteNs(temp.get(), num_components, 0, num_elements);
+}
+
+
Field::Ref UByteNField::Create(ServiceLocator* service_locator,
Buffer* buffer,
unsigned num_components,
diff --git a/o3d/core/cross/field.h b/o3d/core/cross/field.h
index d44d556..212b003 100644
--- a/o3d/core/cross/field.h
+++ b/o3d/core/cross/field.h
@@ -163,6 +163,19 @@ class Field : public NamedObject {
// outside the buffer associated with this field.
bool RangeValid(unsigned int start_index, unsigned int num_elements);
+ // Copies a field. The field must be of the same type.
+ // Paremeters:
+ // source: field to copy from.
+ void Copy(const Field& source);
+
+ protected:
+ // The concrete version of Copy. Copy calls this function to do the actual
+ // copying after it has verified the types are compatible and the buffers
+ // exist. ConcreteCopy does NOT have to check for those errors.
+ // Paremeters:
+ // source: field to copy from.
+ virtual void ConcreteCopy(const Field& source) = 0;
+
private:
friend class Buffer;
void set_offset(unsigned offset) {
@@ -226,6 +239,10 @@ class FloatField : public Field {
unsigned destination_stride,
unsigned num_elements) const;
+ protected:
+ // Overridden from Field.
+ virtual void ConcreteCopy(const Field& source);
+
private:
FloatField(ServiceLocator* service_locator,
Buffer* buffer,
@@ -297,6 +314,10 @@ class UInt32Field : public Field {
unsigned destination_stride,
unsigned num_elements) const;
+ protected:
+ // Overridden from Field.
+ virtual void ConcreteCopy(const Field& source);
+
private:
UInt32Field(ServiceLocator* service_locator,
Buffer* buffer,
@@ -350,7 +371,7 @@ class UByteNField : public Field {
unsigned destination_stride,
unsigned num_elements) const;
- // Gets this field as byte data.
+ // Gets this field as ubyten data.
//
// This function copies elements from the the field to the destination array.
// It assumes that there are a multiple of N components in the destination
@@ -364,11 +385,14 @@ class UByteNField : public Field {
// destination_stride: stride between elements in the destination in
// destination units.
// num_elements: The number of elements to copy.
- void GetAsBytes(unsigned source_start_index,
- uint8* destination,
- unsigned destination_stride,
- unsigned num_elements) const;
+ void GetAsUByteNs(unsigned source_start_index,
+ uint8* destination,
+ unsigned destination_stride,
+ unsigned num_elements) const;
+ protected:
+ // Overridden from Field.
+ virtual void ConcreteCopy(const Field& source);
private:
UByteNField(ServiceLocator* service_locator,
diff --git a/o3d/core/cross/field_test.cc b/o3d/core/cross/field_test.cc
index b7ce54a..6340f30 100644
--- a/o3d/core/cross/field_test.cc
+++ b/o3d/core/cross/field_test.cc
@@ -261,6 +261,19 @@ TEST_F(FloatFieldTest, TestBasic) {
kFloatsNumElements,
kFloatsNumComponents));
+ Field* new_field = buffer()->CreateField(FloatField::GetApparentClass(),
+ kFloatsNumComponents);
+ ASSERT_TRUE(new_field != NULL);
+ new_field->Copy(*field);
+ memset(&out_floats, 0, sizeof(out_floats));
+ new_field->GetAsFloats(0, &out_floats[0][0], kFloatsStride,
+ kFloatsNumElements);
+
+ EXPECT_TRUE(CompareElements(&kInFloats[0][0],
+ &out_floats[0][0],
+ kFloatsNumElements,
+ kFloatsNumComponents));
+
field->SetFromUInt32s(&kInUInt32s[0][0], kUInt32sStride, 0,
kUInt32sNumElements);
@@ -355,6 +368,20 @@ TEST_F(UInt32FieldTest, TestBasic) {
}
}
+ Field* new_field = buffer()->CreateField(UInt32Field::GetApparentClass(),
+ kUInt32sNumComponents);
+ ASSERT_TRUE(new_field != NULL);
+ new_field->Copy(*field);
+ memset(&out_uint32s, 0, sizeof(out_uint32s));
+ down_cast<UInt32Field*>(new_field)->GetAsUInt32s(
+ 0, &out_uint32s[0][0], kUInt32sStride, kUInt32sNumElements);
+
+ for (unsigned jj = 0; jj < kUInt32sNumElements; ++jj) {
+ for (unsigned ii = 0; ii < kUInt32sNumComponents; ++ii) {
+ EXPECT_EQ(kInUInt32s[jj][ii], out_uint32s[jj][ii]);
+ }
+ }
+
memset(&out_floats, 0, sizeof(out_floats));
field->GetAsFloats(0, &out_floats[0][0], kFloatsStride, kUInt32sNumElements);
@@ -451,17 +478,33 @@ TEST_F(UByteNFieldTest, TestBasic) {
field->SetFromUByteNs(&kInUByteNs[0][0], kUByteNsStride, 0,
kUByteNsNumElements);
+ uint8 out_ubytens[kUByteNsNumElements][kUByteNsNumComponents];
+ memset(&out_ubytens, 0, sizeof(out_ubytens));
+ down_cast<UByteNField*>(field)->GetAsUByteNs(
+ 0, &out_ubytens[0][0], kUByteNsStride, kUByteNsNumElements);
- memset(&out_floats, 0, sizeof(out_floats));
- field->GetAsFloats(0, &out_floats[0][0], kFloatsStride, kUByteNsNumElements);
+ for (unsigned jj = 0; jj < kUByteNsNumElements; ++jj) {
+ for (unsigned ii = 0; ii < kUByteNsNumComponents; ++ii) {
+ EXPECT_EQ(kInUByteNs[jj][ii], out_ubytens[jj][ii]);
+ }
+ }
+
+ Field* new_field = buffer()->CreateField(UByteNField::GetApparentClass(),
+ kUByteNsNumComponents);
+ ASSERT_TRUE(new_field != NULL);
+ new_field->Copy(*field);
+
+ memset(&out_ubytens, 0, sizeof(out_ubytens));
+ down_cast<UByteNField*>(new_field)->GetAsUByteNs(
+ 0, &out_ubytens[0][0], kUByteNsStride, kUByteNsNumElements);
for (unsigned jj = 0; jj < kUByteNsNumElements; ++jj) {
for (unsigned ii = 0; ii < kUByteNsNumComponents; ++ii) {
- EXPECT_EQ(static_cast<float>(kInUByteNs[jj][ii] / 255.0f),
- out_floats[jj][ii]);
+ EXPECT_EQ(kInUByteNs[jj][ii], out_ubytens[jj][ii]);
}
}
+
// Test that we can't make a UByteN field that is not multiple of 4
EXPECT_TRUE(buffer()->CreateField(UByteNField::GetApparentClass(), 1) ==
NULL);
diff --git a/o3d/core/cross/stream.h b/o3d/core/cross/stream.h
index 526b739..15830bd 100644
--- a/o3d/core/cross/stream.h
+++ b/o3d/core/cross/stream.h
@@ -70,7 +70,7 @@ class Stream : public ObjectBase {
int semantic_index);
// Returns a pointer to the associated Field object.
- const Field& field() const {
+ Field& field() const {
// This is guaranteed to be not NULL.
return *field_.Get();
}
diff --git a/o3d/core/cross/stream_test.cc b/o3d/core/cross/stream_test.cc
index bd9d751..cfbacff 100644
--- a/o3d/core/cross/stream_test.cc
+++ b/o3d/core/cross/stream_test.cc
@@ -70,6 +70,8 @@ class FieldTest : public Field {
unsigned num_elements) const { }
virtual bool SetFromMemoryStream(MemoryReadStream* stream) { return true; }
+
+ virtual void ConcreteCopy(const Field& source) { }
};
} // end unnamed namespace
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;
diff --git a/o3d/serializer/cross/serializer_binary.cc b/o3d/serializer/cross/serializer_binary.cc
index 1af3e2c..9b7f523 100644
--- a/o3d/serializer/cross/serializer_binary.cc
+++ b/o3d/serializer/cross/serializer_binary.cc
@@ -144,10 +144,10 @@ void SerializeBuffer(const Buffer &buffer, MemoryBuffer<uint8> *output) {
} else if (field.IsA(UByteNField::GetApparentClass())) {
const UByteNField &byte_field = static_cast<const UByteNField&>(field);
uint8 *byte_destination = reinterpret_cast<uint8*>(destination);
- byte_field.GetAsBytes(0,
- byte_destination,
- field.num_components(),
- num_elements);
+ byte_field.GetAsUByteNs(0,
+ byte_destination,
+ field.num_components(),
+ num_elements);
// Write out the bytes
stream.Write(byte_destination, nitems);
}