qpGeomVertexWriter

This commit is contained in:
David Rose 2005-03-27 16:43:46 +00:00
parent 52ffd8194b
commit f8acb8d5d4
22 changed files with 2312 additions and 1358 deletions

View File

@ -197,7 +197,12 @@ update() {
PStatTimer timer(_char_pcollector);
// First, update all the joints and sliders.
bool any_changed = get_bundle()->update();
bool any_changed;
if (even_animation) {
any_changed = get_bundle()->force_update();
} else {
any_changed = get_bundle()->update();
}
// Now update the vertices, if we need to. This is likely to be a
// slow operation.

View File

@ -36,7 +36,7 @@
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexIterator.h"
#include "qpgeomVertexWriter.h"
#include "qpgeom.h"
#include "qpgeomTriangles.h"
#include "qpgeomTristrips.h"
@ -1987,21 +1987,21 @@ make_vertex_data(const EggRenderState *render_state,
// And fill the data from the vertex pool.
EggVertexPool::const_iterator vi;
for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
qpGeomVertexIterator gvi(vertex_data);
qpGeomVertexWriter gvi(vertex_data);
EggVertex *vertex = (*vi);
gvi.set_vertex(vertex->get_index());
gvi.set_data_type(InternalName::get_vertex());
gvi.set_data4f(LCAST(float, vertex->get_pos4() * transform));
gvi.add_data4f(LCAST(float, vertex->get_pos4() * transform));
if (vertex->has_normal()) {
gvi.set_data_type(InternalName::get_normal());
gvi.set_data3f(LCAST(float, vertex->get_normal() * transform));
gvi.add_data3f(LCAST(float, vertex->get_normal() * transform));
}
if (vertex->has_color()) {
gvi.set_data_type(InternalName::get_color());
gvi.set_data4f(vertex->get_color());
gvi.add_data4f(vertex->get_color());
}
EggVertex::const_uv_iterator uvi;

View File

@ -31,7 +31,7 @@
#include "qpgeomTristrips.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexIterator.h"
#include "qpgeomVertexWriter.h"
#include "texturePool.h"
#include "textureAttrib.h"
#include "colorAttrib.h"
@ -635,26 +635,26 @@ load_default_model(const NodePath &parent) {
PT(qpGeomVertexData) vdata = new qpGeomVertexData
(string(), qpGeomVertexFormat::get_v3n3cpt2(),
qpGeomUsageHint::UH_static);
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator normal(vdata, InternalName::get_normal());
qpGeomVertexIterator color(vdata, InternalName::get_color());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
qpGeomVertexWriter vertex(vdata, InternalName::get_vertex());
qpGeomVertexWriter normal(vdata, InternalName::get_normal());
qpGeomVertexWriter color(vdata, InternalName::get_color());
qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
vertex.set_data3f(Vertexf::rfu(1.0, 0.0, 0.0));
vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 1.0));
vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
vertex.add_data3f(Vertexf::rfu(1.0, 0.0, 0.0));
vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 1.0));
normal.set_data3f(Normalf::back());
normal.set_data3f(Normalf::back());
normal.set_data3f(Normalf::back());
normal.add_data3f(Normalf::back());
normal.add_data3f(Normalf::back());
normal.add_data3f(Normalf::back());
color.set_data4f(0.5, 0.5, 1.0, 1.0);
color.set_data4f(0.5, 0.5, 1.0, 1.0);
color.set_data4f(0.5, 0.5, 1.0, 1.0);
color.add_data4f(0.5, 0.5, 1.0, 1.0);
color.add_data4f(0.5, 0.5, 1.0, 1.0);
color.add_data4f(0.5, 0.5, 1.0, 1.0);
texcoord.set_data2f(0.0, 0.0);
texcoord.set_data2f(1.0, 0.0);
texcoord.set_data2f(0.0, 1.0);
texcoord.add_data2f(0.0, 0.0);
texcoord.add_data2f(1.0, 0.0);
texcoord.add_data2f(0.0, 1.0);
PT(qpGeomTriangles) tri = new qpGeomTriangles(qpGeomUsageHint::UH_static);
tri->add_consecutive_vertices(0, 3);
@ -1062,18 +1062,18 @@ load_image_as_model(const Filename &filename) {
PT(qpGeomVertexData) vdata = new qpGeomVertexData
(string(), qpGeomVertexFormat::get_v3t2(),
qpGeomUsageHint::UH_static);
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
qpGeomVertexWriter vertex(vdata, InternalName::get_vertex());
qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
vertex.set_data3f(Vertexf::rfu(left, 0.02f, top));
vertex.set_data3f(Vertexf::rfu(left, 0.02f, bottom));
vertex.set_data3f(Vertexf::rfu(right, 0.02f, top));
vertex.set_data3f(Vertexf::rfu(right, 0.02f, bottom));
vertex.add_data3f(Vertexf::rfu(left, 0.02f, top));
vertex.add_data3f(Vertexf::rfu(left, 0.02f, bottom));
vertex.add_data3f(Vertexf::rfu(right, 0.02f, top));
vertex.add_data3f(Vertexf::rfu(right, 0.02f, bottom));
texcoord.set_data2f(0.0f, 1.0f);
texcoord.set_data2f(0.0f, 0.0f);
texcoord.set_data2f(1.0f, 1.0f);
texcoord.set_data2f(1.0f, 0.0f);
texcoord.add_data2f(0.0f, 1.0f);
texcoord.add_data2f(0.0f, 0.0f);
texcoord.add_data2f(1.0f, 1.0f);
texcoord.add_data2f(1.0f, 0.0f);
PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static);
strip->add_consecutive_vertices(0, 4);

View File

@ -35,8 +35,8 @@
qpgeomVertexData.h qpgeomVertexData.I \
qpgeomVertexDataType.h qpgeomVertexDataType.I \
qpgeomVertexFormat.h qpgeomVertexFormat.I \
qpgeomVertexIterator.h qpgeomVertexIterator.I \
qpgeomVertexReader.h qpgeomVertexReader.I \
qpgeomVertexWriter.h qpgeomVertexWriter.I \
indexBufferContext.I indexBufferContext.h \
internalName.I internalName.h \
material.I material.h materialPool.I materialPool.h \
@ -81,8 +81,8 @@
qpgeomVertexData.cxx \
qpgeomVertexDataType.cxx \
qpgeomVertexFormat.cxx \
qpgeomVertexIterator.cxx \
qpgeomVertexReader.cxx \
qpgeomVertexWriter.cxx \
indexBufferContext.cxx \
material.cxx \
internalName.cxx \
@ -125,8 +125,8 @@
qpgeomVertexData.h qpgeomVertexData.I \
qpgeomVertexDataType.h qpgeomVertexDataType.I \
qpgeomVertexFormat.h qpgeomVertexFormat.I \
qpgeomVertexIterator.h qpgeomVertexIterator.I \
qpgeomVertexReader.h qpgeomVertexReader.I \
qpgeomVertexWriter.h qpgeomVertexWriter.I \
indexBufferContext.I indexBufferContext.h \
internalName.I internalName.h \
material.I material.h \

View File

@ -27,5 +27,5 @@
#include "qpgeomVertexData.cxx"
#include "qpgeomVertexDataType.cxx"
#include "qpgeomVertexFormat.cxx"
#include "qpgeomVertexIterator.cxx"
#include "qpgeomVertexReader.cxx"
#include "qpgeomVertexWriter.cxx"

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "qpgeom.h"
#include "qpgeomVertexReader.h"
#include "pStatTimer.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -404,6 +405,32 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomMunger *munger,
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::calc_tight_bounds
// Access: Public, Virtual
// Description: Expands min_point and max_point to include all of the
// vertices in the Geom, if any. found_any is set true
// if any points are found. It is the caller's
// responsibility to initialize min_point, max_point,
// and found_any before calling this function.
////////////////////////////////////////////////////////////////////
void qpGeom::
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat) const {
CDReader cdata(_cycler);
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
(*pi)->calc_tight_bounds(min_point, max_point, found_any, vertex_data,
got_mat, mat);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_next_modified
// Access: Public, Static
@ -437,56 +464,22 @@ recompute_bound() {
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
// Now actually compute the bounding volume by putting it around all
// of our vertices.
CDReader cdata(_cycler);
// Now actually compute the bounding volume. We do this by using
// calc_tight_bounds to determine our minmax first.
LPoint3f points[2];
bool found_any = false;
calc_tight_bounds(points[0], points[1], found_any, get_vertex_data(),
false, LMatrix4f::ident_mat());
if (found_any) {
// Then we put the bounding volume around both of those points.
// Technically, we should put it around the eight points at the
// corners of the rectangular solid, but we happen to know that
// the two diagonally opposite points is good enough to define any
// of our bound volume types.
const qpGeomVertexFormat *format = cdata->_data->get_format();
int array_index = format->get_array_with(InternalName::get_vertex());
if (array_index < 0) {
// No vertex data.
return bound;
}
const qpGeomVertexArrayFormat *array_format = format->get_array(array_index);
const qpGeomVertexDataType *data_type =
array_format->get_data_type(InternalName::get_vertex());
int stride = array_format->get_stride();
int start = data_type->get_start();
int num_components = data_type->get_num_components();
CPTA_uchar array_data = cdata->_data->get_array(array_index)->get_data();
if (stride == 3 * sizeof(PN_float32) && start == 0 && num_components == 3 &&
(array_data.size() % stride) == 0) {
// Here's an easy special case: it's a standalone table of vertex
// positions, with nothing else in the middle, so we can use
// directly as an array of LPoint3f's.
const LPoint3f *vertices_begin = (const LPoint3f *)&array_data[0];
const LPoint3f *vertices_end = (const LPoint3f *)&array_data[array_data.size()];
gbv->around(vertices_begin, vertices_end);
} else {
// Otherwise, we have to copy the vertex positions out one at time.
pvector<LPoint3f> vertices;
size_t p = start;
while (p + stride <= array_data.size()) {
const PN_float32 *v = (const PN_float32 *)&array_data[p];
LPoint3f vertex;
qpGeomVertexData::to_vec3(vertex, v, num_components);
vertices.push_back(vertex);
p += stride;
}
const LPoint3f *vertices_begin = &vertices[0];
const LPoint3f *vertices_end = vertices_begin + vertices.size();
gbv->around(vertices_begin, vertices_end);
const LPoint3f *points_begin = &points[0];
const LPoint3f *points_end = points_begin + 2;
gbv->around(points_begin, points_end);
}
return bound;

View File

@ -97,6 +97,11 @@ public:
const qpGeomMunger *munger,
const qpGeomVertexData *vertex_data) const;
void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat) const;
static UpdateSeq get_next_modified();
protected:

View File

@ -21,6 +21,7 @@
#include "qpgeomVertexData.h"
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexDataType.h"
#include "qpgeomVertexReader.h"
#include "preparedGraphicsObjects.h"
#include "internalName.h"
#include "bamReader.h"
@ -671,46 +672,55 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
void qpGeomPrimitive::
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data) const {
CDReader cdata(_cycler);
const qpGeomVertexFormat *format = vertex_data->get_format();
int array_index = format->get_array_with(InternalName::get_vertex());
if (array_index < 0) {
const qpGeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat) const {
qpGeomVertexReader reader(vertex_data, InternalName::get_vertex());
if (!reader.has_data_type()) {
// No vertex data.
return;
}
const qpGeomVertexArrayFormat *array_format = format->get_array(array_index);
const qpGeomVertexDataType *data_type =
array_format->get_data_type(InternalName::get_vertex());
CDReader cdata(_cycler);
int stride = array_format->get_stride();
int start = data_type->get_start();
int num_components = data_type->get_num_components();
CPTA_uchar array_data = vertex_data->get_array(array_index)->get_data();
PTA_ushort::const_iterator ii;
for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
int index = (int)(*ii);
const PN_float32 *v = (const PN_float32 *)&array_data[start + index * stride];
LPoint3f vertex;
qpGeomVertexData::to_vec3(vertex, v, num_components);
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
if (got_mat) {
PTA_ushort::const_iterator ii;
for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
int index = (int)(*ii);
reader.set_vertex(index);
const LVecBase3f &vertex = reader.get_data3f();
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
}
}
} else {
PTA_ushort::const_iterator ii;
for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
int index = (int)(*ii);
reader.set_vertex(index);
LPoint3f vertex = mat.xform_point(reader.get_data3f());
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
}
}
}
}

View File

@ -162,9 +162,10 @@ private:
public:
virtual void draw(GraphicsStateGuardianBase *gsg) const=0;
virtual void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data) const;
void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat) const;
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;

View File

@ -19,6 +19,7 @@
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexDataType.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexReader.h"
#include "indent.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -430,20 +431,24 @@ write_with_data(ostream &out, int indent_level,
const qpGeomVertexData *data, int array_index) const {
consider_sort_data_types();
int num_vertices = data->get_num_vertices();
qpGeomVertexReader reader(data);
for (int i = 0; i < num_vertices; i++) {
indent(out, indent_level)
<< "vertex index " << i << ":\n";
reader.set_vertex(i);
DataTypes::const_iterator dti;
for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
const qpGeomVertexDataType *data_type = (*dti);
int num_values = min(data_type->get_num_values(), 4);
float data_values[4];
data->get_data(array_index, data_type, i, data_values, num_values);
reader.set_data_type(array_index, data_type);
const LVecBase4f &d = reader.get_data4f();
indent(out, indent_level + 2)
<< *data_type->get_name();
for (int v = 0; v < num_values; v++) {
out << " " << data_values[v];
out << " " << d[v];
}
out << "\n";
}

View File

@ -17,8 +17,8 @@
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexData.h"
#include "qpgeomVertexIterator.h"
#include "qpgeomVertexReader.h"
#include "qpgeomVertexWriter.h"
#include "pStatTimer.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -381,8 +381,8 @@ scale_color(const LVecBase4f &color_scale, int num_components,
contents, get_usage_hint(), true);
// Now go through and apply the scale, copying it to the new data.
qpGeomVertexIterator from(this, InternalName::get_color());
qpGeomVertexIterator to(new_data, InternalName::get_color());
qpGeomVertexReader from(this, InternalName::get_color());
qpGeomVertexWriter to(new_data, InternalName::get_color());
for (int i = 0; i < num_vertices; i++) {
Colorf color = from.get_data4f();
@ -423,7 +423,7 @@ set_color(const Colorf &color, int num_components,
contents, get_usage_hint(), true);
// Now go through and set the new color value.
qpGeomVertexIterator to(new_data, InternalName::get_color());
qpGeomVertexWriter to(new_data, InternalName::get_color());
for (int i = 0; i < num_vertices; i++) {
to.set_data4f(color);
@ -522,16 +522,23 @@ replace_data_type(const InternalName *name, int num_components,
new qpGeomVertexArrayFormat(name, num_components, numeric_type, contents);
new_type_array = new_format->add_array(type_array_format);
}
CPT(qpGeomVertexFormat) format =
qpGeomVertexFormat::register_format(new_format);
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Replacing data type " << *name << "; converting "
<< get_num_vertices() << " vertices from "
<< *_format << " to " << *new_format << "\n";
}
PT(qpGeomVertexData) new_data =
new qpGeomVertexData(get_name(),
qpGeomVertexFormat::register_format(new_format),
usage_hint);
new qpGeomVertexData(get_name(), format, usage_hint);
if (keep_animation) {
new_data->set_transform_blend_palette(get_transform_blend_palette());
}
int j = 0;
int num_arrays = get_num_arrays();
for (int i = 0; i < num_arrays; ++i) {
@ -589,398 +596,6 @@ write(ostream &out, int indent_level) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_data
// Access: Public
// Description: Sets the nth vertex to a particular value. Query the
// format to get the array index and data_type
// parameters for the particular data type you want to
// set.
//
// This flavor of set_data() accepts a generic float
// array and a specific number of dimensions. The new
// data will be copied from the num_values elements
// of data.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const float *data, int num_values) {
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
{
CDReader cdata(_cycler);
int array_size = (int)cdata->_arrays[array]->get_data_size_bytes();
if (element + data_type->get_total_bytes() > array_size) {
// Whoops, we need more vertices!
CDWriter cdataw(_cycler, cdata);
do_set_num_vertices(vertex + 1, cdataw);
}
}
PTA_uchar array_data = modify_array(array)->modify_data();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint16:
{
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_uint16 *)&array_data[element] = (int)data[i];
element += sizeof(PN_uint16);
++i;
}
while (i < data_type->get_num_values()) {
*(PN_uint16 *)&array_data[element] = 0;
element += sizeof(PN_uint16);
++i;
}
}
break;
case qpGeomVertexDataType::NT_uint8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
int value = (int)(data[i] * 255.0f);
array_data[element] = value;
element += 1;
++i;
}
while (i < data_type->get_num_values()) {
array_data[element] = 0;
element += 1;
++i;
}
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
if (num_values == 4) {
*(PN_uint32 *)&array_data[element] = pack_argb(data);
} else {
// Elevate (or truncate) to 4 components.
float data4[4];
memset(data4, 0, 4 * sizeof(float));
memcpy(data4, data, min(4, num_values) * sizeof(float));
*(PN_uint32 *)&array_data[element] = pack_argb(data4);
}
}
break;
case qpGeomVertexDataType::NT_float32:
if (num_values == 4 && sizeof(float) == sizeof(PN_float32)) {
// The easy way: we can memcpy the data directly in.
memcpy(&array_data[element], data, data_type->get_total_bytes());
} else {
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_float32 *)&array_data[element] = data[i];
element += sizeof(PN_float32);
++i;
}
while (i < data_type->get_num_values()) {
if (i == 3 && data_type->get_num_values() == 4) {
*(PN_float32 *)&array_data[element] = 1.0f;
} else {
*(PN_float32 *)&array_data[element] = 0.0f;
}
element += sizeof(PN_float32);
++i;
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_data
// Access: Public
// Description: Returns the data associated with the nth vertex for a
// particular value. Query the format to get the array
// index and data_type parameters for the particular
// data type you want to get.
//
// This flavor of get_data() copies its data into a
// generic float array.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, float *data, int num_values) const {
CPTA_uchar array_data = get_array(array)->get_data();
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint16:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = *(PN_uint16 *)&array_data[element];
element += sizeof(PN_uint16);
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
case qpGeomVertexDataType::NT_uint8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
int value = *(unsigned char *)&array_data[element];
element += 1;
data[i] = (float)value / 255.0f;
++i;
}
while (i < num_values) {
data[i] = 0.0f;
++i;
}
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
if (num_values == 4) {
unpack_argb(data, *(PN_uint32 *)&array_data[element]);
} else {
float data4[4];
unpack_argb(data4, *(PN_uint32 *)&array_data[element]);
memset(data, 0, num_values * sizeof(float));
memcpy(data, data4, min(num_values, 4) * sizeof(float));
}
}
break;
case qpGeomVertexDataType::NT_float32:
if (num_values == data_type->get_num_values() &&
sizeof(float) == sizeof(PN_float32)) {
memcpy(data, &array_data[element], num_values * sizeof(PN_float32));
} else {
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = *(PN_float32 *)&array_data[element];
element += sizeof(PN_float32);
++i;
}
while (i < num_values) {
if (i == 3 && num_values == 4) {
data[i] = 1.0f;
} else {
data[i] = 0.0f;
}
++i;
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_data
// Access: Public
// Description: Sets the nth vertex to a particular value. Query the
// format to get the array index and data_type
// parameters for the particular data type you want to
// set.
//
// This flavor of set_data() accepts a generic float
// array and a specific number of dimensions. The new
// data will be copied from the num_values elements
// of data.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const int *data, int num_values) {
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
{
CDReader cdata(_cycler);
int array_size = (int)cdata->_arrays[array]->get_data_size_bytes();
if (element + data_type->get_total_bytes() > array_size) {
// Whoops, we need more vertices!
CDWriter cdataw(_cycler, cdata);
do_set_num_vertices(vertex + 1, cdataw);
}
}
PTA_uchar array_data = modify_array(array)->modify_data();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint16:
{
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_uint16 *)&array_data[element] = data[i];
element += sizeof(PN_uint16);
++i;
}
while (i < data_type->get_num_values()) {
*(PN_uint16 *)&array_data[element] = 0;
element += sizeof(PN_uint16);
++i;
}
}
break;
case qpGeomVertexDataType::NT_uint8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
array_data[element] = data[i];
element += 1;
++i;
}
while (i < data_type->get_num_values()) {
array_data[element] = 0;
element += 1;
++i;
}
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
if (num_values == 4) {
*(PN_uint32 *)&array_data[element] = pack_argb(data);
} else {
// Elevate (or truncate) to 4 components.
int data4[4];
memset(data4, 0, 4 * sizeof(int));
memcpy(data4, data, min(4, num_values) * sizeof(int));
*(PN_uint32 *)&array_data[element] = pack_argb(data4);
}
}
break;
case qpGeomVertexDataType::NT_float32:
{
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_float32 *)&array_data[element] = data[i];
element += sizeof(PN_float32);
++i;
}
while (i < data_type->get_num_values()) {
*(PN_float32 *)&array_data[element] = 0.0f;
element += sizeof(PN_float32);
++i;
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_data
// Access: Public
// Description: Returns the data associated with the nth vertex for a
// particular value. Query the format to get the array
// index and data_type parameters for the particular
// data type you want to get.
//
// This flavor of get_data() copies its data into a
// generic float array.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, int *data, int num_values) const {
CPTA_uchar array_data = get_array(array)->get_data();
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint16:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = *(PN_uint16 *)&array_data[element];
element += sizeof(PN_uint16);
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
case qpGeomVertexDataType::NT_uint8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
int value = *(unsigned char *)&array_data[element];
element += 1;
data[i] = value;
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
if (num_values == 4) {
unpack_argb(data, *(PN_uint32 *)&array_data[element]);
} else {
int data4[4];
unpack_argb(data4, *(PN_uint32 *)&array_data[element]);
memset(data, 0, num_values * sizeof(int));
memcpy(data, data4, min(num_values, 4) * sizeof(int));
}
}
break;
case qpGeomVertexDataType::NT_float32:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = (int)*(PN_float32 *)&array_data[element];
element += sizeof(PN_float32);
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_array_info
// Access: Public
@ -1015,142 +630,6 @@ get_array_info(const InternalName *name,
return false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::to_vec2
// Access: Public, Static
// Description: Converts a data element of arbitrary number of
// dimensions (1 - 4) into a vec2 in a sensible way.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
to_vec2(LVecBase2f &vec, const float *data, int num_values) {
switch (num_values) {
case 1:
vec.set(data[0], 0.0f);
break;
case 2:
case 3:
vec.set(data[0], data[1]);
break;
default: // 4 or more.
vec.set(data[0] / data[3], data[1] / data[3]);
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::to_vec3
// Access: Public, Static
// Description: Converts a data element of arbitrary number of
// dimensions (1 - 4) into a vec3 in a sensible way.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
to_vec3(LVecBase3f &vec, const float *data, int num_values) {
switch (num_values) {
case 1:
vec.set(data[0], 0.0f, 0.0f);
break;
case 2:
vec.set(data[0], data[1], 0.0f);
break;
case 3:
vec.set(data[0], data[1], data[2]);
break;
default: // 4 or more.
vec.set(data[0] / data[3], data[1] / data[3], data[2] / data[3]);
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::to_vec4
// Access: Public, Static
// Description: Converts a data element of arbitrary number of
// dimensions (1 - 4) into a vec4 in a sensible way.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
to_vec4(LVecBase4f &vec, const float *data, int num_values) {
switch (num_values) {
case 1:
vec.set(data[0], 0.0f, 0.0f, 1.0f);
break;
case 2:
vec.set(data[0], data[1], 0.0f, 1.0f);
break;
case 3:
vec.set(data[0], data[1], data[2], 1.0f);
break;
default: // 4 or more.
vec.set(data[0], data[1], data[2], data[3]);
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::pack_argb
// Access: Public, Static
// Description: Packs four floats, stored R, G, B, A, into a
// packed_argb value.
////////////////////////////////////////////////////////////////////
unsigned int qpGeomVertexData::
pack_argb(const float data[4]) {
unsigned int r = ((unsigned int)(data[0] * 255.0f)) & 0xff;
unsigned int g = ((unsigned int)(data[1] * 255.0f)) & 0xff;
unsigned int b = ((unsigned int)(data[2] * 255.0f)) & 0xff;
unsigned int a = ((unsigned int)(data[3] * 255.0f)) & 0xff;
return ((a << 24) | (r << 16) | (g << 8) | b);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::unpack_argb
// Access: Public, Static
// Description: Unpacks a packed_argb value into four floats, stored
// R, G, B, A.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
unpack_argb(float data[4], unsigned int packed_argb) {
data[0] = (float)((packed_argb >> 16) & 0xff) / 255.0f;
data[1] = (float)((packed_argb >> 8) & 0xff) / 255.0f;
data[2] = (float)(packed_argb & 0xff) / 255.0f;
data[3] = (float)((packed_argb >> 24) & 0xff) / 255.0f;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::pack_argb
// Access: Public, Static
// Description: Packs four ints, stored R, G, B, A, into a
// packed_argb value.
////////////////////////////////////////////////////////////////////
unsigned int qpGeomVertexData::
pack_argb(const int data[4]) {
unsigned int r = ((unsigned int)data[0]) & 0xff;
unsigned int g = ((unsigned int)data[1]) & 0xff;
unsigned int b = ((unsigned int)data[2]) & 0xff;
unsigned int a = ((unsigned int)data[3]) & 0xff;
return ((a << 24) | (r << 16) | (g << 8) | b);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::unpack_argb
// Access: Public, Static
// Description: Unpacks a packed_argb value into four ints, stored
// R, G, B, A.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
unpack_argb(int data[4], unsigned int packed_argb) {
data[0] = (int)((packed_argb >> 16) & 0xff);
data[1] = (int)((packed_argb >> 8) & 0xff);
data[2] = (int)(packed_argb & 0xff);
data[3] = (int)((packed_argb >> 24) & 0xff);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::do_set_num_vertices
// Access: Private
@ -1234,7 +713,7 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata) {
// Now go through and apply the scale, copying it to the new data.
qpGeomVertexReader from(this, InternalName::get_vertex());
qpGeomVertexReader blendi(this, InternalName::get_transform_blend());
qpGeomVertexIterator to(new_data, InternalName::get_vertex());
qpGeomVertexWriter to(new_data, InternalName::get_vertex());
if (from.get_data_type()->get_num_values() == 4) {
for (int i = 0; i < num_vertices; i++) {

View File

@ -117,30 +117,12 @@ PUBLISHED:
void write(ostream &out, int indent_level = 0) const;
public:
void set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const float *data, int num_values);
void get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, float *data, int num_values) const;
void set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const int *data, int num_values);
void get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, int *data, int num_values) const;
bool get_array_info(const InternalName *name,
const qpGeomVertexArrayData *&array_data,
int &num_components,
qpGeomVertexDataType::NumericType &numeric_type,
int &start, int &stride) const;
static void to_vec2(LVecBase2f &vec, const float *data, int num_values);
static void to_vec3(LVecBase3f &vec, const float *data, int num_values);
static void to_vec4(LVecBase4f &vec, const float *data, int num_values);
static unsigned int pack_argb(const float data[4]);
static void unpack_argb(float data[4], unsigned int packed_argb);
static unsigned int pack_argb(const int data[4]);
static void unpack_argb(int data[4], unsigned int packed_argb);
private:
string _name;
CPT(qpGeomVertexFormat) _format;

View File

@ -1,473 +0,0 @@
// Filename: qpgeomVertexIterator.I
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(qpGeomVertexData *data) :
_data(data),
_const_data(false),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object. This flavor creates the
// iterator specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(qpGeomVertexData *data, const string &name) :
_data(data),
_const_data(false),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object. This flavor creates the
// iterator specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(qpGeomVertexData *data, const InternalName *name) :
_data(data),
_const_data(false),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(const qpGeomVertexData *data) :
_data((qpGeomVertexData *)data),
_const_data(true),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object. This flavor creates the
// iterator specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(const qpGeomVertexData *data, const string &name) :
_data((qpGeomVertexData *)data),
_const_data(true),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object. This flavor creates the
// iterator specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(const qpGeomVertexData *data, const InternalName *name) :
_data((qpGeomVertexData *)data),
_const_data(true),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data
// Access: Published
// Description: Returns the current data object that the iterator is
// processing.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexData *qpGeomVertexIterator::
get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the nth data type of the
// GeomVertexFormat, numbering from 0.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(int data_type) {
nassertv(_data->get_format()->get_array_with(data_type) >= 0);
set_data_type(_data->get_format()->get_array_with(data_type),
_data->get_format()->get_data_type(data_type));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the data type with the
// indicated name.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(const string &name) {
set_data_type(InternalName::make(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the data type with the
// indicated name.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(const InternalName *name) {
nassertv(_data->get_format()->get_array_with(name) >= 0);
set_data_type(_data->get_format()->get_array_with(name),
_data->get_format()->get_data_type(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the indicated data_type
// description on the given array.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(int array, const qpGeomVertexDataType *data_type) {
nassertv(array >= 0 && array < _data->get_num_arrays());
nassertv(data_type != (qpGeomVertexDataType *)NULL);
_array = array;
_data_type = data_type;
_read_vertex = _start_vertex;
_write_vertex = _start_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_array
// Access: Published
// Description: Returns the array index containing the data type that
// the iterator is working on.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_array() const {
return _array;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data_type
// Access: Published
// Description: Returns the description of the data type that the
// iterator is working on.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexDataType *qpGeomVertexIterator::
get_data_type() const {
return _data_type;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_vertex
// Access: Published
// Description: Sets the start, read, and write index to the
// indicated value. The iterator will begin traversing
// from the given vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_vertex(int vertex) {
_start_vertex = vertex;
_read_vertex = vertex;
_write_vertex = vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_start_vertex
// Access: Published
// Description: Returns the vertex index at which the iterator
// started. It will return to this vertex if you reset
// the current data_type.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_start_vertex() const {
return _start_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_read_vertex
// Access: Published
// Description: Returns the current read vertex index of the
// iterator. This is the index whose value will be
// returned by the next call to get_vertex().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_read_vertex() const {
return _read_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_write_vertex
// Access: Published
// Description: Returns the current write vertex index of the
// iterator. This is the index whose value will be
// modified by the next call to set_vertex().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_write_vertex() const {
return _write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data1f
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data1f(float data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, &data, 1);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data2f(float x, float y) {
set_data2f(LVecBase2f(x, y));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data2f(const LVecBase2f &data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 2);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data3f(float x, float y, float z) {
set_data3f(LVecBase3f(x, y, z));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data3f(const LVecBase3f &data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 3);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data4f(float x, float y, float z, float w) {
set_data4f(LVecBase4f(x, y, z, w));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data4f(const LVecBase4f &data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 4);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data1f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 1-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE float qpGeomVertexIterator::
get_data1f() {
float data;
_data->get_data(_array, _data_type, _read_vertex, &data, 1);
++_read_vertex;
return data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data2f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 2-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase2f qpGeomVertexIterator::
get_data2f() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
++_read_vertex;
LVecBase2f result;
qpGeomVertexData::to_vec2(result, data, num_values);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data3f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 3-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase3f qpGeomVertexIterator::
get_data3f() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
++_read_vertex;
LVecBase3f result;
qpGeomVertexData::to_vec3(result, data, num_values);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data4f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 4-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase4f qpGeomVertexIterator::
get_data4f() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
++_read_vertex;
LVecBase4f result;
qpGeomVertexData::to_vec4(result, data, num_values);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data1i
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data1i(int data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, &data, 1);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data1i
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 1-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_data1i() {
int data;
_data->get_data(_array, _data_type, _read_vertex, &data, 1);
++_read_vertex;
return data;
}

View File

@ -1,19 +0,0 @@
// Filename: qpgeomVertexIterator.cxx
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexIterator.h"

View File

@ -1,99 +0,0 @@
// Filename: qpgeomVertexIterator.h
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXITERATOR_H
#define qpGEOMVERTEXITERATOR_H
#include "pandabase.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexDataType.h"
#include "internalName.h"
#include "luse.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexIterator
// Description : This is used to read or write the vertices of a
// GeomVertexData structure, one vertex and data type at
// a time.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexIterator {
PUBLISHED:
INLINE qpGeomVertexIterator(qpGeomVertexData *data);
INLINE qpGeomVertexIterator(qpGeomVertexData *data,
const string &name);
INLINE qpGeomVertexIterator(qpGeomVertexData *data,
const InternalName *name);
public:
// These const variants are not published, since our Python layer
// doesn't know the difference between const and non-const anyway.
INLINE qpGeomVertexIterator(const qpGeomVertexData *data);
INLINE qpGeomVertexIterator(const qpGeomVertexData *data,
const string &name);
INLINE qpGeomVertexIterator(const qpGeomVertexData *data,
const InternalName *name);
PUBLISHED:
INLINE const qpGeomVertexData *get_data() const;
INLINE void set_data_type(int data_type);
INLINE void set_data_type(const string &name);
INLINE void set_data_type(const InternalName *name);
INLINE void set_data_type(int array, const qpGeomVertexDataType *data_type);
INLINE int get_array() const;
INLINE const qpGeomVertexDataType *get_data_type() const;
INLINE void set_vertex(int vertex);
INLINE int get_start_vertex() const;
INLINE int get_read_vertex() const;
INLINE int get_write_vertex() const;
INLINE void set_data1f(float data);
INLINE void set_data2f(float x, float y);
INLINE void set_data2f(const LVecBase2f &data);
INLINE void set_data3f(float x, float y, float z);
INLINE void set_data3f(const LVecBase3f &data);
INLINE void set_data4f(float x, float y, float z, float w);
INLINE void set_data4f(const LVecBase4f &data);
INLINE float get_data1f();
INLINE LVecBase2f get_data2f();
INLINE LVecBase3f get_data3f();
INLINE LVecBase4f get_data4f();
INLINE void set_data1i(int data);
INLINE int get_data1i();
private:
PT(qpGeomVertexData) _data;
bool _const_data;
int _array;
const qpGeomVertexDataType *_data_type;
int _start_vertex;
int _read_vertex;
int _write_vertex;
};
#include "qpgeomVertexIterator.I"
#endif

View File

@ -31,6 +31,7 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data) :
_pointer(NULL),
_start_vertex(0),
_read_vertex(0),
_num_vertices(0),
_reader(NULL)
{
}
@ -50,6 +51,7 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data, const string &name) :
_pointer(NULL),
_start_vertex(0),
_read_vertex(0),
_num_vertices(0),
_reader(NULL)
{
set_data_type(name);
@ -71,6 +73,7 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data,
_pointer(NULL),
_start_vertex(0),
_read_vertex(0),
_num_vertices(0),
_reader(NULL)
{
set_data_type(name);
@ -109,12 +112,14 @@ get_vertex_data() const {
// This also resets the read vertex number to the start
// vertex (the same value passed to a previous call to
// set_vertex(), or 0 if set_vertex() was never called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexReader::
INLINE bool qpGeomVertexReader::
set_data_type(int data_type) {
nassertv(_vertex_data->get_format()->get_array_with(data_type) >= 0);
set_data_type(_vertex_data->get_format()->get_array_with(data_type),
_vertex_data->get_format()->get_data_type(data_type));
return set_data_type(_vertex_data->get_format()->get_array_with(data_type),
_vertex_data->get_format()->get_data_type(data_type));
}
////////////////////////////////////////////////////////////////////
@ -126,10 +131,13 @@ set_data_type(int data_type) {
// This also resets the read vertex number to the start
// vertex (the same value passed to a previous call to
// set_vertex(), or 0 if set_vertex() was never called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexReader::
INLINE bool qpGeomVertexReader::
set_data_type(const string &name) {
set_data_type(InternalName::make(name));
return set_data_type(InternalName::make(name));
}
////////////////////////////////////////////////////////////////////
@ -141,12 +149,26 @@ set_data_type(const string &name) {
// This also resets the read vertex number to the start
// vertex (the same value passed to a previous call to
// set_vertex(), or 0 if set_vertex() was never called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexReader::
INLINE bool qpGeomVertexReader::
set_data_type(const InternalName *name) {
nassertv(_vertex_data->get_format()->get_array_with(name) >= 0);
set_data_type(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_data_type(name));
return set_data_type(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_data_type(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::has_data_type
// Access: Published
// Description: Returns true if a valid data type has been
// successfully set, or false if the data type does not
// exist.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexReader::
has_data_type() const {
return (_data_type != (qpGeomVertexDataType *)NULL);
}
////////////////////////////////////////////////////////////////////
@ -181,8 +203,9 @@ get_data_type() const {
INLINE void qpGeomVertexReader::
set_vertex(int vertex) {
_start_vertex = vertex;
_read_vertex = vertex;
set_pointer();
if (_data_type != (qpGeomVertexDataType *)NULL) {
set_pointer(_start_vertex);
}
}
////////////////////////////////////////////////////////////////////
@ -209,6 +232,29 @@ get_read_vertex() const {
return _read_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::get_num_vertices
// Access: Published
// Description: Returns the number of vertices in the vertex data.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexReader::
get_num_vertices() const {
return _num_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::is_at_end
// Access: Published
// Description: Returns true if the reader is currently at the end of
// the list of vertices, false otherwise. If this is
// true, another call to get_data*() will result in a
// crash.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexReader::
is_at_end() const {
return _read_vertex >= _num_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::get_data1f
// Access: Published
@ -218,6 +264,7 @@ get_read_vertex() const {
////////////////////////////////////////////////////////////////////
INLINE float qpGeomVertexReader::
get_data1f() {
nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0.0f);
return _reader->get_data1f(inc_pointer());
}
@ -230,6 +277,7 @@ get_data1f() {
////////////////////////////////////////////////////////////////////
INLINE const LVecBase2f &qpGeomVertexReader::
get_data2f() {
nassertr(_data_type != (qpGeomVertexDataType *)NULL, LVecBase2f::zero());
return _reader->get_data2f(inc_pointer());
}
@ -242,6 +290,7 @@ get_data2f() {
////////////////////////////////////////////////////////////////////
INLINE const LVecBase3f &qpGeomVertexReader::
get_data3f() {
nassertr(_data_type != (qpGeomVertexDataType *)NULL, LVecBase3f::zero());
return _reader->get_data3f(inc_pointer());
}
@ -254,6 +303,7 @@ get_data3f() {
////////////////////////////////////////////////////////////////////
INLINE const LVecBase4f &qpGeomVertexReader::
get_data4f() {
nassertr(_data_type != (qpGeomVertexDataType *)NULL, LVecBase4f::zero());
return _reader->get_data4f(inc_pointer());
}
@ -266,20 +316,24 @@ get_data4f() {
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexReader::
get_data1i() {
nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0);
return _reader->get_data1i(inc_pointer());
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::set_pointer
// Access: Private
// Description: Sets up the internal pointer, etc. to use the vertex
// indicated by _start_vertex.
// Description: Sets up the internal write pointer, etc. to use the
// indicated vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexReader::
set_pointer() {
_read_vertex = _start_vertex;
_data = _vertex_data->get_array(_array)->get_data();
set_pointer(int vertex) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_read_vertex = vertex;
CPT(qpGeomVertexArrayData) array_data = _vertex_data->get_array(_array);
_data = array_data->get_data();
_pointer = _data.p() + _data_type->get_start() + _stride * _read_vertex;
_num_vertices = array_data->get_num_vertices();
}
////////////////////////////////////////////////////////////////////
@ -290,6 +344,9 @@ set_pointer() {
////////////////////////////////////////////////////////////////////
INLINE const unsigned char *qpGeomVertexReader::
inc_pointer() {
nassertr(_read_vertex < _num_vertices, NULL);
nassertr(_pointer == _vertex_data->get_array(_array)->get_data().p() + _data_type->get_start() + _stride * _read_vertex, NULL);
const unsigned char *orig_pointer = _pointer;
_pointer += _stride;
++_read_vertex;

View File

@ -28,26 +28,42 @@
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
void qpGeomVertexReader::
bool qpGeomVertexReader::
set_data_type(int array, const qpGeomVertexDataType *data_type) {
nassertv(array >= 0 && array < _vertex_data->get_num_arrays());
nassertv(data_type != (qpGeomVertexDataType *)NULL);
_array = array;
_data_type = data_type;
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
set_pointer();
// Delete the old reader, if we've got one.
if (_reader != (Reader *)NULL) {
delete _reader;
_reader = NULL;
}
// Now set up a new reader.
_reader = make_reader();
_reader->_data_type = _data_type;
if (array < 0 || array >= _vertex_data->get_num_arrays() ||
data_type == (qpGeomVertexDataType *)NULL) {
// Clear the data type.
_array = -1;
_data_type = NULL;
_stride = 0;
_read_vertex = _start_vertex;
_num_vertices = 0;
return false;
} else {
_array = array;
_data_type = data_type;
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
set_pointer(_start_vertex);
// Now set up a new reader.
_reader = make_reader();
_reader->_data_type = _data_type;
return true;
}
}
////////////////////////////////////////////////////////////////////
@ -58,40 +74,109 @@ set_data_type(int array, const qpGeomVertexDataType *data_type) {
////////////////////////////////////////////////////////////////////
qpGeomVertexReader::Reader *qpGeomVertexReader::
make_reader() const {
if (_data_type->get_contents() == qpGeomVertexDataType::C_point &&
_data_type->get_num_values() < 4) {
return new Reader_point;
} else {
switch (_data_type->get_contents()) {
case qpGeomVertexDataType::C_point:
case qpGeomVertexDataType::C_texcoord:
// These types are read as a 4-d homogeneous point.
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_float32:
if (sizeof(float) == 4) {
if (sizeof(float) == sizeof(PN_float32)) {
// Use the native float type implementation for a tiny bit
// more optimization.
switch (_data_type->get_num_components()) {
case 2:
return new Reader_point_nativefloat_2;
case 3:
return new Reader_float_3;
default:
break;
return new Reader_point_nativefloat_3;
case 4:
return new Reader_point_nativefloat_4;
}
} else {
switch (_data_type->get_num_components()) {
case 2:
return new Reader_point_float32_2;
case 3:
return new Reader_point_float32_3;
case 4:
return new Reader_point_float32_4;
}
}
break;
default:
break;
}
return new Reader_point;
case qpGeomVertexDataType::NT_uint16:
case qpGeomVertexDataType::C_rgba:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
switch (_data_type->get_num_components()) {
case 1:
return new Reader_uint16_1;
case 4:
return new Reader_rgba_uint8_4;
default:
break;
}
break;
case qpGeomVertexDataType::NT_float32:
switch (_data_type->get_num_components()) {
case 4:
if (sizeof(float) == sizeof(PN_float32)) {
// Use the native float type implementation for a tiny bit
// more optimization.
return new Reader_rgba_nativefloat_4;
} else {
return new Reader_rgba_float32_4;
}
default:
break;
}
break;
default:
break;
}
}
return new Reader_color;
// If we got here, we have to create a generic reader.
return new Reader;
case qpGeomVertexDataType::C_argb:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_packed_8888:
switch (_data_type->get_num_components()) {
case 1:
return new Reader_argb_packed_8888;
default:
break;
}
break;
default:
break;
}
return new Reader_color;
default:
// Otherwise, we just read it as a generic value.
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_float32:
switch (_data_type->get_num_components()) {
case 3:
if (sizeof(float) == sizeof(PN_float32)) {
// Use the native float type implementation for a tiny bit
// more optimization.
return new Reader_nativefloat_3;
} else {
return new Reader_float32_3;
}
default:
break;
}
break;
default:
break;
}
return new Reader;
}
}
////////////////////////////////////////////////////////////////////
@ -121,7 +206,11 @@ get_data1f(const unsigned char *pointer) {
{
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
return maybe_scale_color(dword._b[0]);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
return maybe_scale_color(dword._b[1]);
} else {
return maybe_scale_color(dword._b[0]);
}
}
case qpGeomVertexDataType::NT_float32:
@ -159,7 +248,11 @@ get_data2f(const unsigned char *pointer) {
{
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
maybe_scale_color(dword._b[0], dword._b[1]);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
maybe_scale_color(dword._b[1], dword._b[2]);
} else {
maybe_scale_color(dword._b[0], dword._b[1]);
}
}
return _v2;
@ -184,7 +277,7 @@ const LVecBase3f &qpGeomVertexReader::Reader::
get_data3f(const unsigned char *pointer) {
switch (_data_type->get_num_values()) {
case 1:
_v3.set(get_data1i(pointer), 0.0f, 0.0f);
_v3.set(get_data1f(pointer), 0.0f, 0.0f);
return _v3;
case 2:
@ -211,7 +304,11 @@ get_data3f(const unsigned char *pointer) {
{
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2]);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
maybe_scale_color(dword._b[1], dword._b[2], dword._b[3]);
} else {
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2]);
}
}
return _v3;
@ -270,7 +367,11 @@ get_data4f(const unsigned char *pointer) {
{
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
maybe_scale_color(dword._b[1], dword._b[2], dword._b[3], dword._b[0]);
} else {
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
}
}
return _v4;
@ -315,6 +416,53 @@ get_data1i(const unsigned char *pointer) {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point::get_data1f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
float qpGeomVertexReader::Reader_point::
get_data1f(const unsigned char *pointer) {
if (_data_type->get_num_values() == 4) {
const LVecBase4f &v4 = get_data4f(pointer);
return v4[0] / v4[3];
} else {
return Reader::get_data1f(pointer);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point::get_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase2f &qpGeomVertexReader::Reader_point::
get_data2f(const unsigned char *pointer) {
if (_data_type->get_num_values() == 4) {
const LVecBase4f &v4 = get_data4f(pointer);
_v2.set(v4[0] / v4[3], v4[1] / v4[3]);
return _v2;
} else {
return Reader::get_data2f(pointer);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point::get_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase3f &qpGeomVertexReader::Reader_point::
get_data3f(const unsigned char *pointer) {
if (_data_type->get_num_values() == 4) {
const LVecBase4f &v4 = get_data4f(pointer);
_v3.set(v4[0] / v4[3], v4[1] / v4[3], v4[2] / v4[3]);
return _v3;
} else {
return Reader::get_data3f(pointer);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point::get_data4f
// Access: Public, Virtual
@ -358,7 +506,11 @@ get_data4f(const unsigned char *pointer) {
{
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
maybe_scale_color(dword._b[1], dword._b[2], dword._b[3], dword._b[0]);
} else {
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
}
}
return _v4;
@ -375,16 +527,206 @@ get_data4f(const unsigned char *pointer) {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_float_3::get_data3f
// Function: qpGeomVertexReader::Reader_color::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase3f &qpGeomVertexReader::Reader_float_3::
const LVecBase4f &qpGeomVertexReader::Reader_color::
get_data4f(const unsigned char *pointer) {
switch (_data_type->get_num_values()) {
case 1:
_v4.set(get_data1i(pointer), 0.0f, 0.0f, 1.0f);
return _v4;
case 2:
{
const LVecBase2f &v2 = get_data2f(pointer);
_v4.set(v2[0], v2[1], 0.0f, 1.0f);
}
return _v4;
case 3:
{
const LVecBase3f &v3 = get_data3f(pointer);
_v4.set(v3[0], v3[1], v3[2], 1.0f);
}
return _v4;
default:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
return _v4;
case qpGeomVertexDataType::NT_uint16:
{
PN_uint16 *pi = (PN_uint16 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
}
return _v4;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
maybe_scale_color(dword._b[1], dword._b[2], dword._b[3], dword._b[0]);
} else {
maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
}
}
return _v4;
case qpGeomVertexDataType::NT_float32:
{
PN_float32 *pi = (PN_float32 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
}
return _v4;
}
}
return _v4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_float32_3::get_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase3f &qpGeomVertexReader::Reader_float32_3::
get_data3f(const unsigned char *pointer) {
// We sneakily cast a float[3] array to an LVecBase3f reference,
// making all kinds of assumptions about how an LVecBase3f is
// stored.
return *(LVecBase3f *)pointer;
PN_float32 *pi = (PN_float32 *)pointer;
_v3.set(pi[0], pi[1], pi[2]);
return _v3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point_float32_2::get_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase2f &qpGeomVertexReader::Reader_point_float32_2::
get_data2f(const unsigned char *pointer) {
PN_float32 *pi = (PN_float32 *)pointer;
_v2.set(pi[0], pi[1]);
return _v2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point_float32_3::get_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase3f &qpGeomVertexReader::Reader_point_float32_3::
get_data3f(const unsigned char *pointer) {
PN_float32 *pi = (PN_float32 *)pointer;
_v3.set(pi[0], pi[1], pi[2]);
return _v3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point_float32_4::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase4f &qpGeomVertexReader::Reader_point_float32_4::
get_data4f(const unsigned char *pointer) {
PN_float32 *pi = (PN_float32 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
return _v4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_nativefloat_3::get_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase3f &qpGeomVertexReader::Reader_nativefloat_3::
get_data3f(const unsigned char *pointer) {
return *(const LVecBase3f *)pointer;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point_nativefloat_2::get_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase2f &qpGeomVertexReader::Reader_point_nativefloat_2::
get_data2f(const unsigned char *pointer) {
return *(const LVecBase2f *)pointer;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point_nativefloat_3::get_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase3f &qpGeomVertexReader::Reader_point_nativefloat_3::
get_data3f(const unsigned char *pointer) {
return *(const LVecBase3f *)pointer;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_point_nativefloat_4::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase4f &qpGeomVertexReader::Reader_point_nativefloat_4::
get_data4f(const unsigned char *pointer) {
return *(const LVecBase4f *)pointer;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_argb_packed_8888::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase4f &qpGeomVertexReader::Reader_argb_packed_8888::
get_data4f(const unsigned char *pointer) {
packed_8888 dword;
dword._i = *(PN_uint32 *)pointer;
_v4.set((float)dword._b[1] / 255.0f,
(float)dword._b[2] / 255.0f,
(float)dword._b[3] / 255.0f,
(float)dword._b[0] / 255.0f);
return _v4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_rgba_uint8_4::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase4f &qpGeomVertexReader::Reader_rgba_uint8_4::
get_data4f(const unsigned char *pointer) {
_v4.set((float)pointer[0] / 255.0f,
(float)pointer[1] / 255.0f,
(float)pointer[2] / 255.0f,
(float)pointer[3] / 255.0f);
return _v4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_rgba_float32_4::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase4f &qpGeomVertexReader::Reader_rgba_float32_4::
get_data4f(const unsigned char *pointer) {
PN_float32 *pi = (PN_float32 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
return _v4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Reader_rgba_nativefloat_4::get_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
const LVecBase4f &qpGeomVertexReader::Reader_rgba_nativefloat_4::
get_data4f(const unsigned char *pointer) {
return *(const LVecBase4f *)pointer;
}
////////////////////////////////////////////////////////////////////

View File

@ -53,11 +53,12 @@ PUBLISHED:
INLINE const qpGeomVertexData *get_vertex_data() const;
INLINE void set_data_type(int data_type);
INLINE void set_data_type(const string &name);
INLINE void set_data_type(const InternalName *name);
void set_data_type(int array, const qpGeomVertexDataType *data_type);
INLINE bool set_data_type(int data_type);
INLINE bool set_data_type(const string &name);
INLINE bool set_data_type(const InternalName *name);
bool set_data_type(int array, const qpGeomVertexDataType *data_type);
INLINE bool has_data_type() const;
INLINE int get_array() const;
INLINE const qpGeomVertexDataType *get_data_type() const;
@ -65,6 +66,8 @@ PUBLISHED:
INLINE int get_start_vertex() const;
INLINE int get_read_vertex() const;
INLINE int get_num_vertices() const;
INLINE bool is_at_end() const;
INLINE float get_data1f();
INLINE const LVecBase2f &get_data2f();
@ -76,7 +79,7 @@ PUBLISHED:
private:
class Reader;
INLINE void set_pointer();
INLINE void set_pointer(int vertex);
INLINE const unsigned char *inc_pointer();
Reader *make_reader() const;
@ -90,6 +93,7 @@ private:
int _start_vertex;
int _read_vertex;
int _num_vertices;
Reader *_reader;
@ -126,9 +130,22 @@ private:
};
// This is a specialization on the generic Reader that handles
// points, which are special because the fourth component, if
// omitted, is 1.0.
// points, which are special because the fourth component, if not
// present in the data, is implicitly 1.0; and if it is present,
// than any three-component or smaller return is implicitly divided
// by the fourth component.
class Reader_point : public Reader {
public:
virtual float get_data1f(const unsigned char *pointer);
virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
// This is similar to Reader_point, in that the fourth component is
// implicitly 1.0 if it is not present in the data, but we never
// divide by alpha.
class Reader_color : public Reader {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
@ -137,11 +154,66 @@ private:
// These are the specializations on the generic Reader that handle
// the direct code paths.
class Reader_float_3 : public Reader {
class Reader_float32_3 : public Reader {
public:
virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
};
class Reader_point_float32_2 : public Reader_point {
public:
virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
};
class Reader_point_float32_3 : public Reader_point {
public:
virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
};
class Reader_point_float32_4 : public Reader_point {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
class Reader_nativefloat_3 : public Reader {
public:
virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
};
class Reader_point_nativefloat_2 : public Reader_point {
public:
virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
};
class Reader_point_nativefloat_3 : public Reader_point {
public:
virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
};
class Reader_point_nativefloat_4 : public Reader_point {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
class Reader_argb_packed_8888 : public Reader_color {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
class Reader_rgba_uint8_4 : public Reader_color {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
class Reader_rgba_float32_4 : public Reader_color {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
class Reader_rgba_nativefloat_4 : public Reader_color {
public:
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
};
class Reader_uint16_1 : public Reader {
public:
virtual int get_data1i(const unsigned char *pointer);

View File

@ -0,0 +1,636 @@
// Filename: qpgeomVertexWriter.I
// Created by: drose (25Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Constructor
// Access: Published
// Description: Constructs a new writer to process the vertices of
// the indicated data object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexData *vertex_data) :
_vertex_data(vertex_data),
_array(0),
_data_type(NULL),
_pointer(NULL),
_start_vertex(0),
_write_vertex(0),
_num_vertices(0),
_writer(NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Constructor
// Access: Published
// Description: Constructs a new writer to process the vertices of
// the indicated data object. This flavor creates the
// writer specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexData *vertex_data, const string &name) :
_vertex_data(vertex_data),
_array(0),
_data_type(NULL),
_pointer(NULL),
_start_vertex(0),
_write_vertex(0),
_num_vertices(0),
_writer(NULL)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Constructor
// Access: Published
// Description: Constructs a new writer to process the vertices of
// the indicated data object. This flavor creates the
// writer specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexData *vertex_data, const InternalName *name) :
_vertex_data(vertex_data),
_array(0),
_data_type(NULL),
_pointer(NULL),
_start_vertex(0),
_write_vertex(0),
_num_vertices(0),
_writer(NULL)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
~qpGeomVertexWriter() {
if (_writer != (Writer *)NULL) {
delete _writer;
_writer = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_vertex_data
// Access: Published
// Description: Returns the vertex data object that the
// writer is processing.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexData *qpGeomVertexWriter::
get_vertex_data() const {
return _vertex_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data_type
// Access: Published
// Description: Sets up the writer to use the nth data type of the
// GeomVertexFormat, numbering from 0.
//
// This also resets the write vertex number to the start
// vertex (the same value passed to a previous call to
// set_vertex(), or 0 if set_vertex() was never called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
set_data_type(int data_type) {
return set_data_type(_vertex_data->get_format()->get_array_with(data_type),
_vertex_data->get_format()->get_data_type(data_type));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data_type
// Access: Published
// Description: Sets up the writer to use the data type with the
// indicated name.
//
// This also resets the write vertex number to the start
// vertex (the same value passed to a previous call to
// set_vertex(), or 0 if set_vertex() was never called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
set_data_type(const string &name) {
return set_data_type(InternalName::make(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data_type
// Access: Published
// Description: Sets up the writer to use the data type with the
// indicated name.
//
// This also resets the write number to the start vertex
// (the same value passed to a previous call to
// set_vertex(), or 0 if set_vertex() was never called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
set_data_type(const InternalName *name) {
return set_data_type(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_data_type(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::has_data_type
// Access: Published
// Description: Returns true if a valid data type has been
// successfully set, or false if the data type does not
// exist.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
has_data_type() const {
return (_data_type != (qpGeomVertexDataType *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_array
// Access: Published
// Description: Returns the array index containing the data type that
// the writer is working on.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexWriter::
get_array() const {
return _array;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_data_type
// Access: Published
// Description: Returns the description of the data type that the
// writer is working on.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexDataType *qpGeomVertexWriter::
get_data_type() const {
return _data_type;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_vertex
// Access: Published
// Description: Sets the start, write, and write index to the
// indicated value. The writer will begin traversing
// from the given vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_vertex(int vertex) {
_start_vertex = vertex;
if (_data_type != (qpGeomVertexDataType *)NULL) {
set_pointer(_start_vertex);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_start_vertex
// Access: Published
// Description: Returns the vertex index at which the writer
// started. It will return to this vertex if you reset
// the current data_type.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexWriter::
get_start_vertex() const {
return _start_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_write_vertex
// Access: Published
// Description: Returns the current write vertex index of the
// writer. This is the index whose value will be
// returned by the next call to get_data*().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexWriter::
get_write_vertex() const {
return _write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_num_vertices
// Access: Published
// Description: Returns the number of vertices in the vertex data.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexWriter::
get_num_vertices() const {
return _num_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::is_at_end
// Access: Published
// Description: Returns true if the writer is currently at the end of
// the list of vertices, false otherwise. If this is
// true, another call to set_data*() will result in a
// crash, but another call to add_data*() will add a new
// vertex.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
is_at_end() const {
return _write_vertex >= _num_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data1f
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data1f(float data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data1f(inc_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data2f(float x, float y) {
set_data2f(LVecBase2f(x, y));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data2f(const LVecBase2f &data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data2f(inc_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data3f(float x, float y, float z) {
set_data3f(LVecBase3f(x, y, z));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data3f(const LVecBase3f &data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data3f(inc_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data4f(float x, float y, float z, float w) {
set_data4f(LVecBase4f(x, y, z, w));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data4f(const LVecBase4f &data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data4f(inc_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data1i
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
//
// It is an error for the write vertex to advance past
// the end of data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_data1i(int data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data1i(inc_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data1f
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data1f(float data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data1f(inc_add_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data2f(float x, float y) {
add_data2f(LVecBase2f(x, y));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data2f(const LVecBase2f &data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data2f(inc_add_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data3f(float x, float y, float z) {
add_data3f(LVecBase3f(x, y, z));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data3f(const LVecBase3f &data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data3f(inc_add_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data4f(float x, float y, float z, float w) {
add_data4f(LVecBase4f(x, y, z, w));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data4f(const LVecBase4f &data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data4f(inc_add_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::add_data1i
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
//
// If the write vertex advances past the end of data,
// implicitly adds a new vertex to the data.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
add_data1i(int data) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_writer->set_data1i(inc_add_pointer(), data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_pointer
// Access: Private
// Description: Sets up the internal write pointer, etc. to use the
// indicated vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::
set_pointer(int vertex) {
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
_write_vertex = vertex;
PT(qpGeomVertexArrayData) array_data = _vertex_data->modify_array(_array);
_data = array_data->modify_data();
_pointer = _data.p() + _data_type->get_start() + _stride * _write_vertex;
_num_vertices = array_data->get_num_vertices();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::inc_pointer
// Access: Private
// Description: Increments to the next vertex, and returns the data
// pointer as it was before incrementing.
////////////////////////////////////////////////////////////////////
INLINE unsigned char *qpGeomVertexWriter::
inc_pointer() {
nassertr(_write_vertex < _num_vertices, NULL);
nassertr(_pointer == _vertex_data->get_array(_array)->get_data().p() + _data_type->get_start() + _stride * _write_vertex, NULL);
unsigned char *orig_pointer = _pointer;
_pointer += _stride;
++_write_vertex;
return orig_pointer;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::inc_add_pointer
// Access: Private
// Description: Increments to the next vertex, and returns the data
// pointer as it was before incrementing. If we are at
// or past the end of data, implicitly adds more
// vertices first.
////////////////////////////////////////////////////////////////////
INLINE unsigned char *qpGeomVertexWriter::
inc_add_pointer() {
if (_write_vertex >= _num_vertices) {
// Reset the data pointer.
_vertex_data->set_num_vertices(max(_write_vertex + 1, _vertex_data->get_num_vertices()));
set_pointer(_write_vertex);
}
return inc_pointer();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::maybe_scale_color
// Access: Public
// Description: Converts a floating-point value to a uint8 value. If
// the contents value indicates this is a color value,
// scales it into the range 0..255 per convention;
// otherwise leaves it alone.
////////////////////////////////////////////////////////////////////
INLINE unsigned int qpGeomVertexWriter::Writer::
maybe_scale_color(float data) {
switch (_data_type->get_contents()) {
case qpGeomVertexDataType::C_rgba:
case qpGeomVertexDataType::C_argb:
return (unsigned int)(data * 255.0f);
default:
return (unsigned int)data;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::maybe_scale_color
// Access: Public
// Description: Converts an LVecBase2f into a pair of uint8
// values. See one-parameter maybe_scale_color() for
// more info.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::Writer::
maybe_scale_color(const LVecBase2f &data) {
switch (_data_type->get_contents()) {
case qpGeomVertexDataType::C_rgba:
case qpGeomVertexDataType::C_argb:
_a = (unsigned int)(data[0] * 255.0f);
_b = (unsigned int)(data[1] * 255.0f);
break;
default:
_a = (unsigned int)data[0];
_b = (unsigned int)data[1];
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::maybe_scale_color
// Access: Public
// Description: Converts an LVecBase3f into a pair of uint8
// values. See one-parameter maybe_scale_color() for
// more info.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::Writer::
maybe_scale_color(const LVecBase3f &data) {
switch (_data_type->get_contents()) {
case qpGeomVertexDataType::C_rgba:
case qpGeomVertexDataType::C_argb:
_a = (unsigned int)(data[0] * 255.0f);
_b = (unsigned int)(data[1] * 255.0f);
_c = (unsigned int)(data[2] * 255.0f);
break;
default:
_a = (unsigned int)data[0];
_b = (unsigned int)data[1];
_c = (unsigned int)data[2];
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::maybe_scale_color
// Access: Public
// Description: Converts an LVecBase4f into a pair of uint8
// values. See one-parameter maybe_scale_color() for
// more info.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexWriter::Writer::
maybe_scale_color(const LVecBase4f &data) {
switch (_data_type->get_contents()) {
case qpGeomVertexDataType::C_rgba:
case qpGeomVertexDataType::C_argb:
_a = (unsigned int)(data[0] * 255.0f);
_b = (unsigned int)(data[1] * 255.0f);
_c = (unsigned int)(data[2] * 255.0f);
_d = (unsigned int)(data[3] * 255.0f);
break;
default:
_a = (unsigned int)data[0];
_b = (unsigned int)data[1];
_c = (unsigned int)data[2];
_d = (unsigned int)data[3];
break;
}
}

View File

@ -0,0 +1,721 @@
// Filename: qpgeomVertexWriter.cxx
// Created by: drose (25Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexWriter.h"
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_data_type
// Access: Published
// Description: Sets up the writer to use the indicated data_type
// description on the given array.
//
// This also resets the current write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
//
// The return value is true if the data type is valid,
// false otherwise.
////////////////////////////////////////////////////////////////////
bool qpGeomVertexWriter::
set_data_type(int array, const qpGeomVertexDataType *data_type) {
// Delete the old writer, if we've got one.
if (_writer != (Writer *)NULL) {
delete _writer;
_writer = NULL;
}
if (array < 0 || array >= _vertex_data->get_num_arrays() ||
data_type == (qpGeomVertexDataType *)NULL) {
// Clear the data type.
_array = -1;
_data_type = NULL;
_stride = 0;
_write_vertex = _start_vertex;
_num_vertices = 0;
return false;
} else {
_array = array;
_data_type = data_type;
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
set_pointer(_start_vertex);
// Now set up a new writer.
_writer = make_writer();
_writer->_data_type = _data_type;
return true;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::make_writer
// Access: Private
// Description: Returns a newly-allocated Writer object suitable for
// writing the current data type.
////////////////////////////////////////////////////////////////////
qpGeomVertexWriter::Writer *qpGeomVertexWriter::
make_writer() const {
switch (_data_type->get_contents()) {
case qpGeomVertexDataType::C_point:
case qpGeomVertexDataType::C_texcoord:
// These types are written as a 4-d homogeneous point.
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_float32:
switch (_data_type->get_num_components()) {
case 2:
return new Writer_point_float32_2;
case 3:
return new Writer_point_float32_3;
case 4:
return new Writer_point_float32_4;
default:
break;
}
break;
default:
break;
}
return new Writer_point;
case qpGeomVertexDataType::C_rgba:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
switch (_data_type->get_num_components()) {
case 4:
return new Writer_rgba_uint8_4;
default:
break;
}
break;
case qpGeomVertexDataType::NT_float32:
switch (_data_type->get_num_components()) {
case 4:
return new Writer_rgba_float32_4;
default:
break;
}
break;
default:
break;
}
return new Writer_color;
case qpGeomVertexDataType::C_argb:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_packed_8888:
switch (_data_type->get_num_components()) {
case 1:
return new Writer_argb_packed_8888;
default:
break;
}
break;
default:
break;
}
return new Writer_color;
default:
// Otherwise, we just write it as a generic value.
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_float32:
switch (_data_type->get_num_components()) {
case 3:
return new Writer_float32_3;
default:
break;
}
break;
default:
break;
}
return new Writer;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexWriter::Writer::
~Writer() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::set_data1f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer::
set_data1f(unsigned char *pointer, float data) {
switch (_data_type->get_num_values()) {
case 1:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
*pointer = maybe_scale_color(data);
break;
case qpGeomVertexDataType::NT_uint16:
*(PN_uint16 *)pointer = (unsigned int)data;
break;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
dword._i = 0;
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
dword._b[1] = maybe_scale_color(data);
} else {
dword._b[0] = maybe_scale_color(data);
}
*(PN_uint32 *)pointer = dword._i;
}
break;
case qpGeomVertexDataType::NT_float32:
*(PN_float32 *)pointer = data;
break;
}
break;
case 2:
set_data2f(pointer, LVecBase2f(data, 0.0f));
break;
case 3:
set_data3f(pointer, LVecBase3f(data, 0.0f, 0.0f));
break;
case 4:
set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 0.0f));
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::set_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer::
set_data2f(unsigned char *pointer, const LVecBase2f &data) {
switch (_data_type->get_num_values()) {
case 1:
set_data1f(pointer, data[0]);
case 2:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
maybe_scale_color(data);
pointer[0] = _a;
pointer[1] = _b;
break;
case qpGeomVertexDataType::NT_uint16:
{
PN_uint16 *pi = (PN_uint16 *)pointer;
pi[0] = (unsigned int)data[0];
pi[1] = (unsigned int)data[1];
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
maybe_scale_color(data);
dword._i = 0;
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
dword._b[1] = _a;
dword._b[2] = _b;
} else {
dword._b[0] = _a;
dword._b[1] = _b;
}
*(PN_uint32 *)pointer = dword._i;
}
break;
case qpGeomVertexDataType::NT_float32:
{
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
}
break;
}
break;
case 3:
set_data3f(pointer, LVecBase3f(data[0], data[1], 0.0f));
break;
default:
set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 0.0f));
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::set_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer::
set_data3f(unsigned char *pointer, const LVecBase3f &data) {
switch (_data_type->get_num_values()) {
case 1:
set_data1f(pointer, data[0]);
break;
case 2:
set_data2f(pointer, LVecBase2f(data[0], data[1]));
break;
case 3:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
maybe_scale_color(data);
pointer[0] = _a;
pointer[1] = _b;
pointer[2] = _c;
break;
case qpGeomVertexDataType::NT_uint16:
{
PN_uint16 *pi = (PN_uint16 *)pointer;
pi[0] = (unsigned int)data[0];
pi[1] = (unsigned int)data[1];
pi[2] = (unsigned int)data[2];
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
maybe_scale_color(data);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
dword._b[0] = 0;
dword._b[1] = _a;
dword._b[2] = _b;
dword._b[3] = _c;
} else {
dword._b[0] = _a;
dword._b[1] = _b;
dword._b[2] = _c;
dword._b[3] = 0;
}
*(PN_uint32 *)pointer = dword._i;
}
break;
case qpGeomVertexDataType::NT_float32:
{
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
}
break;
}
break;
default:
set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 0.0f));
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::set_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer::
set_data4f(unsigned char *pointer, const LVecBase4f &data) {
switch (_data_type->get_num_values()) {
case 1:
set_data1f(pointer, data[0]);
break;
case 2:
set_data2f(pointer, LVecBase2f(data[0], data[1]));
break;
case 3:
set_data3f(pointer, LVecBase3f(data[0], data[1], data[2]));
break;
default:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
maybe_scale_color(data);
pointer[0] = _a;
pointer[1] = _b;
pointer[2] = _c;
pointer[3] = _d;
break;
case qpGeomVertexDataType::NT_uint16:
{
PN_uint16 *pi = (PN_uint16 *)pointer;
pi[0] = (unsigned int)data[0];
pi[1] = (unsigned int)data[1];
pi[2] = (unsigned int)data[2];
pi[3] = (unsigned int)data[3];
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
maybe_scale_color(data);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
dword._b[0] = _d;
dword._b[1] = _a;
dword._b[2] = _b;
dword._b[3] = _c;
} else {
dword._b[0] = _a;
dword._b[1] = _b;
dword._b[2] = _c;
dword._b[3] = _d;
}
*(PN_uint32 *)pointer = dword._i;
}
break;
case qpGeomVertexDataType::NT_float32:
{
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
pi[3] = data[3];
}
break;
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer::set_data1i
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer::
set_data1i(unsigned char *pointer, int data) {
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
*pointer = data;
break;
case qpGeomVertexDataType::NT_uint16:
*(PN_uint16 *)pointer = data;
break;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
dword._i = 0;
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
dword._b[1] = data;
} else {
dword._b[0] = data;
}
*(PN_uint32 *)pointer = dword._i;
}
break;
case qpGeomVertexDataType::NT_float32:
*(PN_float32 *)pointer = (float)data;
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point::set_data1f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point::
set_data1f(unsigned char *pointer, float data) {
if (_data_type->get_num_values() == 4) {
set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 1.0f));
} else {
Writer::set_data1f(pointer, data);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point::set_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point::
set_data2f(unsigned char *pointer, const LVecBase2f &data) {
if (_data_type->get_num_values() == 4) {
set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 1.0f));
} else {
Writer::set_data2f(pointer, data);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point::set_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point::
set_data3f(unsigned char *pointer, const LVecBase3f &data) {
if (_data_type->get_num_values() == 4) {
set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
} else {
Writer::set_data3f(pointer, data);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point::set_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point::
set_data4f(unsigned char *pointer, const LVecBase4f &data) {
switch (_data_type->get_num_values()) {
case 1:
set_data1f(pointer, data[0] / data[3]);
break;
case 2:
set_data2f(pointer, LVecBase2f(data[0] / data[3], data[1] / data[3]));
break;
case 3:
set_data3f(pointer, LVecBase3f(data[0] / data[3], data[1] / data[3], data[2] / data[3]));
break;
default:
switch (_data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
maybe_scale_color(data);
pointer[0] = _a;
pointer[1] = _b;
pointer[2] = _c;
pointer[3] = _d;
break;
case qpGeomVertexDataType::NT_uint16:
{
PN_uint16 *pi = (PN_uint16 *)pointer;
pi[0] = (unsigned int)data[0];
pi[1] = (unsigned int)data[1];
pi[2] = (unsigned int)data[2];
pi[3] = (unsigned int)data[3];
}
break;
case qpGeomVertexDataType::NT_packed_8888:
{
packed_8888 dword;
maybe_scale_color(data);
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
dword._b[0] = _d;
dword._b[1] = _a;
dword._b[2] = _b;
dword._b[3] = _c;
} else {
dword._b[0] = _a;
dword._b[1] = _b;
dword._b[2] = _c;
dword._b[3] = _d;
}
*(PN_uint32 *)pointer = dword._i;
}
break;
case qpGeomVertexDataType::NT_float32:
{
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
pi[3] = data[3];
}
break;
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_color::set_data1f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_color::
set_data1f(unsigned char *pointer, float data) {
if (_data_type->get_num_values() == 4) {
set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 1.0f));
} else {
Writer::set_data1f(pointer, data);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_color::set_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_color::
set_data2f(unsigned char *pointer, const LVecBase2f &data) {
if (_data_type->get_num_values() == 4) {
set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 1.0f));
} else {
Writer::set_data2f(pointer, data);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_color::set_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_color::
set_data3f(unsigned char *pointer, const LVecBase3f &data) {
if (_data_type->get_num_values() == 4) {
set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
} else {
Writer::set_data3f(pointer, data);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_float32_3::set_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_float32_3::
set_data3f(unsigned char *pointer, const LVecBase3f &data) {
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point_float32_2::set_data2f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point_float32_2::
set_data2f(unsigned char *pointer, const LVecBase2f &data) {
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point_float32_3::set_data3f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point_float32_3::
set_data3f(unsigned char *pointer, const LVecBase3f &data) {
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_point_float32_4::set_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_point_float32_4::
set_data4f(unsigned char *pointer, const LVecBase4f &data) {
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
pi[3] = data[3];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_argb_packed_8888::set_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_argb_packed_8888::
set_data4f(unsigned char *pointer, const LVecBase4f &data) {
packed_8888 dword;
dword._b[0] = (unsigned int)(data[3] * 255.0f);
dword._b[1] = (unsigned int)(data[0] * 255.0f);
dword._b[2] = (unsigned int)(data[1] * 255.0f);
dword._b[3] = (unsigned int)(data[2] * 255.0f);
*(PN_uint32 *)pointer = dword._i;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_rgba_uint8_4::set_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_rgba_uint8_4::
set_data4f(unsigned char *pointer, const LVecBase4f &data) {
pointer[0] = (unsigned int)(data[0] * 255.0f);
pointer[1] = (unsigned int)(data[1] * 255.0f);
pointer[2] = (unsigned int)(data[2] * 255.0f);
pointer[3] = (unsigned int)(data[3] * 255.0f);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_rgba_float32_4::set_data4f
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_rgba_float32_4::
set_data4f(unsigned char *pointer, const LVecBase4f &data) {
PN_float32 *pi = (PN_float32 *)pointer;
pi[0] = data[0];
pi[1] = data[1];
pi[2] = data[2];
pi[3] = data[3];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Writer_uint16_1::set_data1i
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::Writer_uint16_1::
set_data1i(unsigned char *pointer, int data) {
*(PN_uint16 *)pointer = data;
}

View File

@ -0,0 +1,226 @@
// Filename: qpgeomVertexWriter.h
// Created by: drose (25Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXWRITER_H
#define qpGEOMVERTEXWRITER_H
#include "pandabase.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexDataType.h"
#include "internalName.h"
#include "luse.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexWriter
// Description : This object provides a high-level interface for
// quickly writing a sequence of numeric values from a
// vertex table.
//
// This object can be used both to replace existing
// vertices in the table, or to extend the table with
// new vertices. The set_data*() family of methods can
// only be used to replace existing data; it is an error
// to allow these to run past the end of the data. The
// add_data*() family of methods, on the other hand, can
// be used to replace existing data or add new data; if
// you call set_vertex() into the middle of existing
// data the add_data*() methods will behave like the
// corresponding set_data*(), but if they run past the
// end of existing data they will quietly add new data.
//
// Like GeomVertexReader, the writer is particularly
// optimized for writing a column of data values for a
// series of vertices, without changing data types
// between each number. Although you can use one
// GeomVertexWriter to write one complete row at a time,
// by calling set_data_type() repeatedly for each
// vertex, it is faster to use a different
// GeomVertexWriter for each data type.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexWriter {
PUBLISHED:
INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data);
INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data,
const string &name);
INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data,
const InternalName *name);
INLINE ~qpGeomVertexWriter();
INLINE qpGeomVertexData *get_vertex_data() const;
INLINE bool set_data_type(int data_type);
INLINE bool set_data_type(const string &name);
INLINE bool set_data_type(const InternalName *name);
bool set_data_type(int array, const qpGeomVertexDataType *data_type);
INLINE bool has_data_type() const;
INLINE int get_array() const;
INLINE const qpGeomVertexDataType *get_data_type() const;
INLINE void set_vertex(int vertex);
INLINE int get_start_vertex() const;
INLINE int get_write_vertex() const;
INLINE int get_num_vertices() const;
INLINE bool is_at_end() const;
INLINE void set_data1f(float data);
INLINE void set_data2f(float x, float y);
INLINE void set_data2f(const LVecBase2f &data);
INLINE void set_data3f(float x, float y, float z);
INLINE void set_data3f(const LVecBase3f &data);
INLINE void set_data4f(float x, float y, float z, float w);
INLINE void set_data4f(const LVecBase4f &data);
INLINE void set_data1i(int data);
INLINE void add_data1f(float data);
INLINE void add_data2f(float x, float y);
INLINE void add_data2f(const LVecBase2f &data);
INLINE void add_data3f(float x, float y, float z);
INLINE void add_data3f(const LVecBase3f &data);
INLINE void add_data4f(float x, float y, float z, float w);
INLINE void add_data4f(const LVecBase4f &data);
INLINE void add_data1i(int data);
private:
class Writer;
INLINE void set_pointer(int vertex);
INLINE unsigned char *inc_pointer();
INLINE unsigned char *inc_add_pointer();
Writer *make_writer() const;
PT(qpGeomVertexData) _vertex_data;
int _array;
const qpGeomVertexDataType *_data_type;
int _stride;
PTA_uchar _data;
unsigned char *_pointer;
int _start_vertex;
int _write_vertex;
int _num_vertices;
Writer *_writer;
// This union is handy for packing an NT_packed_8888 value.
typedef union {
unsigned char _b[4];
PN_uint32 _i;
} packed_8888;
// This nested class provides the implementation for unpacking data
// in a very general way, but also provides the hooks for
// implementing the common, very direct code paths (for instance,
// 3-component float32 to LVecBase3f) as quickly as possible.
class Writer {
public:
virtual ~Writer();
virtual void set_data1f(unsigned char *pointer, float data);
virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &data);
virtual void set_data1i(unsigned char *pointer, int data);
INLINE unsigned int maybe_scale_color(float data);
INLINE void maybe_scale_color(const LVecBase2f &data);
INLINE void maybe_scale_color(const LVecBase3f &data);
INLINE void maybe_scale_color(const LVecBase4f &data);
const qpGeomVertexDataType *_data_type;
unsigned int _a, _b, _c, _d;
};
// This is a specialization on the generic Writer that handles
// points, which are special because the fourth component, if
// present in the data but not specified by the caller, is
// implicitly 1.0; and if it is not present in the data but is
// specified, we have to divide by it.
class Writer_point : public Writer {
public:
virtual void set_data1f(unsigned char *pointer, float data);
virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &data);
};
// This is similar to Writer_point, in that the fourth component
// (alpha) is implicitly 1.0 if unspecified, but we never divide by
// alpha.
class Writer_color : public Writer {
public:
virtual void set_data1f(unsigned char *pointer, float data);
virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
};
// These are the specializations on the generic Writer that handle
// the direct code paths.
class Writer_float32_3 : public Writer {
public:
virtual void set_data3f(unsigned char *pointer, const LVecBase3f &value);
};
class Writer_point_float32_2 : public Writer_point {
public:
virtual void set_data2f(unsigned char *pointer, const LVecBase2f &value);
};
class Writer_point_float32_3 : public Writer_point {
public:
virtual void set_data3f(unsigned char *pointer, const LVecBase3f &value);
};
class Writer_point_float32_4 : public Writer_point {
public:
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
};
class Writer_argb_packed_8888 : public Writer_color {
public:
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
};
class Writer_rgba_uint8_4 : public Writer_color {
public:
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
};
class Writer_rgba_float32_4 : public Writer_color {
public:
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
};
class Writer_uint16_1 : public Writer {
public:
virtual void set_data1i(unsigned char *pointer, int value);
};
};
#include "qpgeomVertexWriter.I"
#endif

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "geomNode.h"
#include "qpgeom.h"
#include "geomTransformer.h"
#include "sceneGraphReducer.h"
#include "accumulatedAttribs.h"
@ -351,25 +352,35 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
int num_geoms = get_num_geoms();
for (int i = 0; i < num_geoms; i++) {
const Geom *geom = get_geom(i);
Geom::VertexIterator vi = geom->make_vertex_iterator();
int num_prims = geom->get_num_prims();
for (int p = 0; p < num_prims; p++) {
int length = geom->get_length(p);
for (int v = 0; v < length; v++) {
Vertexf vertex = geom->get_next_vertex(vi) * mat;
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
// Temporary test until the experimental Geom rewrite is final.
if (geom->is_exact_type(qpGeom::get_class_type())) {
const qpGeom *qpgeom = DCAST(qpGeom, geom);
qpgeom->calc_tight_bounds(min_point, max_point, found_any,
qpgeom->get_vertex_data()->animate_vertices(),
!transform->is_identity(), mat);
} else {
Geom::VertexIterator vi = geom->make_vertex_iterator();
int num_prims = geom->get_num_prims();
for (int p = 0; p < num_prims; p++) {
int length = geom->get_length(p);
for (int v = 0; v < length; v++) {
Vertexf vertex = geom->get_next_vertex(vi) * mat;
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
}
}
}
}