mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
use GeomVertexReader/Writer to implement convert_to()
This commit is contained in:
parent
f8acb8d5d4
commit
5ba9232349
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user