use GeomVertexReader/Writer to implement convert_to()

This commit is contained in:
David Rose 2005-03-27 19:02:40 +00:00
parent f8acb8d5d4
commit 5ba9232349
5 changed files with 218 additions and 276 deletions

View File

@ -327,19 +327,62 @@ convert_to(const qpGeomVertexFormat *new_format) const {
int new_i = new_format->get_array_with(data_type->get_name());
if (new_i >= 0 && done_arrays.count(new_i) == 0) {
// The data type exists in the new format; we have to copy it.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
const qpGeomVertexArrayFormat *new_array_format =
new_format->get_array(new_i);
const qpGeomVertexDataType *new_data_type =
new_array_format->get_data_type(data_type->get_name());
new_data_type->copy_records
(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
data_type, num_vertices);
if (new_data_type->is_bytewise_equivalent(*data_type)) {
// We can do a quick bytewise copy.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
bytewise_copy(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
data_type, num_vertices);
} else if (new_data_type->is_packed_argb() &&
data_type->is_uint8_rgba()) {
// A common special case: OpenGL color to DirectX color.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
uint8_rgba_to_packed_argb
(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
num_vertices);
} else if (new_data_type->is_uint8_rgba() &&
data_type->is_packed_argb()) {
// Another common special case: DirectX color to OpenGL
// color.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
packed_argb_to_uint8_rgba
(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
num_vertices);
} else {
// A generic copy.
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "generic copy " << *new_data_type << " from "
<< *data_type << "\n";
}
qpGeomVertexReader from(this);
from.set_data_type(i, data_type);
qpGeomVertexWriter to(new_data);
to.set_data_type(new_i, new_data_type);
while (!from.is_at_end()) {
to.set_data4f(from.get_data4f());
}
}
}
}
}
@ -630,6 +673,110 @@ get_array_info(const InternalName *name,
return false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::bytewise_copy
// Access: Private, Static
// Description: Quickly copies data without the need to convert it.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
bytewise_copy(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "bytewise_copy(" << (void *)to << ", " << to_stride
<< ", " << (const void *)from << ", " << from_stride
<< ", " << *from_type << ", " << num_records << ")\n";
}
if (to_stride == from_type->get_total_bytes() &&
from_stride == from_type->get_total_bytes()) {
// Fantastic! It's just a linear array of this one data type.
// Copy the whole thing all at once.
memcpy(to, from, num_records * from_type->get_total_bytes());
} else {
// Ok, it's interleaved in with other data. Copy them one record
// at a time.
while (num_records > 0) {
memcpy(to, from, from_type->get_total_bytes());
to += to_stride;
from += from_stride;
num_records--;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::packed_argb_to_uint8_rgba
// Access: Private, Static
// Description: Quickly converts DirectX-style color to OpenGL-style
// color.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
packed_argb_to_uint8_rgba(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
int num_records) {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "packed_argb_to_uint8_rgba(" << (void *)to << ", " << to_stride
<< ", " << (const void *)from << ", " << from_stride
<< ", " << num_records << ")\n";
}
typedef union {
unsigned char _b[4];
PN_uint32 _i;
} packed_8888;
while (num_records > 0) {
packed_8888 dword;
dword._i = *(const PN_uint32 *)from;
to[0] = dword._b[1];
to[1] = dword._b[2];
to[2] = dword._b[3];
to[3] = dword._b[0];
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::uint8_rgba_to_packed_argb
// Access: Private, Static
// Description: Quickly converts OpenGL-style color to DirectX-style
// color.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
int num_records) {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "uint8_rgba_to_packed_argb(" << (void *)to << ", " << to_stride
<< ", " << (const void *)from << ", " << from_stride
<< ", " << num_records << ")\n";
}
typedef union {
unsigned char _b[4];
PN_uint32 _i;
} packed_8888;
while (num_records > 0) {
packed_8888 dword;
dword._b[0] = from[3];
dword._b[1] = from[0];
dword._b[2] = from[1];
dword._b[3] = from[2];
*(PN_uint32 *)to = dword._i;
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::do_set_num_vertices
// Access: Private

View File

@ -123,6 +123,20 @@ public:
qpGeomVertexDataType::NumericType &numeric_type,
int &start, int &stride) const;
private:
static void bytewise_copy(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records);
static void
packed_argb_to_uint8_rgba(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
int num_records);
static void
uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
int num_records);
private:
string _name;
CPT(qpGeomVertexFormat) _format;

View File

@ -164,6 +164,50 @@ overlaps_with(int start_byte, int num_bytes) const {
_start + _total_bytes > start_byte);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::is_bytewise_equivalent
// Access: Published
// Description: Returns true if the data store of this data type is
// exactly the same as that of the other, irrespective
// of name or start position within the record.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
is_bytewise_equivalent(const qpGeomVertexDataType &other) const {
// The _contents are relevant, because they specify such things as
// the difference between C_rgba and C_argb.
return (_num_components == other._num_components &&
_numeric_type == other._numeric_type &&
_contents == other._contents);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::is_packed_argb
// Access: Public
// Description: Returns true if this data type is the standard
// DirectX representation of 4-component color: C_argb,
// in NT_packed_8888, with 1 component (4 values).
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
is_packed_argb() const {
return (_num_components == 1 &&
_numeric_type == NT_packed_8888 &&
_contents == C_argb);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::is_uint8_rgba
// Access: Public
// Description: Returns true if this data type is the standard
// OpenGL representation of 4-component color: C_rgba,
// in NT_uint8, with 4 components.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
is_uint8_rgba() const {
return (_num_components == 4 &&
_numeric_type == NT_uint8 &&
_contents == C_rgba);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::compare_to
// Access: Public

View File

@ -80,243 +80,3 @@ void qpGeomVertexDataType::
output(ostream &out) const {
out << *get_name() << "(" << get_num_components() << ")";
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_records
// Access: Published
// Description: Copies and converts from one data type to another.
// Copies the num_records records from the "from"
// buffer, encoded with from_type, to the "to" buffer,
// encoded with this current type, converting each one
// as necessary.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_records(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
// Temp for debugging.
static ConfigVariableBool do_copy_generic("copy-generic", false);
if (do_copy_generic) {
copy_generic(to, to_stride, from, from_stride, from_type, num_records);
return;
}
if (get_numeric_type() == from_type->get_numeric_type() &&
get_num_values() == from_type->get_num_values()) {
// An easy case.
copy_no_convert(to, to_stride, from, from_stride, from_type, num_records);
} else if (get_numeric_type() == NT_uint8 && from_type->get_numeric_type() == NT_packed_8888 &&
get_num_values() == from_type->get_num_values()) {
copy_argb_to_uint8(to, to_stride, from, from_stride, from_type, num_records);
} else if (get_numeric_type() == NT_packed_8888 && from_type->get_numeric_type() == NT_uint8 &&
get_num_values() == from_type->get_num_values()) {
copy_uint8_to_argb(to, to_stride, from, from_stride, from_type, num_records);
} else {
copy_generic(to, to_stride, from, from_stride, from_type, num_records);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_no_convert
// Access: Private
// Description: Quickly copies data without the need to convert it.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_no_convert(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
if (to_stride == _total_bytes && from_stride == _total_bytes) {
// Fantastic! It's just a linear array of this one data type.
// Copy the whole thing all at once.
memcpy(to, from, num_records * _total_bytes);
} else {
// Ok, it's interleaved in with other data. Copy them one record
// at a time.
while (num_records > 0) {
memcpy(to, from, _total_bytes);
to += to_stride;
from += from_stride;
num_records--;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_argb_to_uint8
// Access: Private
// Description: Converts packed_argb to uint8-based r, g, b, a.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_argb_to_uint8(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
while (num_records > 0) {
PN_uint32 packed_argb = *(const PN_uint32 *)from;
to[0] = ((packed_argb >> 16) & 0xff);
to[1] = ((packed_argb >> 8) & 0xff);
to[2] = (packed_argb & 0xff);
to[3] = ((packed_argb >> 24) & 0xff);
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_uint8_to_argb
// Access: Private
// Description: Converts uint8-based r, g, b, a to packed_argb.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_uint8_to_argb(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
while (num_records > 0) {
PN_uint32 packed_argb = ((from[3] << 24) | (from[0] << 16) | (from[1] << 8) | from[2]);
*(PN_uint32 *)to = packed_argb;
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_generic
// Access: Private
// Description: A more general anything-to-anything copy (somewhat
// more expensive than the above).
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_generic(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
int num_values_to_copy = min(get_num_values(), from_type->get_num_values());
int num_values_to_fill = get_num_values() - num_values_to_copy;
while (num_records > 0) {
int vi = 0;
while (vi < num_values_to_copy) {
float value = from_type->get_value(from, vi);
set_value(to, vi, value);
++vi;
}
while (vi < num_values_to_fill) {
set_value(to, vi, 0.0f);
++vi;
}
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_value
// Access: Private
// Description: Returns the nth value of the data type, expressed as
// a float.
////////////////////////////////////////////////////////////////////
float qpGeomVertexDataType::
get_value(const unsigned char *data, int n) const {
switch (get_numeric_type()) {
case NT_uint16:
return (float)data[n];
case NT_uint8:
return (float)data[n] / 255.0f;
case qpGeomVertexDataType::NT_packed_8888:
{
int element = n / 4;
const PN_uint32 *int_array = (const PN_uint32 *)data;
PN_uint32 packed_argb = int_array[element];
switch (n % 4) {
case 0:
return (float)((packed_argb >> 16) & 0xff) / 255.0f;
case 1:
return (float)((packed_argb >> 8) & 0xff) / 255.0f;
case 2:
return (float)(packed_argb & 0xff) / 255.0f;
case 3:
return (float)((packed_argb >> 24) & 0xff) / 255.0f;
}
}
break;
case qpGeomVertexDataType::NT_float32:
{
const PN_float32 *float_array = (const PN_float32 *)data;
return float_array[n];
}
}
return 0.0f;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::set_value
// Access: Private
// Description: Modifies the nth value of the data type.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
set_value(unsigned char *data, int n, float value) const {
switch (get_numeric_type()) {
case NT_uint16:
data[n] = (int)value;
break;
case NT_uint8:
data[n] = (int)(value * 255.0f);
break;
case qpGeomVertexDataType::NT_packed_8888:
{
int element = n / 4;
union {
PN_uint32 _packed_argb;
struct {
unsigned char _a;
unsigned char _r;
unsigned char _g;
unsigned char _b;
} _argb;
} color;
PN_uint32 *int_array = (PN_uint32 *)data;
color._packed_argb = int_array[element];
switch (n % 4) {
case 0:
color._argb._r = (int)(value * 255.0f);
break;
case 1:
color._argb._g = (int)(value * 255.0f);
break;
case 2:
color._argb._b = (int)(value * 255.0f);
break;
case 3:
color._argb._a = (int)(value * 255.0f);
break;
}
int_array[element] = color._packed_argb;
}
break;
case qpGeomVertexDataType::NT_float32:
PN_float32 *float_array = (PN_float32 *)data;
float_array[n] = value;
break;
}
}

View File

@ -37,7 +37,7 @@ PUBLISHED:
enum NumericType {
NT_uint8, // An integer 0..255
NT_uint16, // An integer 0..65535
NT_packed_8888, // DirectX style, four byte values packed in a dword
NT_packed_8888, // DirectX style, four byte values packed in a uint32
NT_float32, // A floating-point number
};
@ -69,42 +69,19 @@ PUBLISHED:
INLINE int get_total_bytes() const;
INLINE bool overlaps_with(int start_byte, int num_bytes) const;
INLINE bool is_bytewise_equivalent(const qpGeomVertexDataType &other) const;
void output(ostream &out) const;
public:
INLINE bool is_packed_argb() const;
INLINE bool is_uint8_rgba() const;
INLINE int compare_to(const qpGeomVertexDataType &other) const;
INLINE bool operator == (const qpGeomVertexDataType &other) const;
INLINE bool operator != (const qpGeomVertexDataType &other) const;
INLINE bool operator < (const qpGeomVertexDataType &other) const;
void copy_records(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
private:
void copy_no_convert(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
void copy_argb_to_uint8(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
void copy_uint8_to_argb(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
void copy_generic(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
float get_value(const unsigned char *data, int n) const;
void set_value(unsigned char *data, int n, float value) const;
private:
CPT(InternalName) _name;
int _num_components;