diff options
author | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-09 15:52:10 +0000 |
---|---|---|
committer | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-09 15:52:10 +0000 |
commit | c8b58a46e4f97791f81500006e464a94d68c8c12 (patch) | |
tree | 8991b7d38e19d9808ef273049a57c7338f4122d2 /o3d/core | |
parent | 1b91f510fdda3d6e764e0476df5a82c64ae2975e (diff) | |
download | chromium_src-c8b58a46e4f97791f81500006e464a94d68c8c12.zip chromium_src-c8b58a46e4f97791f81500006e464a94d68c8c12.tar.gz chromium_src-c8b58a46e4f97791f81500006e464a94d68c8c12.tar.bz2 |
This CL makes the collada importer handle skinned data
better.
Specifically, it takes the original VertexBuffer and
splits it. One VertexBuffer contains the parts fields
that get skinned. (POSITION, NORMAL, etc...) The other
VertexBuffer contains the fields that don't get Skinned.
(COLOR, TEXCOORD, etc...)
That way instancing you can share the non-skinned
VertexBuffer.
The next step is to not serialize the skinned
VertexBuffer's contents.
Review URL: http://codereview.chromium.org/118156
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17942 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/core')
-rw-r--r-- | o3d/core/cross/buffer_test.cc | 2 | ||||
-rw-r--r-- | o3d/core/cross/field.cc | 59 | ||||
-rw-r--r-- | o3d/core/cross/field.h | 34 | ||||
-rw-r--r-- | o3d/core/cross/field_test.cc | 51 | ||||
-rw-r--r-- | o3d/core/cross/stream.h | 2 | ||||
-rw-r--r-- | o3d/core/cross/stream_test.cc | 2 |
6 files changed, 135 insertions, 15 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 |