generalize index list

This commit is contained in:
David Rose 2005-04-15 14:32:31 +00:00
parent 2434300804
commit 4f47bf53e7
33 changed files with 1071 additions and 424 deletions

View File

@ -55,6 +55,7 @@
#include "qpgeomTristrips.h"
#include "qpgeomTrifans.h"
#include "qpgeomLines.h"
#include "qpGeomVertexReader.h"
#include "dxGeomMunger8.h"
#include "config_gobj.h"
#include "dxVertexBufferContext8.h"
@ -2747,13 +2748,15 @@ draw_triangles(const qpGeomTriangles *primitive) {
0, primitive->get_num_primitives());
} else {
D3DFORMAT index_type = get_index_type(primitive->get_index_type());
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLELIST,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_vertices(),
D3DFMT_INDEX16,
index_type,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
}
@ -2768,6 +2771,7 @@ void DXGraphicsStateGuardian8::
draw_tristrips(const qpGeomTristrips *primitive) {
int min_vertex = primitive->get_min_vertex();
int max_vertex = primitive->get_max_vertex();
D3DFORMAT index_type = get_index_type(primitive->get_index_type());
if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
// One long triangle strip, connected by the degenerate vertices
@ -2788,7 +2792,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
(D3DPT_TRIANGLESTRIP,
min_vertex, max_vertex - min_vertex + 1,
primitive->get_num_vertices() - 2,
primitive->get_vertices(), D3DFMT_INDEX16,
primitive->get_data(), index_type,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
}
@ -2797,9 +2801,11 @@ draw_tristrips(const qpGeomTristrips *primitive) {
// Send the individual triangle strips, stepping over the
// degenerate vertices.
CPTA_int ends = primitive->get_ends();
CPTA_ushort mins = primitive->get_mins();
CPTA_ushort maxs = primitive->get_maxs();
nassertv(mins.size() == ends.size() && maxs.size() == ends.size());
int index_stride = primitive->get_index_stride();
qpGeomVertexReader mins(primitive->get_mins(), 0);
qpGeomVertexReader maxs(primitive->get_mins(), 0);
nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size());
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
@ -2809,10 +2815,12 @@ draw_tristrips(const qpGeomTristrips *primitive) {
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_tristrip_pcollector.add_level(ends[i] - start);
unsigned int min = mins.get_data1i();
unsigned int max = maxs.get_data1i();
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLESTRIP,
mins[i], maxs[i] - mins[i] + 1,
start, ends[i] - start - 2);
min, max - min + 1,
start * index_stride, ends[i] - start - 2);
start = ends[i] + 2;
}
@ -2820,16 +2828,18 @@ draw_tristrips(const qpGeomTristrips *primitive) {
} else {
CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
int stride = _vertex_data->get_format()->get_array(0)->get_stride();
CPTA_ushort vertices = primitive->get_vertices();
CPTA_uchar vertices = primitive->get_data();
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_tristrip_pcollector.add_level(ends[i] - start);
unsigned int min = mins.get_data1i();
unsigned int max = maxs.get_data1i();
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLESTRIP,
mins[i], maxs[i] - mins[i] + 1,
min, max - min + 1,
ends[i] - start - 2,
vertices + start, D3DFMT_INDEX16,
vertices + start * index_stride, index_type,
array_data, stride);
start = ends[i] + 2;
@ -2847,13 +2857,16 @@ void DXGraphicsStateGuardian8::
draw_trifans(const qpGeomTrifans *primitive) {
int min_vertex = primitive->get_min_vertex();
int max_vertex = primitive->get_max_vertex();
D3DFORMAT index_type = get_index_type(primitive->get_index_type());
// Send the individual triangle fans. There's no connecting fans
// with degenerate vertices, so no worries about that.
CPTA_int ends = primitive->get_ends();
CPTA_ushort mins = primitive->get_mins();
CPTA_ushort maxs = primitive->get_maxs();
nassertv(mins.size() == ends.size() && maxs.size() == ends.size());
int index_stride = primitive->get_index_stride();
qpGeomVertexReader mins(primitive->get_mins(), 0);
qpGeomVertexReader maxs(primitive->get_mins(), 0);
nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size());
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
@ -2863,10 +2876,12 @@ draw_trifans(const qpGeomTrifans *primitive) {
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_trifan_pcollector.add_level(ends[i] - start);
unsigned int min = mins.get_data1i();
unsigned int max = maxs.get_data1i();
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLEFAN,
mins[i], maxs[i] - mins[i] + 1,
start, ends[i] - start - 2);
min, max - min + 1,
start * index_stride, ends[i] - start - 2);
start = ends[i] + 2;
}
@ -2874,16 +2889,18 @@ draw_trifans(const qpGeomTrifans *primitive) {
} else {
CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
int stride = _vertex_data->get_format()->get_array(0)->get_stride();
CPTA_ushort vertices = primitive->get_vertices();
CPTA_uchar vertices = primitive->get_data();
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_trifan_pcollector.add_level(ends[i] - start);
unsigned int min = mins.get_data1i();
unsigned int max = maxs.get_data1i();
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLEFAN,
mins[i], maxs[i] - mins[i] + 1,
min, max - min + 1,
ends[i] - start - 2,
vertices + start, D3DFMT_INDEX16,
vertices + start * index_stride, index_type,
array_data, stride);
start = ends[i] + 2;
@ -2911,13 +2928,15 @@ draw_lines(const qpGeomLines *primitive) {
0, primitive->get_num_primitives());
} else {
D3DFORMAT index_type = get_index_type(primitive->get_index_type());
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_LINELIST,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_vertices(),
D3DFMT_INDEX16,
primitive->get_data(),
index_type,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
}
@ -4249,6 +4268,27 @@ end_frame() {
GraphicsStateGuardian::end_frame();
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::get_index_type
// Access: Protected, Static
// Description: Maps from the Geom's internal numeric type symbols
// to DirectX's.
////////////////////////////////////////////////////////////////////
D3DFORMAT DXGraphicsStateGuardian8::
get_index_type(qpGeom::NumericType numeric_type) {
switch (numeric_type) {
case qpGeom::NT_uint16:
return D3DFMT_INDEX16;
case qpGeom::NT_uint32:
return D3DFMT_INDEX32;
}
dxgsg8_cat.error()
<< "Invalid index NumericType value (" << (int)numeric_type << ")\n";
return D3DFMT_INDEX16;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::set_draw_buffer
// Access: Protected

View File

@ -152,6 +152,8 @@ public:
INLINE float compute_distance_to(const LPoint3f &point) const;
virtual void set_color_clear_value(const Colorf& value);
static D3DFORMAT get_index_type(qpGeom::NumericType numeric_type);
public:
// recreate_tex_callback needs these to be public
DXScreenData *_pScrn;

View File

@ -65,9 +65,12 @@ create_ibuffer(DXScreenData &scrn) {
_ibuffer = NULL;
}
D3DFORMAT index_type =
DXGraphicsStateGuardian8::get_index_type(get_data()->get_index_type());
HRESULT hr = scrn.pD3DDevice->CreateIndexBuffer
(get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16, D3DPOOL_MANAGED, &_ibuffer);
index_type, D3DPOOL_MANAGED, &_ibuffer);
if (FAILED(hr)) {
dxgsg8_cat.warning()
<< "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
@ -104,7 +107,7 @@ upload_data() {
return;
}
memcpy(local_pointer, get_data()->get_vertices(), data_size);
memcpy(local_pointer, get_data()->get_data(), data_size);
_ibuffer->Unlock();
}

View File

@ -2480,13 +2480,14 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
void CLP(GraphicsStateGuardian)::
draw_triangles(const qpGeomTriangles *primitive) {
_vertices_tri_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
const unsigned char *client_pointer = setup_primitive(primitive);
_glDrawRangeElements(GL_TRIANGLES,
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, client_pointer);
get_numeric_type(primitive->get_index_type()),
client_pointer);
report_my_gl_errors();
}
@ -2498,7 +2499,7 @@ draw_triangles(const qpGeomTriangles *primitive) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_tristrips(const qpGeomTristrips *primitive) {
const unsigned short *client_pointer = setup_primitive(primitive);
const unsigned char *client_pointer = setup_primitive(primitive);
if (connect_triangle_strips && _render_mode != RenderModeAttrib::M_wireframe) {
// One long triangle strip, connected by the degenerate vertices
@ -2508,22 +2509,27 @@ draw_tristrips(const qpGeomTristrips *primitive) {
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, client_pointer);
get_numeric_type(primitive->get_index_type()),
client_pointer);
} else {
// Send the individual triangle strips, stepping over the
// degenerate vertices.
CPTA_int ends = primitive->get_ends();
CPTA_ushort mins = primitive->get_mins();
CPTA_ushort maxs = primitive->get_maxs();
nassertv(mins.size() == ends.size() && maxs.size() == ends.size());
int index_stride = primitive->get_index_stride();
qpGeomVertexReader mins(primitive->get_mins(), 0);
qpGeomVertexReader maxs(primitive->get_mins(), 0);
nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size());
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_tristrip_pcollector.add_level(ends[i] - start);
_glDrawRangeElements(GL_TRIANGLE_STRIP,
mins[i], maxs[i], ends[i] - start,
GL_UNSIGNED_SHORT, client_pointer + start);
mins.get_data1i(), maxs.get_data1i(),
ends[i] - start,
get_numeric_type(primitive->get_index_type()),
client_pointer + start * index_stride);
start = ends[i] + 2;
}
}
@ -2531,6 +2537,37 @@ draw_tristrips(const qpGeomTristrips *primitive) {
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::draw_trifans
// Access: Public, Virtual
// Description: Draws a series of triangle fans.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_trifans(const qpGeomTrifans *primitive) {
const unsigned char *client_pointer = setup_primitive(primitive);
// Send the individual triangle fans. There's no connecting fans
// with degenerate vertices, so no worries about that.
CPTA_int ends = primitive->get_ends();
int index_stride = primitive->get_index_stride();
qpGeomVertexReader mins(primitive->get_mins(), 0);
qpGeomVertexReader maxs(primitive->get_mins(), 0);
nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size());
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_trifan_pcollector.add_level(ends[i] - start);
_glDrawRangeElements(GL_TRIANGLE_FAN,
mins.get_data1i(), maxs.get_data1i(), ends[i] - start,
get_numeric_type(primitive->get_index_type()),
client_pointer + start * index_stride);
start = ends[i] + 2;
}
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::draw_lines
// Access: Public, Virtual
@ -2539,13 +2576,14 @@ draw_tristrips(const qpGeomTristrips *primitive) {
void CLP(GraphicsStateGuardian)::
draw_lines(const qpGeomLines *primitive) {
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
const unsigned char *client_pointer = setup_primitive(primitive);
_glDrawRangeElements(GL_LINES,
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, client_pointer);
get_numeric_type(primitive->get_index_type()),
client_pointer);
report_my_gl_errors();
}
@ -2567,13 +2605,14 @@ draw_linestrips(const qpGeomLinestrips *primitive) {
void CLP(GraphicsStateGuardian)::
draw_points(const qpGeomPoints *primitive) {
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
const unsigned char *client_pointer = setup_primitive(primitive);
_glDrawRangeElements(GL_POINTS,
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, client_pointer);
get_numeric_type(primitive->get_index_type()),
client_pointer);
report_my_gl_errors();
}
@ -3005,12 +3044,12 @@ apply_index_buffer(IndexBufferContext *ibc) {
}
if (gibc->changed_size()) {
_glBufferData(GL_ELEMENT_ARRAY_BUFFER, gibc->get_data()->get_data_size_bytes(),
gibc->get_data()->get_vertices(),
gibc->get_data()->get_data(),
get_usage(gibc->get_data()->get_usage_hint()));
} else {
_glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, gibc->get_data_size_bytes(),
gibc->get_data()->get_vertices());
gibc->get_data()->get_data());
}
gibc->mark_loaded();
@ -3059,23 +3098,23 @@ release_index_buffer(IndexBufferContext *ibc) {
// this function returns the pointer to the data array
// in client memory, that is, the data array passed in.
////////////////////////////////////////////////////////////////////
const unsigned short *CLP(GraphicsStateGuardian)::
const unsigned char *CLP(GraphicsStateGuardian)::
setup_primitive(const qpGeomPrimitive *data) {
if (!_supports_buffers) {
// No support for buffer objects; always render from client.
return data->get_vertices();
return data->get_data();
}
if (!vertex_buffers || _geom_display_list != 0 ||
data->get_usage_hint() == qpGeom::UH_client) {
// The array specifies client rendering only, or buffer objects
// are configured off.
_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return data->get_vertices();
return data->get_data();
}
// Prepare the buffer object and bind it.
IndexBufferContext *ibc = ((qpGeomPrimitive *)data)->prepare_now(get_prepared_objects(), this);
nassertr(ibc != (IndexBufferContext *)NULL, data->get_vertices());
nassertr(ibc != (IndexBufferContext *)NULL, data->get_data());
apply_index_buffer(ibc);
// NULL is the OpenGL convention for the first byte of the buffer object.
@ -4735,6 +4774,9 @@ get_numeric_type(qpGeom::NumericType numeric_type) {
case qpGeom::NT_uint16:
return GL_UNSIGNED_SHORT;
case qpGeom::NT_uint32:
return GL_UNSIGNED_INT;
case qpGeom::NT_uint8:
case qpGeom::NT_packed_dcba:
case qpGeom::NT_packed_dabc:

View File

@ -99,6 +99,7 @@ public:
const qpGeomVertexData *vertex_data);
virtual void draw_triangles(const qpGeomTriangles *primitive);
virtual void draw_tristrips(const qpGeomTristrips *primitive);
virtual void draw_trifans(const qpGeomTrifans *primitive);
virtual void draw_lines(const qpGeomLines *primitive);
virtual void draw_linestrips(const qpGeomLinestrips *primitive);
virtual void draw_points(const qpGeomPoints *primitive);
@ -122,7 +123,7 @@ public:
virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data);
void apply_index_buffer(IndexBufferContext *ibc);
virtual void release_index_buffer(IndexBufferContext *ibc);
const unsigned short *setup_primitive(const qpGeomPrimitive *data);
const unsigned char *setup_primitive(const qpGeomPrimitive *data);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);

View File

@ -91,7 +91,9 @@ get_error() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_vertex
// Access: Published, Static
// Description: Returns the standard InternalName "vertex".
// Description: Returns the standard InternalName "vertex". This is
// the column header for the 3-d or 4-d vertex position
// information for each vertex.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_vertex() {
@ -104,7 +106,9 @@ get_vertex() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_normal
// Access: Published, Static
// Description: Returns the standard InternalName "normal".
// Description: Returns the standard InternalName "normal". This is
// the column header for the 3-d lighting normal for
// each vertex.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_normal() {
@ -117,7 +121,12 @@ get_normal() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_tangent
// Access: Published, Static
// Description: Returns the standard InternalName "tangent".
// Description: Returns the standard InternalName "tangent". This is
// the column header for the tangent vector associated
// with each vertex, which is a unit vector
// usually perpendicular to the normal and in the
// direction of the U texture coordinate change. It is
// used for deriving bump maps.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_tangent() {
@ -130,7 +139,13 @@ get_tangent() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_binormal
// Access: Published, Static
// Description: Returns the standard InternalName "binormal".
// Description: Returns the standard InternalName "binormal". This is
// the column header for the tangent vector associated
// with each vertex, which is a unit vector
// usually perpendicular to both the normal and the
// tangent, and in the direction of the V texture
// coordinate change. It is used for deriving bump
// maps.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_binormal() {
@ -143,7 +158,11 @@ get_binormal() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_texcoord
// Access: Published, Static
// Description: Returns the standard InternalName "texcoord".
// Description: Returns the standard InternalName "texcoord". This
// is the column header for the default texture
// coordinate set for each vertex. It is also used for
// identifying the default texture coordinate set in a
// TextureStage.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_texcoord() {
@ -157,8 +176,10 @@ get_texcoord() {
// Function: InternalName::get_texcoord_name
// Access: Published, Static
// Description: Returns the InternalName "texcoord.name", where name
// is the supplied string. This, by convention,
// represents the named texture coordinate set.
// is the supplied string. This is the column header
// for the named texture coordinate set for each vertex.
// It is also used for identifying the named texture
// coordinate set in a TextureStage.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_texcoord_name(const string &name) {
@ -168,7 +189,9 @@ get_texcoord_name(const string &name) {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_color
// Access: Published, Static
// Description: Returns the standard InternalName "color".
// Description: Returns the standard InternalName "color". This is
// the column header for the 4-component color value for
// each vertex.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_color() {
@ -181,7 +204,11 @@ get_color() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_rotate
// Access: Published, Static
// Description: Returns the standard InternalName "rotate".
// Description: Returns the standard InternalName "rotate". This is
// the column header for the floating-point rotate
// value, which represents a number of degrees
// counter-clockwise to rotate each point or point
// sprite.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_rotate() {
@ -194,7 +221,11 @@ get_rotate() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_size
// Access: Published, Static
// Description: Returns the standard InternalName "size".
// Description: Returns the standard InternalName "size". This is
// the column header for the floating-point size value,
// which overrides the thickness parameter of the
// RenderModeAttrib on a per-vertex (e.g. per-point)
// basis.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_size() {
@ -208,6 +239,10 @@ get_size() {
// Function: InternalName::get_aspect_ratio
// Access: Published, Static
// Description: Returns the standard InternalName "aspect_ratio".
// This is the column header for the floating-point
// aspect ratio value, which is used to define
// non-square points. This number is the ratio x / y,
// where y is the point size (above).
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_aspect_ratio() {
@ -221,6 +256,10 @@ get_aspect_ratio() {
// Function: InternalName::get_transform_blend
// Access: Published, Static
// Description: Returns the standard InternalName "transform_blend".
// This is the column header for the integer
// transform_blend index, which is used to define vertex
// animation on the CPU by indexing to a particular
// vertex weighting from the TransformBlendPalette.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_transform_blend() {
@ -234,6 +273,14 @@ get_transform_blend() {
// Function: InternalName::get_transform_weight
// Access: Published, Static
// Description: Returns the standard InternalName "transform_weight".
// This is the column header for the n-component
// transform_weight value, which is used in conjuntion
// with "transform_index" to define vertex animation on
// the graphics card. The transform_weight value
// specifies the weight of the nth transform. By
// convention, there are 1 fewer weight values than
// transforms, since the weights are assumed to sum to 1
// (and the last value is therefore implicit).
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_transform_weight() {
@ -247,6 +294,14 @@ get_transform_weight() {
// Function: InternalName::get_transform_index
// Access: Published, Static
// Description: Returns the standard InternalName "transform_index".
// This is the column header for the n-component
// transform_index value, which is used in conjuntion
// with "transform_weight" to define vertex animation on
// the graphics card. The transform_index value
// specifies the nth transform, by lookup in the
// TransformPalette. The transform_index column may be
// omitted, in which case the nth transform is the nth
// entry in the palette.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_transform_index() {
@ -259,16 +314,41 @@ get_transform_index() {
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_morph
// Access: Published, Static
// Description: Returns an InternalName suitable for defining the
// morph deltas in the GeomVertexData to apply to the
// indicated data type name, using the named slider.
// Description: Returns an InternalName derived from the given base
// column name and the given slider name, which is the
// column header for the offset vector that should be
// applied to the base column name when the named morph
// slider is engaged.
//
// Each morph slider requires a set of n morph columns,
// one for each base column it applies to.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_morph(InternalName *column, const string &slider) {
// Returns column.morph.slider
// This actually returns "column.morph.slider", although that's just
// an implementation detail--as long as it returns a consistent,
// unique name for each combination of column and slider, everything
// is good.
return column->append("morph")->append(slider);
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_index
// Access: Published, Static
// Description: Returns the standard InternalName "index". This is
// the column header for the integer vertex index. It
// is not used in the vertex data itself, but is used in
// the GeomPrimitive structure to index into the vertex
// data.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_index() {
if (_index == (InternalName *)NULL) {
_index = InternalName::make("index");
}
return _index;
}
INLINE ostream &
operator << (ostream &out, const InternalName &tcn) {
tcn.output(out);

View File

@ -38,6 +38,7 @@ PT(InternalName) InternalName::_aspect_ratio;
PT(InternalName) InternalName::_transform_blend;
PT(InternalName) InternalName::_transform_weight;
PT(InternalName) InternalName::_transform_index;
PT(InternalName) InternalName::_index;
TypeHandle InternalName::_type_handle;
TypeHandle InternalName::_texcoord_type_handle;

View File

@ -78,6 +78,7 @@ PUBLISHED:
INLINE static PT(InternalName) get_transform_weight();
INLINE static PT(InternalName) get_transform_index();
INLINE static PT(InternalName) get_morph(InternalName *column, const string &slider);
INLINE static PT(InternalName) get_index();
private:
PT(InternalName) _parent;
@ -101,6 +102,7 @@ private:
static PT(InternalName) _transform_blend;
static PT(InternalName) _transform_weight;
static PT(InternalName) _transform_index;
static PT(InternalName) _index;
public:
// Datagram stuff

View File

@ -28,6 +28,9 @@ operator << (ostream &out, qpGeomEnums::NumericType numeric_type) {
case qpGeomEnums::NT_uint16:
return out << "uint16";
case qpGeomEnums::NT_uint32:
return out << "uint32";
case qpGeomEnums::NT_packed_dcba:
return out << "packed_dcba";

View File

@ -169,6 +169,7 @@ PUBLISHED:
enum NumericType {
NT_uint8, // An integer 0..255
NT_uint16, // An integer 0..65535
NT_uint32, // An integer 0..4294967296
NT_packed_dcba, // DirectX style, four byte values packed in a uint32
NT_packed_dabc, // DirectX packed color order (ARGB)
NT_float32, // A floating-point number

View File

@ -121,20 +121,26 @@ draw(GraphicsStateGuardianBase *gsg) const {
// Access: Protected, Virtual
// Description: The virtual implementation of do_rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomLines::
CPT(qpGeomVertexArrayData) qpGeomLines::
rotate_impl() const {
// To rotate lines, we just move reverse the pairs of vertices.
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
PTA_ushort new_vertices;
new_vertices.reserve(vertices.size());
PT(qpGeomVertexArrayData) new_vertices =
new qpGeomVertexArrayData(*vertices);
qpGeomVertexReader from(vertices, 0);
qpGeomVertexWriter to(new_vertices, 0);
for (int begin = 0; begin < (int)vertices.size(); begin += 2) {
new_vertices.push_back(vertices[begin + 1]);
new_vertices.push_back(vertices[begin]);
int num_vertices = vertices->get_num_vertices();
for (int begin = 0; begin < num_vertices; begin += 2) {
from.set_vertex(begin + 1);
to.set_data1i(from.get_data1i());
from.set_vertex(begin);
to.set_data1i(from.get_data1i());
}
nassertr(new_vertices.size() == vertices.size(), CPTA_ushort());
nassertr(to.is_at_end(), NULL);
return new_vertices;
}

View File

@ -45,7 +45,7 @@ public:
virtual void draw(GraphicsStateGuardianBase *gsg) const;
protected:
virtual CPTA_ushort rotate_impl() const;
virtual CPT(qpGeomVertexArrayData) rotate_impl() const;
public:
static void register_with_read_factory();

View File

@ -18,6 +18,7 @@
#include "qpgeomLinestrips.h"
#include "qpgeomLines.h"
#include "qpgeomVertexRewriter.h"
#include "pStatTimer.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -131,7 +132,8 @@ CPT(qpGeomPrimitive) qpGeomLinestrips::
decompose_impl() const {
PT(qpGeomLines) lines = new qpGeomLines(get_usage_hint());
lines->set_shade_model(get_shade_model());
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
qpGeomVertexReader index(vertices, 0);
CPTA_int ends = get_ends();
int vi = 0;
@ -139,20 +141,19 @@ decompose_impl() const {
while (li < (int)ends.size()) {
int end = ends[li];
nassertr(vi + 1 <= end, lines.p());
nassertr(vi < (int)vertices.size(), this);
int v0 = vertices[vi];
int v0 = index.get_data1i();
++vi;
while (vi < end) {
lines->add_vertex(v0);
lines->add_vertex(vertices[vi]);
nassertr(vi < (int)vertices.size(), this);
v0 = vertices[vi];
lines->close_primitive();
int v1 = index.get_data1i();
++vi;
lines->add_vertex(v0);
lines->add_vertex(v1);
v0 = v1;
lines->close_primitive();
}
++li;
}
nassertr(vi == (int)vertices.size(), lines.p());
nassertr(vi == vertices->get_num_vertices() && index.is_at_end(), NULL);
return lines.p();
}
@ -162,25 +163,28 @@ decompose_impl() const {
// Access: Protected, Virtual
// Description: The virtual implementation of do_rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomLinestrips::
CPT(qpGeomVertexArrayData) qpGeomLinestrips::
rotate_impl() const {
// To rotate a line strip, we just reverse the vertices.
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
CPTA_int ends = get_ends();
PTA_ushort new_vertices;
new_vertices.reserve(vertices.size());
PT(qpGeomVertexArrayData) new_vertices =
new qpGeomVertexArrayData(*vertices);
qpGeomVertexReader from(vertices, 0);
qpGeomVertexWriter to(new_vertices, 0);
int begin = 0;
CPTA_int::const_iterator ei;
for (ei = ends.begin(); ei != ends.end(); ++ei) {
int end = (*ei);
for (int vi = end - 1; vi >= begin; --vi) {
new_vertices.push_back(vertices[vi]);
from.set_vertex(vi);
to.set_data1i(from.get_data1i());
}
begin = end;
}
nassertr(new_vertices.size() == vertices.size(), CPTA_ushort());
nassertr(to.is_at_end(), NULL);
return new_vertices;
}

View File

@ -45,7 +45,7 @@ public:
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;
virtual CPTA_ushort rotate_impl() const;
virtual CPT(qpGeomVertexArrayData) rotate_impl() const;
public:
static void register_with_read_factory();

View File

@ -65,8 +65,7 @@ set_shade_model(qpGeomPrimitive::ShadeModel shade_model) {
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::UsageHint qpGeomPrimitive::
get_usage_hint() const {
CDReader cdata(_cycler);
return cdata->_usage_hint;
return get_vertices()->get_usage_hint();
}
////////////////////////////////////////////////////////////////////
@ -77,8 +76,19 @@ get_usage_hint() const {
////////////////////////////////////////////////////////////////////
INLINE void qpGeomPrimitive::
set_usage_hint(qpGeomPrimitive::UsageHint usage_hint) {
CDWriter cdata(_cycler);
cdata->_usage_hint = usage_hint;
modify_vertices()->set_usage_hint(usage_hint);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_index_type
// Access: Public
// Description: Returns the numeric type of the index column.
// Normally, this will be either NT_uint16 or NT_uint32.
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::NumericType qpGeomPrimitive::
get_index_type() const {
CDReader cdata(_cycler);
return cdata->_index_type;
}
////////////////////////////////////////////////////////////////////
@ -90,19 +100,7 @@ set_usage_hint(qpGeomPrimitive::UsageHint usage_hint) {
INLINE int qpGeomPrimitive::
get_num_vertices() const {
CDReader cdata(_cycler);
return cdata->_vertices.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_vertex
// Access: Published
// Description: Returns the ith vertex index in the table.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_vertex(int i) const {
CDReader cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_vertices.size(), -1);
return cdata->_vertices[i];
return cdata->_vertices->get_num_vertices();
}
////////////////////////////////////////////////////////////////////
@ -162,19 +160,6 @@ get_min_vertex() const {
return cdata->_min_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_min_vertex
// Access: Published
// Description: Returns the minimum vertex index number used by the
// nth primitive in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_primitive_min_vertex(int n) const {
CPTA_ushort mins = get_mins();
nassertr(n >= 0 && n < (int)mins.size(), -1);
return mins[n];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_max_vertex
// Access: Published
@ -192,19 +177,6 @@ get_max_vertex() const {
return cdata->_max_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_max_vertex
// Access: Published
// Description: Returns the maximum vertex index number used by the
// nth primitive in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_primitive_max_vertex(int n) const {
CPTA_ushort maxs = get_maxs();
nassertr(n >= 0 && n < (int)maxs.size(), -1);
return maxs[n];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_data_size_bytes
// Access: Published
@ -214,7 +186,7 @@ get_primitive_max_vertex(int n) const {
INLINE int qpGeomPrimitive::
get_data_size_bytes() const {
CDReader cdata(_cycler);
return cdata->_vertices.size() * sizeof(short);
return cdata->_vertices->get_data_size_bytes();
}
////////////////////////////////////////////////////////////////////
@ -238,12 +210,35 @@ get_modified() const {
// attempt to modify the returned array; use
// modify_vertices() or set_vertices() for this.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
INLINE const qpGeomVertexArrayData *qpGeomPrimitive::
get_vertices() const {
CDReader cdata(_cycler);
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_index_stride
// Access: Public
// Description: A convenience function to return the gap between
// successive index numbers, in bytes, of the index
// data.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_index_stride() const {
return get_vertices()->get_array_format()->get_stride();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_data
// Access: Public
// Description: A convenience function to return the actual data of
// the index array.
////////////////////////////////////////////////////////////////////
INLINE CPTA_uchar qpGeomPrimitive::
get_data() const {
return get_vertices()->get_data();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_ends
// Access: Public
@ -273,7 +268,7 @@ get_ends() const {
// Note that simple primitive types, like triangles, do
// not have a mins array.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
INLINE const qpGeomVertexArrayData *qpGeomPrimitive::
get_mins() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
@ -295,7 +290,7 @@ get_mins() const {
// Note that simple primitive types, like triangles, do
// not have a maxs array.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
INLINE const qpGeomVertexArrayData *qpGeomPrimitive::
get_maxs() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
@ -313,8 +308,8 @@ get_maxs() const {
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::CData::
CData() :
_usage_hint(UH_unspecified),
_shade_model(SM_smooth),
_index_type(NT_uint16),
_got_minmax(true),
_min_vertex(0),
_max_vertex(0)
@ -328,8 +323,8 @@ CData() :
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::CData::
CData(const qpGeomPrimitive::CData &copy) :
_usage_hint(copy._usage_hint),
_shade_model(copy._shade_model),
_index_type(copy._index_type),
_vertices(copy._vertices),
_ends(copy._ends),
_mins(copy._mins),

View File

@ -22,6 +22,8 @@
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexColumn.h"
#include "qpgeomVertexReader.h"
#include "qpgeomVertexWriter.h"
#include "qpgeomVertexRewriter.h"
#include "preparedGraphicsObjects.h"
#include "internalName.h"
#include "bamReader.h"
@ -33,6 +35,16 @@ TypeHandle qpGeomPrimitive::_type_handle;
PStatCollector qpGeomPrimitive::_decompose_pcollector("Cull:Munge:Decompose");
PStatCollector qpGeomPrimitive::_rotate_pcollector("Cull:Munge:Rotate");
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::Default Constructor
// Access: Protected
// Description: Constructs an invalid object. Only used when reading
// from bam.
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
qpGeomPrimitive() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::Constructor
// Access: Published
@ -40,7 +52,14 @@ PStatCollector qpGeomPrimitive::_rotate_pcollector("Cull:Munge:Rotate");
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
qpGeomPrimitive(qpGeomPrimitive::UsageHint usage_hint) {
set_usage_hint(usage_hint);
CDWriter cdata(_cycler);
CPT(qpGeomVertexArrayFormat) new_format =
qpGeomVertexArrayFormat::register_format
(new qpGeomVertexArrayFormat(InternalName::get_index(), 1,
cdata->_index_type, C_index));
cdata->_vertices = new qpGeomVertexArrayData(new_format, usage_hint);
}
////////////////////////////////////////////////////////////////////
@ -78,6 +97,52 @@ get_geom_rendering() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_index_type
// Access: Published
// Description: Changes the numeric type of the index column.
// Normally, this should be either NT_uint16 or
// NT_uint32.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_index_type(qpGeomPrimitive::NumericType index_type) {
CDWriter cdata(_cycler);
cdata->_index_type = index_type;
CPT(qpGeomVertexArrayFormat) new_format =
qpGeomVertexArrayFormat::register_format
(new qpGeomVertexArrayFormat(InternalName::get_index(), 1, index_type,
C_index));
if (cdata->_vertices->get_array_format() != new_format) {
PT(qpGeomVertexArrayData) new_vertices =
new qpGeomVertexArrayData(new_format, cdata->_vertices->get_usage_hint());
qpGeomVertexReader from(cdata->_vertices, 0);
qpGeomVertexWriter to(new_vertices, 0);
while (!from.is_at_end()) {
to.add_data1i(from.get_data1i());
}
cdata->_vertices = new_vertices;
cdata->_got_minmax = false;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_vertex
// Access: Published
// Description: Returns the ith vertex index in the table.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_vertex(int i) const {
CDReader cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_vertices->get_num_vertices(), -1);
qpGeomVertexReader index(cdata->_vertices, 0);
index.set_vertex(i);
return index.get_data1i();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::add_vertex
// Access: Published
@ -90,39 +155,22 @@ get_geom_rendering() const {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
add_vertex(int vertex) {
unsigned short short_vertex = vertex;
nassertv((int)short_vertex == vertex);
CDWriter cdata(_cycler);
int num_primitives = get_num_primitives();
if (num_primitives > 0 &&
(int)cdata->_vertices.size() == get_primitive_end(num_primitives - 1)) {
(int)cdata->_vertices->get_num_vertices() == get_primitive_end(num_primitives - 1)) {
// If we are beginning a new primitive, give the derived class a
// chance to insert some degenerate vertices.
append_unused_vertices(cdata->_vertices, vertex);
}
cdata->_vertices.push_back(short_vertex);
qpGeomVertexWriter index(cdata->_vertices, 0);
index.set_vertex(index.get_num_vertices());
if (cdata->_got_minmax) {
cdata->_min_vertex = min(cdata->_min_vertex, short_vertex);
cdata->_max_vertex = max(cdata->_max_vertex, short_vertex);
index.add_data1i(vertex);
if (get_num_vertices_per_primitive() == 0) {
// Complex primitives also update their per-primitive minmax.
size_t pi = cdata->_ends.size();
if (pi < cdata->_mins.size()) {
cdata->_mins[pi] = min(cdata->_mins[pi], short_vertex);
cdata->_maxs[pi] = max(cdata->_maxs[pi], short_vertex);
} else {
cdata->_mins.push_back(short_vertex);
cdata->_maxs.push_back(short_vertex);
}
nassertv((cdata->_mins.size() == cdata->_ends.size() + 1) &&
(cdata->_maxs.size() == cdata->_ends.size() + 1));
}
}
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
@ -137,42 +185,25 @@ add_consecutive_vertices(int start, int num_vertices) {
return;
}
int end = (start + num_vertices) - 1;
unsigned short short_start = start;
unsigned short short_end = end;
nassertv((int)short_start == start && (int)short_end == end);
CDWriter cdata(_cycler);
int num_primitives = get_num_primitives();
if (num_primitives > 0 &&
(int)cdata->_vertices.size() == get_primitive_end(num_primitives - 1)) {
(int)cdata->_vertices->get_num_vertices() == get_primitive_end(num_primitives - 1)) {
// If we are beginning a new primitive, give the derived class a
// chance to insert some degenerate vertices.
append_unused_vertices(cdata->_vertices, start);
}
for (unsigned short v = short_start; v <= short_end; ++v) {
cdata->_vertices.push_back(v);
qpGeomVertexWriter index(cdata->_vertices, 0);
index.set_vertex(index.get_num_vertices());
for (int v = start; v <= end; ++v) {
index.add_data1i(v);
}
if (cdata->_got_minmax) {
cdata->_min_vertex = min(cdata->_min_vertex, short_start);
cdata->_max_vertex = max(cdata->_max_vertex, short_end);
if (get_num_vertices_per_primitive() == 0) {
// Complex primitives also update their per-primitive minmax.
size_t pi = cdata->_ends.size();
if (pi < cdata->_mins.size()) {
cdata->_mins[pi] = min(cdata->_mins[pi], short_start);
cdata->_maxs[pi] = max(cdata->_maxs[pi], short_end);
} else {
cdata->_mins.push_back(short_start);
cdata->_maxs.push_back(short_end);
}
nassertv((cdata->_mins.size() == cdata->_ends.size() + 1) &&
(cdata->_maxs.size() == cdata->_ends.size() + 1));
}
}
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
@ -214,23 +245,14 @@ close_primitive() {
#ifndef NDEBUG
int num_added;
if (cdata->_ends.empty()) {
num_added = (int)cdata->_vertices.size();
num_added = (int)cdata->_vertices->get_num_vertices();
} else {
num_added = (int)cdata->_vertices.size() - cdata->_ends.back();
num_added = (int)cdata->_vertices->get_num_vertices() - cdata->_ends.back();
num_added -= get_num_unused_vertices_per_primitive();
}
nassertr(num_added >= get_min_num_vertices_per_primitive(), false);
#endif
cdata->_ends.push_back((int)cdata->_vertices.size());
#ifndef NDEBUG
if (cdata->_got_minmax) {
nassertd((cdata->_mins.size() == cdata->_ends.size()) &&
(cdata->_maxs.size() == cdata->_ends.size())) {
cdata->_got_minmax = false;
}
}
#endif
cdata->_ends.push_back((int)cdata->_vertices->get_num_vertices());
} else {
#ifndef NDEBUG
@ -240,7 +262,7 @@ close_primitive() {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
int num_vertices = cdata->_vertices.size();
int num_vertices = cdata->_vertices->get_num_vertices();
nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0, false)
#endif
}
@ -257,7 +279,8 @@ close_primitive() {
void qpGeomPrimitive::
clear_vertices() {
CDWriter cdata(_cycler);
cdata->_vertices.clear();
cdata->_vertices = new qpGeomVertexArrayData
(cdata->_vertices->get_array_format(), cdata->_vertices->get_usage_hint());
cdata->_ends.clear();
cdata->_mins.clear();
cdata->_maxs.clear();
@ -274,13 +297,12 @@ void qpGeomPrimitive::
offset_vertices(int offset) {
CDWriter cdata(_cycler);
cdata->_mins.clear();
cdata->_maxs.clear();
cdata->_got_minmax = false;
PTA_ushort::iterator vi;
for (vi = cdata->_vertices.begin(); vi != cdata->_vertices.end(); ++vi) {
(*vi) += offset;
qpGeomVertexRewriter index(cdata->_vertices, 0);
while (!index.is_at_end()) {
index.set_data1i(index.get_data1i() + offset);
}
}
@ -304,7 +326,7 @@ get_num_primitives() const {
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices.
return ((int)cdata->_vertices.size() / num_vertices_per_primitive);
return ((int)cdata->_vertices->get_num_vertices() / num_vertices_per_primitive);
}
}
@ -401,6 +423,38 @@ get_primitive_num_vertices(int n) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_min_vertex
// Access: Published
// Description: Returns the minimum vertex index number used by the
// nth primitive in this object.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_min_vertex(int n) const {
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_mins->get_num_vertices(), -1);
qpGeomVertexReader index(cdata->_mins, 0);
index.set_vertex(n);
return index.get_data1i();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_max_vertex
// Access: Published
// Description: Returns the maximum vertex index number used by the
// nth primitive in this object.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_max_vertex(int n) const {
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_maxs->get_num_vertices(), -1);
qpGeomVertexReader index(cdata->_maxs, 0);
index.set_vertex(n);
return index.get_data1i();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::decompose
// Access: Published
@ -446,9 +500,9 @@ rotate() const {
}
PStatTimer timer(_rotate_pcollector);
CPTA_ushort rotated_vertices = rotate_impl();
CPT(qpGeomVertexArrayData) rotated_vertices = rotate_impl();
if (rotated_vertices.is_null()) {
if (rotated_vertices == (qpGeomVertexArrayData *)NULL) {
return this;
}
@ -466,8 +520,8 @@ rotate() const {
int qpGeomPrimitive::
get_num_bytes() const {
CDReader cdata(_cycler);
return (cdata->_vertices.size() + cdata->_mins.size() + cdata->_maxs.size()) * sizeof(short) +
cdata->_ends.size() * sizeof(int) + sizeof(qpGeomPrimitive);
return (cdata->_vertices->get_data_size_bytes() +
cdata->_ends.size() * sizeof(int) + sizeof(qpGeomPrimitive));
}
////////////////////////////////////////////////////////////////////
@ -537,9 +591,14 @@ write(ostream &out, int indent_level) const {
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
////////////////////////////////////////////////////////////////////
PTA_ushort qpGeomPrimitive::
qpGeomVertexArrayData *qpGeomPrimitive::
modify_vertices() {
CDWriter cdata(_cycler);
if (cdata->_vertices->get_ref_count() > 1) {
cdata->_vertices = new qpGeomVertexArrayData(*cdata->_vertices);
}
cdata->_modified = qpGeom::get_next_modified();
cdata->_got_minmax = false;
return cdata->_vertices;
}
@ -552,9 +611,11 @@ modify_vertices() {
// the ends list with set_ends() at the same time.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_vertices(CPTA_ushort vertices) {
set_vertices(const qpGeomVertexArrayData *vertices) {
CDWriter cdata(_cycler);
cdata->_vertices = (PTA_ushort &)vertices;
cdata->_vertices = (qpGeomVertexArrayData *)vertices;
cdata->_modified = qpGeom::get_next_modified();
cdata->_got_minmax = false;
}
@ -573,6 +634,8 @@ set_vertices(CPTA_ushort vertices) {
PTA_int qpGeomPrimitive::
modify_ends() {
CDWriter cdata(_cycler);
cdata->_modified = qpGeom::get_next_modified();
cdata->_got_minmax = false;
return cdata->_ends;
}
@ -593,6 +656,8 @@ void qpGeomPrimitive::
set_ends(CPTA_int ends) {
CDWriter cdata(_cycler);
cdata->_ends = (PTA_int &)ends;
cdata->_modified = qpGeom::get_next_modified();
cdata->_got_minmax = false;
}
@ -782,11 +847,11 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
CDReader cdata(_cycler);
qpGeomVertexReader index(cdata->_vertices, 0);
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);
while (!index.is_at_end()) {
reader.set_vertex(index.get_data1i());
const LVecBase3f &vertex = reader.get_data3f();
if (found_any) {
@ -803,10 +868,8 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
}
}
} else {
PTA_ushort::const_iterator ii;
for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
int index = (int)(*ii);
reader.set_vertex(index);
while (!index.is_at_end()) {
reader.set_vertex(index.get_data1i());
LPoint3f vertex = mat.xform_point(reader.get_data3f());
if (found_any) {
@ -849,11 +912,11 @@ decompose_impl() const {
// Access: Protected, Virtual
// Description: The virtual implementation of rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomPrimitive::
CPT(qpGeomVertexArrayData) qpGeomPrimitive::
rotate_impl() const {
// The default implementation doesn't even try to do anything.
nassertr(false, CPTA_ushort());
return CPTA_ushort();
nassertr(false, NULL);
return NULL;
}
////////////////////////////////////////////////////////////////////
@ -866,7 +929,7 @@ rotate_impl() const {
// vertex that begins the new primitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
append_unused_vertices(PTA_ushort &, int) {
append_unused_vertices(qpGeomVertexArrayData *, int) {
}
////////////////////////////////////////////////////////////////////
@ -877,7 +940,7 @@ append_unused_vertices(PTA_ushort &, int) {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
recompute_minmax(qpGeomPrimitive::CDWriter &cdata) {
if (cdata->_vertices.empty()) {
if (cdata->_vertices->get_num_vertices() == 0) {
cdata->_min_vertex = 0;
cdata->_max_vertex = 0;
cdata->_mins.clear();
@ -886,55 +949,65 @@ recompute_minmax(qpGeomPrimitive::CDWriter &cdata) {
} else if (get_num_vertices_per_primitive() == 0) {
// This is a complex primitive type like a triangle strip; compute
// the minmax of each primitive (as well as the overall minmax).
cdata->_mins = PTA_ushort::empty_array(cdata->_ends.size());
cdata->_maxs = PTA_ushort::empty_array(cdata->_ends.size());
qpGeomVertexReader index(cdata->_vertices, 0);
cdata->_mins = new qpGeomVertexArrayData
(cdata->_vertices->get_array_format(), UH_unspecified);
cdata->_maxs = new qpGeomVertexArrayData
(cdata->_vertices->get_array_format(), UH_unspecified);
qpGeomVertexWriter mins(cdata->_mins, 0);
qpGeomVertexWriter maxs(cdata->_maxs, 0);
int pi = 0;
int vi = 0;
int num_vertices = (int)cdata->_vertices.size();
unsigned short vertex = cdata->_vertices[vi];
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = vertex;
cdata->_mins[pi] = vertex;
cdata->_max_vertex = vertex;
cdata->_maxs[pi] = vertex;
unsigned int min_prim = vertex;
unsigned int max_prim = vertex;
++vi;
while (vi < num_vertices) {
unsigned short vertex = cdata->_vertices[vi];
while (!index.is_at_end()) {
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = min(cdata->_min_vertex, vertex);
cdata->_max_vertex = max(cdata->_max_vertex, vertex);
if (vi == cdata->_ends[pi]) {
mins.add_data1i(min_prim);
maxs.add_data1i(max_prim);
min_prim = vertex;
max_prim = vertex;
++pi;
if (pi < (int)cdata->_ends.size()) {
cdata->_mins[pi] = vertex;
cdata->_maxs[pi] = vertex;
}
} else {
nassertv(pi < (int)cdata->_ends.size());
cdata->_mins[pi] = min(cdata->_mins[pi], vertex);
cdata->_maxs[pi] = max(cdata->_maxs[pi], vertex);
min_prim = min(min_prim, vertex);
max_prim = min(max_prim, vertex);
}
++vi;
}
mins.add_data1i(min_prim);
maxs.add_data1i(max_prim);
nassertv(mins.get_num_vertices() == cdata->_ends.size());
} else {
// This is a simple primitive type like a triangle; just compute
// the overall minmax.
PTA_ushort::const_iterator ii = cdata->_vertices.begin();
cdata->_min_vertex = (*ii);
cdata->_max_vertex = (*ii);
qpGeomVertexReader index(cdata->_vertices, 0);
cdata->_mins.clear();
cdata->_maxs.clear();
++ii;
while (ii != cdata->_vertices.end()) {
cdata->_min_vertex = min(cdata->_min_vertex, (*ii));
cdata->_max_vertex = max(cdata->_max_vertex, (*ii));
++ii;
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = vertex;
cdata->_max_vertex = vertex;
while (!index.is_at_end()) {
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = min(cdata->_min_vertex, vertex);
cdata->_max_vertex = max(cdata->_max_vertex, vertex);
}
}
@ -986,13 +1059,29 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
dg.add_uint8(_usage_hint);
dg.add_uint8(_shade_model);
dg.add_uint8(_index_type);
WRITE_PTA(manager, dg, IPD_ushort::write_datagram, _vertices);
manager->write_pointer(dg, _vertices);
WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
_vertices = DCAST(qpGeomVertexArrayData, p_list[pi++]);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::fillin
// Access: Public, Virtual
@ -1002,10 +1091,10 @@ write_datagram(BamWriter *manager, Datagram &dg) const {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
_usage_hint = (UsageHint)scan.get_uint8();
_shade_model = (ShadeModel)scan.get_uint8();
READ_PTA(manager, scan, IPD_ushort::read_datagram, _vertices);
_index_type = (NumericType)scan.get_uint8();
manager->read_pointer(scan);
READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
_modified = qpGeom::get_next_modified();

View File

@ -21,11 +21,11 @@
#include "pandabase.h"
#include "qpgeomEnums.h"
#include "qpgeomVertexArrayData.h"
#include "typedWritableReferenceCount.h"
#include "luse.h"
#include "updateSeq.h"
#include "pointerTo.h"
#include "pta_ushort.h"
#include "pta_int.h"
#include "pStatCollector.h"
#include "cycleData.h"
@ -63,6 +63,9 @@ class FactoryParams;
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomPrimitive : public TypedWritableReferenceCount, public qpGeomEnums {
protected:
qpGeomPrimitive();
PUBLISHED:
qpGeomPrimitive(UsageHint usage_hint);
qpGeomPrimitive(const qpGeomPrimitive &copy);
@ -79,6 +82,9 @@ PUBLISHED:
INLINE UsageHint get_usage_hint() const;
INLINE void set_usage_hint(UsageHint usage_hint);
INLINE NumericType get_index_type() const;
void set_index_type(NumericType index_type);
// The following published methods are provided for safe, high-level
// iteration through the vertices and sub-primitives within the
// GeomPrimitive class. These work correctly regardless of the
@ -87,7 +93,7 @@ PUBLISHED:
// composite primitive using these methods.
INLINE int get_num_vertices() const;
INLINE int get_vertex(int i) const;
int get_vertex(int i) const;
void add_vertex(int vertex);
void add_consecutive_vertices(int start, int num_vertices);
void add_next_vertices(int num_vertices);
@ -104,9 +110,9 @@ PUBLISHED:
INLINE int get_primitive_num_faces(int n) const;
INLINE int get_min_vertex() const;
INLINE int get_primitive_min_vertex(int n) const;
int get_primitive_min_vertex(int n) const;
INLINE int get_max_vertex() const;
INLINE int get_primitive_max_vertex(int n) const;
int get_primitive_max_vertex(int n) const;
CPT(qpGeomPrimitive) decompose() const;
CPT(qpGeomPrimitive) rotate() const;
@ -131,16 +137,19 @@ public:
// recommended that application-level code use the above interfaces
// instead.
INLINE CPTA_ushort get_vertices() const;
PTA_ushort modify_vertices();
void set_vertices(CPTA_ushort vertices);
INLINE const qpGeomVertexArrayData *get_vertices() const;
qpGeomVertexArrayData *modify_vertices();
void set_vertices(const qpGeomVertexArrayData *vertices);
INLINE int get_index_stride() const;
INLINE CPTA_uchar get_data() const;
INLINE CPTA_int get_ends() const;
PTA_int modify_ends();
void set_ends(CPTA_int ends);
INLINE CPTA_ushort get_mins() const;
INLINE CPTA_ushort get_maxs() const;
INLINE const qpGeomVertexArrayData *get_mins() const;
INLINE const qpGeomVertexArrayData *get_maxs() const;
virtual int get_num_vertices_per_primitive() const;
virtual int get_min_num_vertices_per_primitive() const;
@ -167,8 +176,9 @@ public:
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;
virtual CPTA_ushort rotate_impl() const;
virtual void append_unused_vertices(PTA_ushort &vertices, int vertex);
virtual CPT(qpGeomVertexArrayData) rotate_impl() const;
virtual void append_unused_vertices(qpGeomVertexArrayData *vertices,
int vertex);
private:
// A GeomPrimitive keeps a list (actually, a map) of all the
@ -186,14 +196,15 @@ private:
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual void fillin(DatagramIterator &scan, BamReader *manager);
UsageHint _usage_hint;
ShadeModel _shade_model;
PTA_ushort _vertices;
NumericType _index_type;
PT(qpGeomVertexArrayData) _vertices;
PTA_int _ends;
PTA_ushort _mins;
PTA_ushort _maxs;
PT(qpGeomVertexArrayData) _mins;
PT(qpGeomVertexArrayData) _maxs;
UpdateSeq _modified;
bool _got_minmax;

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "qpgeomTriangles.h"
#include "qpgeomVertexRewriter.h"
#include "pStatTimer.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -110,25 +111,31 @@ draw(GraphicsStateGuardianBase *gsg) const {
// Access: Protected, Virtual
// Description: The virtual implementation of do_rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomTriangles::
CPT(qpGeomVertexArrayData) qpGeomTriangles::
rotate_impl() const {
// To rotate triangles, we just move one vertex from the front to
// the back, or vice-versa; but we have to know what direction we're
// going.
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
ShadeModel shade_model = get_shade_model();
PTA_ushort new_vertices;
new_vertices.reserve(vertices.size());
PT(qpGeomVertexArrayData) new_vertices =
new qpGeomVertexArrayData(*vertices);
qpGeomVertexReader from(vertices, 0);
qpGeomVertexWriter to(new_vertices, 0);
int num_vertices = vertices->get_num_vertices();
switch (shade_model) {
case SM_flat_first_vertex:
// Move the first vertex to the end.
{
for (int begin = 0; begin < (int)vertices.size(); begin += 3) {
new_vertices.push_back(vertices[begin + 1]);
new_vertices.push_back(vertices[begin + 2]);
new_vertices.push_back(vertices[begin]);
for (int begin = 0; begin < num_vertices; begin += 3) {
from.set_vertex(begin + 1);
to.set_data1i(from.get_data1i());
to.set_data1i(from.get_data1i());
from.set_vertex(begin);
to.set_data1i(from.get_data1i());
}
}
break;
@ -136,10 +143,12 @@ rotate_impl() const {
case SM_flat_last_vertex:
// Move the last vertex to the front.
{
for (int begin = 0; begin < (int)vertices.size(); begin += 3) {
new_vertices.push_back(vertices[begin + 2]);
new_vertices.push_back(vertices[begin]);
new_vertices.push_back(vertices[begin + 1]);
for (int begin = 0; begin < num_vertices; begin += 3) {
from.set_vertex(begin + 2);
to.set_data1i(from.get_data1i());
from.set_vertex(begin);
to.set_data1i(from.get_data1i());
to.set_data1i(from.get_data1i());
}
}
break;
@ -149,7 +158,7 @@ rotate_impl() const {
nassertr(false, vertices);
}
nassertr(new_vertices.size() == vertices.size(), vertices);
nassertr(to.is_at_end(), NULL);
return new_vertices;
}

View File

@ -44,7 +44,7 @@ public:
virtual void draw(GraphicsStateGuardianBase *gsg) const;
protected:
virtual CPTA_ushort rotate_impl() const;
virtual CPT(qpGeomVertexArrayData) rotate_impl() const;
public:
static void register_with_read_factory();

View File

@ -18,6 +18,7 @@
#include "qpgeomTrifans.h"
#include "qpgeomTriangles.h"
#include "qpgeomVertexRewriter.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -119,33 +120,35 @@ CPT(qpGeomPrimitive) qpGeomTrifans::
decompose_impl() const {
PT(qpGeomTriangles) triangles = new qpGeomTriangles(get_usage_hint());
triangles->set_shade_model(get_shade_model());
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
qpGeomVertexReader index(vertices, 0);
CPTA_int ends = get_ends();
int num_vertices = vertices->get_num_vertices();
int vi = 0;
int li = 0;
while (li < (int)ends.size()) {
int end = ends[li];
nassertr(vi + 2 <= end, triangles.p());
nassertr(vi < (int)vertices.size(), this);
int v0 = vertices[vi];
int v0 = index.get_data1i();
++vi;
nassertr(vi < (int)vertices.size(), this);
int v1 = vertices[vi];
int v1 = index.get_data1i();
++vi;
while (vi < end) {
int v2 = index.get_data1i();
++vi;
triangles->add_vertex(v0);
triangles->add_vertex(v1);
triangles->add_vertex(vertices[vi]);
nassertr(vi < (int)vertices.size(), this);
v1 = vertices[vi];
triangles->add_vertex(v2);
nassertr(vi < num_vertices, this);
v1 = v2;
triangles->close_primitive();
++vi;
}
++li;
}
nassertr(vi == (int)vertices.size(), triangles.p());
nassertr(vi == num_vertices && index.is_at_end(), NULL);
return triangles.p();
}
@ -155,12 +158,12 @@ decompose_impl() const {
// Access: Protected, Virtual
// Description: The virtual implementation of do_rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomTrifans::
CPT(qpGeomVertexArrayData) qpGeomTrifans::
rotate_impl() const {
// Actually, we can't rotate fans without chaging the winding order.
// It's an error to define a flat shade model for a GeomTrifan.
nassertr(false, CPTA_ushort());
return CPTA_ushort();
nassertr(false, NULL);
return NULL;
}
////////////////////////////////////////////////////////////////////

View File

@ -44,7 +44,7 @@ public:
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;
virtual CPTA_ushort rotate_impl() const;
virtual CPT(qpGeomVertexArrayData) rotate_impl() const;
public:
static void register_with_read_factory();

View File

@ -18,6 +18,7 @@
#include "qpgeomTristrips.h"
#include "qpgeomTriangles.h"
#include "qpgeomVertexRewriter.h"
#include "pStatTimer.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -134,9 +135,12 @@ CPT(qpGeomPrimitive) qpGeomTristrips::
decompose_impl() const {
PT(qpGeomTriangles) triangles = new qpGeomTriangles(get_usage_hint());
triangles->set_shade_model(get_shade_model());
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
qpGeomVertexReader index(vertices, 0);
CPTA_int ends = get_ends();
int num_vertices = vertices->get_num_vertices();
// We need a slightly different algorithm for SM_flat_first_vertex
// than for SM_flat_last_vertex, to preserve the key vertex in the
// right place. The remaining shade models can use either
@ -149,35 +153,34 @@ decompose_impl() const {
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += 2;
index.set_vertex(vi);
int end = ends[li];
nassertr(vi + 2 <= end, triangles.p());
nassertr(vi < (int)vertices.size(), this);
int v0 = vertices[vi];
nassertr(vi + 2 <= end, NULL);
int v0 = index.get_data1i();
++vi;
nassertr(vi < (int)vertices.size(), this);
int v1 = vertices[vi];
int v1 = index.get_data1i();
++vi;
bool reversed = false;
while (vi < end) {
triangles->add_vertex(v0);
int v2 = index.get_data1i();
++vi;
if (reversed) {
triangles->add_vertex(vertices[vi]);
triangles->add_vertex(v2);
triangles->add_vertex(v1);
reversed = false;
} else {
triangles->add_vertex(v1);
triangles->add_vertex(vertices[vi]);
triangles->add_vertex(v2);
reversed = true;
}
v0 = v1;
nassertr(vi < (int)vertices.size(), this);
v1 = vertices[vi];
v1 = v2;
triangles->close_primitive();
++vi;
}
++li;
}
nassertr(vi == (int)vertices.size(), triangles.p());
nassertr(vi == num_vertices && index.is_at_end(), NULL);
} else {
// Preserve the last vertex of each component triangle as the
@ -187,13 +190,12 @@ decompose_impl() const {
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += 2;
index.set_vertex(vi);
int end = ends[li];
nassertr(vi + 2 <= end, triangles.p());
nassertr(vi < (int)vertices.size(), this);
int v0 = vertices[vi];
nassertr(vi + 2 <= end, NULL);
int v0 = index.get_data1i();
++vi;
nassertr(vi < (int)vertices.size(), this);
int v1 = vertices[vi];
int v1 = index.get_data1i();
++vi;
bool reversed = false;
while (vi < end) {
@ -206,16 +208,16 @@ decompose_impl() const {
triangles->add_vertex(v1);
reversed = true;
}
triangles->add_vertex(vertices[vi]);
v0 = v1;
nassertr(vi < (int)vertices.size(), this);
v1 = vertices[vi];
triangles->close_primitive();
int v2 = index.get_data1i();
++vi;
triangles->add_vertex(v2);
v0 = v1;
v1 = v2;
triangles->close_primitive();
}
++li;
}
nassertr(vi == (int)vertices.size(), triangles.p());
nassertr(vi == num_vertices && index.is_at_end(), NULL);
}
return triangles.p();
@ -226,21 +228,24 @@ decompose_impl() const {
// Access: Protected, Virtual
// Description: The virtual implementation of do_rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomTristrips::
CPT(qpGeomVertexArrayData) qpGeomTristrips::
rotate_impl() const {
// To rotate a triangle strip with an even number of vertices, we
// just reverse the vertices. But if we have an odd number of
// vertices, that doesn't work--in fact, nothing works (without also
// changing the winding order), so we don't allow an odd number of
// vertices in a flat-shaded tristrip.
CPTA_ushort vertices = get_vertices();
CPT(qpGeomVertexArrayData) vertices = get_vertices();
CPTA_int ends = get_ends();
PTA_ushort new_vertices;
new_vertices.reserve(vertices.size());
PT(qpGeomVertexArrayData) new_vertices =
new qpGeomVertexArrayData(*vertices);
qpGeomVertexReader from(vertices, 0);
qpGeomVertexWriter to(new_vertices, 0);
bool any_odd = false;
int begin = 0;
int last_added = 0;
CPTA_int::const_iterator ei;
for (ei = ends.begin(); ei != ends.end(); ++ei) {
int end = (*ei);
@ -248,27 +253,25 @@ rotate_impl() const {
if (begin != 0) {
// Copy in the unused vertices between tristrips.
new_vertices.push_back(new_vertices.back());
new_vertices.push_back(vertices[end - 1]);
to.set_data1i(last_added);
from.set_vertex(end - 1);
to.set_data1i(from.get_data1i());
begin += 2;
}
if ((num_vertices & 1) == 0) {
for (int vi = end - 1; vi >= begin; --vi) {
new_vertices.push_back(vertices[vi]);
}
} else {
any_odd = true;
// If this assertion is triggered, there was a triangle strip with
// an odd number of vertices, which is not allowed.
nassertr((num_vertices & 1) == 0, NULL);
for (int vi = end - 1; vi >= begin; --vi) {
from.set_vertex(vi);
last_added = from.get_data1i();
to.set_data1i(last_added);
}
begin = end;
}
nassertr(new_vertices.size() == vertices.size(), vertices);
// If this assertion is triggered, there was a triangle strip with
// an odd number of vertices and either SM_flat_first_vertex or
// SM_flat_last_vertex specified--which is not allowed.
nassertr(!any_odd, CPTA_ushort());
nassertr(to.is_at_end(), NULL);
return new_vertices;
}
@ -282,9 +285,16 @@ rotate_impl() const {
// vertex that begins the new primitive.
////////////////////////////////////////////////////////////////////
void qpGeomTristrips::
append_unused_vertices(PTA_ushort &vertices, int vertex) {
vertices.push_back(vertices.back());
vertices.push_back(vertex);
append_unused_vertices(qpGeomVertexArrayData *vertices, int vertex) {
qpGeomVertexReader from(vertices, 0);
from.set_vertex(from.get_num_vertices() - 1);
int prev = from.get_data1i();
qpGeomVertexWriter to(vertices, 0);
to.set_vertex(to.get_num_vertices());
to.add_data1i(prev);
to.add_data1i(vertex);
}
////////////////////////////////////////////////////////////////////

View File

@ -45,8 +45,9 @@ public:
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;
virtual CPTA_ushort rotate_impl() const;
virtual void append_unused_vertices(PTA_ushort &vertices, int vertex);
virtual CPT(qpGeomVertexArrayData) rotate_impl() const;
virtual void append_unused_vertices(qpGeomVertexArrayData *vertices,
int vertex);
public:
static void register_with_read_factory();

View File

@ -47,6 +47,10 @@ setup() {
_component_bytes = 2; // sizeof(PN_uint16)
break;
case NT_uint32:
_component_bytes = 4; // sizeof(PN_uint32)
break;
case NT_uint8:
_component_bytes = 1;
break;

View File

@ -25,15 +25,9 @@
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexReader::
qpGeomVertexReader(const qpGeomVertexData *vertex_data) :
_vertex_data(vertex_data),
_array(0),
_column(NULL),
_pointer(NULL),
_start_vertex(0),
_read_vertex(0),
_num_vertices(0),
_reader(NULL)
_vertex_data(vertex_data)
{
initialize();
}
////////////////////////////////////////////////////////////////////
@ -45,15 +39,9 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data) :
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexReader::
qpGeomVertexReader(const qpGeomVertexData *vertex_data, const string &name) :
_vertex_data(vertex_data),
_array(0),
_column(NULL),
_pointer(NULL),
_start_vertex(0),
_read_vertex(0),
_num_vertices(0),
_reader(NULL)
_vertex_data(vertex_data)
{
initialize();
set_column(name);
}
@ -67,18 +55,39 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data, const string &name) :
INLINE qpGeomVertexReader::
qpGeomVertexReader(const qpGeomVertexData *vertex_data,
const InternalName *name) :
_vertex_data(vertex_data),
_array(0),
_column(NULL),
_pointer(NULL),
_start_vertex(0),
_read_vertex(0),
_num_vertices(0),
_reader(NULL)
_vertex_data(vertex_data)
{
initialize();
set_column(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Constructor
// Access: Published
// Description: Constructs a new reader to process the vertices of
// the indicated array only.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexReader::
qpGeomVertexReader(const qpGeomVertexArrayData *array_data) :
_array_data(array_data)
{
initialize();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Constructor
// Access: Published
// Description: Constructs a new reader to process the vertices of
// the indicated array only.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexReader::
qpGeomVertexReader(const qpGeomVertexArrayData *array_data, int column) :
_array_data(array_data)
{
initialize();
set_column(column);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::Destructor
// Access: Published
@ -96,13 +105,25 @@ INLINE qpGeomVertexReader::
// Function: qpGeomVertexReader::get_vertex_data
// Access: Published
// Description: Returns the vertex data object that the
// reader is processing.
// reader is processing. This may return NULL if the
// reader was constructed with just an array pointer.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexData *qpGeomVertexReader::
get_vertex_data() const {
return _vertex_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::get_array_data
// Access: Published
// Description: Returns the particular array object that the
// reader is currently processing.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexArrayData *qpGeomVertexReader::
get_array_data() const {
return _array_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::set_column
// Access: Published
@ -118,8 +139,14 @@ get_vertex_data() const {
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexReader::
set_column(int column) {
return set_column(_vertex_data->get_format()->get_array_with(column),
_vertex_data->get_format()->get_column(column));
if (_vertex_data != (const qpGeomVertexData *)NULL) {
return set_column(_vertex_data->get_format()->get_array_with(column),
_vertex_data->get_format()->get_column(column));
}
if (_array_data != (const qpGeomVertexArrayData *)NULL) {
return set_column(0, _array_data->get_array_format()->get_column(column));
}
return false;
}
////////////////////////////////////////////////////////////////////
@ -155,8 +182,15 @@ set_column(const string &name) {
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexReader::
set_column(const InternalName *name) {
return set_column(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_column(name));
if (_vertex_data != (const qpGeomVertexData *)NULL) {
return set_column(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_column(name));
}
if (_array_data != (const qpGeomVertexArrayData *)NULL) {
return set_column(0, _array_data->get_array_format()->get_column(name));
}
return false;
}
////////////////////////////////////////////////////////////////////
@ -369,9 +403,11 @@ INLINE void qpGeomVertexReader::
set_pointer(int vertex) {
nassertv(_column != (qpGeomVertexColumn *)NULL);
_read_vertex = vertex;
CPT(qpGeomVertexArrayData) array_data = _vertex_data->get_array(_array);
_pointer = array_data->get_data() + _column->get_start() + _stride * _read_vertex;
_num_vertices = array_data->get_num_vertices();
if (_vertex_data != (const qpGeomVertexData *)NULL) {
_array_data = _vertex_data->get_array(_array);
}
_pointer = _array_data->get_data() + _column->get_start() + _stride * _read_vertex;
_num_vertices = _array_data->get_num_vertices();
}
////////////////////////////////////////////////////////////////////
@ -382,8 +418,14 @@ set_pointer(int vertex) {
////////////////////////////////////////////////////////////////////
INLINE const unsigned char *qpGeomVertexReader::
inc_pointer() {
#ifndef NDEBUG
nassertr(_read_vertex < _num_vertices, empty_buffer);
nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer);
if (_vertex_data != (const qpGeomVertexData *)NULL){
nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer);
} else {
nassertr(_pointer == _array_data->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer);
}
#endif
const unsigned char *orig_pointer = _pointer;
_pointer += _stride;

View File

@ -41,14 +41,24 @@ const unsigned char qpGeomVertexReader::empty_buffer[100] = { 0 };
////////////////////////////////////////////////////////////////////
bool qpGeomVertexReader::
set_column(int array, const qpGeomVertexColumn *column) {
if (_vertex_data == (const qpGeomVertexData *)NULL &&
_array_data == (const qpGeomVertexArrayData *)NULL) {
return false;
}
// Delete the old reader, if we've got one.
if (_reader != (Reader *)NULL) {
delete _reader;
_reader = NULL;
}
if (array < 0 || array >= _vertex_data->get_num_arrays() ||
column == (qpGeomVertexColumn *)NULL) {
int num_arrays = 1;
if (_vertex_data != (const qpGeomVertexData *)NULL) {
num_arrays = _vertex_data->get_num_arrays();
}
if (array < 0 || array >= num_arrays ||
column == (const qpGeomVertexColumn *)NULL) {
// Clear the data type.
_array = -1;
_column = NULL;
@ -61,7 +71,11 @@ set_column(int array, const qpGeomVertexColumn *column) {
} else {
_array = array;
_column = column;
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
if (_vertex_data != (const qpGeomVertexData *)NULL) {
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
} else {
_stride = _array_data->get_array_format()->get_stride();
}
set_pointer(_start_vertex);
@ -73,6 +87,22 @@ set_column(int array, const qpGeomVertexColumn *column) {
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::initialize
// Access: Private
// Description: Called only by the constructor.
////////////////////////////////////////////////////////////////////
void qpGeomVertexReader::
initialize() {
_array = 0;
_column = NULL;
_pointer = NULL;
_start_vertex = 0;
_read_vertex = 0;
_num_vertices = 0;
_reader = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexReader::make_reader
// Access: Private
@ -203,6 +233,9 @@ get_data1f(const unsigned char *pointer) {
case NT_uint16:
return *(const PN_uint16 *)pointer;
case NT_uint32:
return *(const PN_uint32 *)pointer;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -246,6 +279,13 @@ get_data2f(const unsigned char *pointer) {
}
return _v2;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_v2.set(pi[0], pi[1]);
}
return _v2;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -306,6 +346,13 @@ get_data3f(const unsigned char *pointer) {
}
return _v3;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_v3.set(pi[0], pi[1], pi[2]);
}
return _v3;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -375,6 +422,13 @@ get_data4f(const unsigned char *pointer) {
}
return _v4;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
}
return _v4;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -421,6 +475,9 @@ get_data1i(const unsigned char *pointer) {
case NT_uint16:
return *(const PN_uint16 *)pointer;
case NT_uint32:
return *(const PN_uint32 *)pointer;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -470,6 +527,14 @@ get_data2i(const unsigned char *pointer) {
}
return _i;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_i[0] = pi[0];
_i[1] = pi[1];
}
return _i;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -539,6 +604,15 @@ get_data3i(const unsigned char *pointer) {
}
return _i;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_i[0] = pi[0];
_i[1] = pi[1];
_i[2] = pi[2];
}
return _i;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -625,6 +699,16 @@ get_data4i(const unsigned char *pointer) {
}
return _i;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_i[0] = pi[0];
_i[1] = pi[1];
_i[2] = pi[2];
_i[3] = pi[3];
}
return _i;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -746,6 +830,13 @@ get_data4f(const unsigned char *pointer) {
}
return _v4;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
}
return _v4;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;
@ -817,6 +908,13 @@ get_data4f(const unsigned char *pointer) {
}
return _v4;
case NT_uint32:
{
const PN_uint32 *pi = (const PN_uint32 *)pointer;
_v4.set(pi[0], pi[1], pi[2], pi[3]);
}
return _v4;
case NT_packed_dcba:
{
PN_uint32 dword = *(const PN_uint32 *)pointer;

View File

@ -66,9 +66,13 @@ PUBLISHED:
const string &name);
INLINE qpGeomVertexReader(const qpGeomVertexData *vertex_data,
const InternalName *name);
INLINE qpGeomVertexReader(const qpGeomVertexArrayData *array_data);
INLINE qpGeomVertexReader(const qpGeomVertexArrayData *array_data,
int column);
INLINE ~qpGeomVertexReader();
INLINE const qpGeomVertexData *get_vertex_data() const;
INLINE const qpGeomVertexArrayData *get_array_data() const;
INLINE bool set_column(int column);
INLINE bool set_column(const string &name);
@ -99,11 +103,14 @@ PUBLISHED:
private:
class Reader;
void initialize();
INLINE void set_pointer(int vertex);
INLINE const unsigned char *inc_pointer();
Reader *make_reader() const;
CPT(qpGeomVertexData) _vertex_data;
CPT(qpGeomVertexArrayData) _array_data;
int _array;
const qpGeomVertexColumn *_column;
int _stride;

View File

@ -60,6 +60,33 @@ qpGeomVertexRewriter(qpGeomVertexData *vertex_data, const InternalName *name) :
set_column(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexRewriter::Constructor
// Access: Published
// Description: Constructs a new rewriter to process the vertices of
// the indicated array only.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexRewriter::
qpGeomVertexRewriter(qpGeomVertexArrayData *array_data) :
qpGeomVertexWriter(array_data),
qpGeomVertexReader(array_data)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexRewriter::Constructor
// Access: Published
// Description: Constructs a new rewriter to process the vertices of
// the indicated array only.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexRewriter::
qpGeomVertexRewriter(qpGeomVertexArrayData *array_data, int column) :
qpGeomVertexWriter(array_data),
qpGeomVertexReader(array_data)
{
set_column(column);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexRewriter::Destructor
// Access: Published
@ -82,6 +109,19 @@ get_vertex_data() const {
return qpGeomVertexWriter::get_vertex_data();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexRewriter::get_array_data
// Access: Published
// Description: Returns the particular array object that the
// rewriter is currently processing.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData *qpGeomVertexRewriter::
get_array_data() const {
nassertr(qpGeomVertexWriter::get_array_data() ==
qpGeomVertexReader::get_array_data(), NULL);
return qpGeomVertexWriter::get_array_data();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexRewriter::set_column
// Access: Published

View File

@ -49,9 +49,13 @@ PUBLISHED:
const string &name);
INLINE qpGeomVertexRewriter(qpGeomVertexData *vertex_data,
const InternalName *name);
INLINE qpGeomVertexRewriter(qpGeomVertexArrayData *array_data);
INLINE qpGeomVertexRewriter(qpGeomVertexArrayData *array_data,
int column);
INLINE ~qpGeomVertexRewriter();
INLINE qpGeomVertexData *get_vertex_data() const;
INLINE qpGeomVertexArrayData *get_array_data() const;
INLINE bool set_column(int column);
INLINE bool set_column(const string &name);

View File

@ -25,15 +25,9 @@
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexData *vertex_data) :
_vertex_data(vertex_data),
_array(0),
_column(NULL),
_pointer(NULL),
_start_vertex(0),
_write_vertex(0),
_num_vertices(0),
_writer(NULL)
_vertex_data(vertex_data)
{
initialize();
}
////////////////////////////////////////////////////////////////////
@ -45,15 +39,9 @@ qpGeomVertexWriter(qpGeomVertexData *vertex_data) :
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexData *vertex_data, const string &name) :
_vertex_data(vertex_data),
_array(0),
_column(NULL),
_pointer(NULL),
_start_vertex(0),
_write_vertex(0),
_num_vertices(0),
_writer(NULL)
_vertex_data(vertex_data)
{
initialize();
set_column(name);
}
@ -66,18 +54,39 @@ qpGeomVertexWriter(qpGeomVertexData *vertex_data, const string &name) :
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexData *vertex_data, const InternalName *name) :
_vertex_data(vertex_data),
_array(0),
_column(NULL),
_pointer(NULL),
_start_vertex(0),
_write_vertex(0),
_num_vertices(0),
_writer(NULL)
_vertex_data(vertex_data)
{
initialize();
set_column(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Constructor
// Access: Published
// Description: Constructs a new writer to process the vertices of
// the indicated array only.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexArrayData *array_data) :
_array_data(array_data)
{
initialize();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Constructor
// Access: Published
// Description: Constructs a new writer to process the vertices of
// the indicated array only.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexWriter::
qpGeomVertexWriter(qpGeomVertexArrayData *array_data, int column) :
_array_data(array_data)
{
initialize();
set_column(column);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::Destructor
// Access: Published
@ -95,13 +104,25 @@ INLINE qpGeomVertexWriter::
// Function: qpGeomVertexWriter::get_vertex_data
// Access: Published
// Description: Returns the vertex data object that the
// writer is processing.
// writer is processing. This may return NULL if the
// writer was constructed with just an array pointer.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexData *qpGeomVertexWriter::
get_vertex_data() const {
return _vertex_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::get_array_data
// Access: Published
// Description: Returns the particular array object that the
// writer is currently processing.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexArrayData *qpGeomVertexWriter::
get_array_data() const {
return _array_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::set_column
// Access: Published
@ -117,11 +138,14 @@ get_vertex_data() const {
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
set_column(int column) {
if (_vertex_data == (qpGeomVertexData *)NULL) {
return false;
if (_vertex_data != (qpGeomVertexData *)NULL) {
return set_column(_vertex_data->get_format()->get_array_with(column),
_vertex_data->get_format()->get_column(column));
}
return set_column(_vertex_data->get_format()->get_array_with(column),
_vertex_data->get_format()->get_column(column));
if (_array_data != (qpGeomVertexArrayData *)NULL) {
return set_column(0, _array_data->get_array_format()->get_column(column));
}
return false;
}
////////////////////////////////////////////////////////////////////
@ -157,11 +181,15 @@ set_column(const string &name) {
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexWriter::
set_column(const InternalName *name) {
if (_vertex_data == (qpGeomVertexData *)NULL) {
return false;
if (_vertex_data != (qpGeomVertexData *)NULL) {
return set_column(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_column(name));
}
return set_column(_vertex_data->get_format()->get_array_with(name),
_vertex_data->get_format()->get_column(name));
if (_array_data != (qpGeomVertexArrayData *)NULL) {
return set_column(0, _array_data->get_array_format()->get_column(name));
}
return false;
}
////////////////////////////////////////////////////////////////////
@ -679,9 +707,11 @@ INLINE void qpGeomVertexWriter::
set_pointer(int vertex) {
nassertv(_column != (qpGeomVertexColumn *)NULL);
_write_vertex = vertex;
PT(qpGeomVertexArrayData) array_data = _vertex_data->modify_array(_array);
_pointer = array_data->modify_data() + _column->get_start() + _stride * _write_vertex;
_num_vertices = array_data->get_num_vertices();
if (_vertex_data != (qpGeomVertexData *)NULL) {
_array_data = _vertex_data->modify_array(_array);
}
_pointer = _array_data->modify_data() + _column->get_start() + _stride * _write_vertex;
_num_vertices = _array_data->get_num_vertices();
}
////////////////////////////////////////////////////////////////////
@ -692,8 +722,14 @@ set_pointer(int vertex) {
////////////////////////////////////////////////////////////////////
INLINE unsigned char *qpGeomVertexWriter::
inc_pointer() {
#ifndef NDEBUG
nassertr(_write_vertex < _num_vertices, empty_buffer);
nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer);
if (_vertex_data != (qpGeomVertexData *)NULL){
nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer);
} else {
nassertr(_pointer == _array_data->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer);
}
#endif
unsigned char *orig_pointer = _pointer;
_pointer += _stride;
@ -713,7 +749,11 @@ 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()));
if (_vertex_data != (qpGeomVertexData *)NULL) {
_vertex_data->set_num_vertices(max(_write_vertex + 1, _vertex_data->get_num_vertices()));
} else {
_array_data->set_num_vertices(max(_write_vertex + 1, _array_data->get_num_vertices()));
}
set_pointer(_write_vertex);
}
return inc_pointer();

View File

@ -41,7 +41,8 @@ unsigned char qpGeomVertexWriter::empty_buffer[100] = { 0 };
////////////////////////////////////////////////////////////////////
bool qpGeomVertexWriter::
set_column(int array, const qpGeomVertexColumn *column) {
if (_vertex_data == (qpGeomVertexData *)NULL) {
if (_vertex_data == (qpGeomVertexData *)NULL &&
_array_data == (qpGeomVertexArrayData *)NULL) {
return false;
}
@ -51,8 +52,13 @@ set_column(int array, const qpGeomVertexColumn *column) {
_writer = NULL;
}
if (array < 0 || array >= _vertex_data->get_num_arrays() ||
column == (qpGeomVertexColumn *)NULL) {
int num_arrays = 1;
if (_vertex_data != (qpGeomVertexData *)NULL) {
num_arrays = _vertex_data->get_num_arrays();
}
if (array < 0 || array >= num_arrays ||
column == (const qpGeomVertexColumn *)NULL) {
// Clear the data type.
_array = -1;
_column = NULL;
@ -65,7 +71,11 @@ set_column(int array, const qpGeomVertexColumn *column) {
} else {
_array = array;
_column = column;
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
if (_vertex_data != (qpGeomVertexData *)NULL) {
_stride = _vertex_data->get_format()->get_array(_array)->get_stride();
} else {
_stride = _array_data->get_array_format()->get_stride();
}
set_pointer(_start_vertex);
@ -77,6 +87,22 @@ set_column(int array, const qpGeomVertexColumn *column) {
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::initialize
// Access: Private
// Description: Called only by the constructor.
////////////////////////////////////////////////////////////////////
void qpGeomVertexWriter::
initialize() {
_array = 0;
_column = NULL;
_pointer = NULL;
_start_vertex = 0;
_write_vertex = 0;
_num_vertices = 0;
_writer = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexWriter::make_writer
// Access: Private
@ -189,6 +215,10 @@ set_data1f(unsigned char *pointer, float data) {
*(PN_uint16 *)pointer = (unsigned int)data;
break;
case NT_uint32:
*(PN_uint32 *)pointer = (unsigned int)data;
break;
case NT_packed_dcba:
case NT_packed_dabc:
nassertv(false);
@ -241,6 +271,14 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) {
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)pointer;
pi[0] = (unsigned int)data[0];
pi[1] = (unsigned int)data[1];
}
break;
case NT_packed_dcba:
case NT_packed_dabc:
nassertv(false);
@ -300,6 +338,15 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) {
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)pointer;
pi[0] = (unsigned int)data[0];
pi[1] = (unsigned int)data[1];
pi[2] = (unsigned int)data[2];
}
break;
case NT_packed_dcba:
case NT_packed_dabc:
nassertv(false);
@ -361,6 +408,16 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
pi[3] = (unsigned int)data[3];
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)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 NT_packed_dcba:
maybe_scale_color(data);
@ -398,10 +455,17 @@ set_data1i(unsigned char *pointer, int a) {
switch (_column->get_numeric_type()) {
case NT_uint8:
*pointer = a;
nassertv((*pointer) == a);
break;
case NT_uint16:
*(PN_uint16 *)pointer = a;
nassertv(*(PN_uint16 *)pointer == a);
break;
case NT_uint32:
*(PN_uint32 *)pointer = a;
nassertv(*(PN_uint32 *)pointer == a);
break;
case NT_packed_dcba:
@ -455,6 +519,14 @@ set_data2i(unsigned char *pointer, int a, int b) {
pi[1] = b;
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)pointer;
pi[0] = a;
pi[1] = b;
}
break;
case NT_packed_dcba:
case NT_packed_dabc:
@ -513,6 +585,15 @@ set_data3i(unsigned char *pointer, int a, int b, int c) {
pi[2] = c;
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)pointer;
pi[0] = a;
pi[1] = b;
pi[2] = c;
}
break;
case NT_packed_dcba:
case NT_packed_dabc:
@ -574,6 +655,16 @@ set_data4i(unsigned char *pointer, int a, int b, int c, int d) {
pi[3] = d;
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)pointer;
pi[0] = a;
pi[1] = b;
pi[2] = c;
pi[3] = d;
}
break;
case NT_packed_dcba:
*(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(d, c, b, a);
@ -678,6 +769,16 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
pi[3] = (unsigned int)data[3];
}
break;
case NT_uint32:
{
PN_uint32 *pi = (PN_uint32 *)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 NT_packed_dcba:
maybe_scale_color(data);
@ -846,4 +947,5 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
void qpGeomVertexWriter::Writer_uint16_1::
set_data1i(unsigned char *pointer, int data) {
*(PN_uint16 *)pointer = data;
nassertv(*(PN_uint16 *)pointer == data);
}

View File

@ -79,9 +79,13 @@ PUBLISHED:
const string &name);
INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data,
const InternalName *name);
INLINE qpGeomVertexWriter(qpGeomVertexArrayData *array_data);
INLINE qpGeomVertexWriter(qpGeomVertexArrayData *array_data,
int column);
INLINE ~qpGeomVertexWriter();
INLINE qpGeomVertexData *get_vertex_data() const;
INLINE qpGeomVertexArrayData *get_array_data() const;
INLINE bool set_column(int column);
INLINE bool set_column(const string &name);
@ -134,12 +138,15 @@ PUBLISHED:
private:
class Writer;
void initialize();
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;
PT(qpGeomVertexArrayData) _array_data;
int _array;
const qpGeomVertexColumn *_column;
int _stride;

View File

@ -264,18 +264,18 @@ munge_points_to_quads(const CullTraverser *traverser) {
int num_points = primitive->get_max_vertex() + 1;
int num_vertices = primitive->get_num_vertices();
PointData *points = (PointData *)alloca(num_points * sizeof(PointData));
unsigned short *vertices = (unsigned short *)alloca(num_vertices * sizeof(unsigned short));
unsigned short *vertices_end = vertices + num_vertices;
unsigned int *vertices = (unsigned int *)alloca(num_vertices * sizeof(unsigned int));
unsigned int *vertices_end = vertices + num_vertices;
memcpy(vertices, primitive->get_vertices(),
num_vertices * sizeof(unsigned short));
unsigned short *vi;
qpGeomVertexReader index(primitive->get_vertices(), 0);
unsigned int *vi;
for (vi = vertices; vi != vertices_end; ++vi) {
// Get the point in eye-space coordinates.
vertex.set_vertex(*vi);
points[*vi]._eye = modelview.xform_point(vertex.get_data3f());
points[*vi]._dist = gsg->compute_distance_to(points[*vi]._eye);
unsigned int v = index.get_data1i();
(*vi) = v;
vertex.set_vertex(v);
points[v]._eye = modelview.xform_point(vertex.get_data3f());
points[v]._dist = gsg->compute_distance_to(points[v]._eye);
}
// Now sort the points in order from back-to-front so they will