connect-triangle-strips

This commit is contained in:
David Rose 2005-03-31 16:10:06 +00:00
parent 160099a0ec
commit 08241a99ea
19 changed files with 626 additions and 376 deletions

View File

@ -2711,6 +2711,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
draw_triangles(const qpGeomTriangles *primitive) {
_vertices_tri_pcollector.add_level(primitive->get_num_vertices());
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
nassertv(ibc != (IndexBufferContext *)NULL);
@ -2744,41 +2745,75 @@ void DXGraphicsStateGuardian8::
draw_tristrips(const qpGeomTristrips *primitive) {
int min_vertex = primitive->get_min_vertex();
int max_vertex = primitive->get_max_vertex();
CPTA_ushort vertices = primitive->get_flat_first_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());
// CPTA_ushort vertices = primitive->get_flat_first_vertices();
CPTA_ushort vertices = primitive->get_vertices();
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
nassertv(ibc != (IndexBufferContext *)NULL);
apply_index_buffer(ibc);
if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
// One long triangle strip, connected by the degenerate vertices
// that have already been set up within the primitive.
_vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
nassertv(ibc != (IndexBufferContext *)NULL);
apply_index_buffer(ibc);
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLESTRIP,
mins[i], maxs[i] - mins[i] + 1,
start, ends[i] - start - 2);
start = ends[i];
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
0, primitive->get_num_vertices() - 2);
} else {
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLESTRIP,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_vertices() - 2,
vertices, D3DFMT_INDEX16,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
}
} else {
CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
int stride = _vertex_data->get_format()->get_array(0)->get_stride();
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLESTRIP,
mins[i], maxs[i] - mins[i] + 1,
ends[i] - start - 2,
vertices + start, D3DFMT_INDEX16,
array_data, stride);
// 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());
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
nassertv(ibc != (IndexBufferContext *)NULL);
apply_index_buffer(ibc);
start = ends[i];
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_tristrip_pcollector.add_level(ends[i] - start);
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLESTRIP,
mins[i], maxs[i] - mins[i] + 1,
start, ends[i] - start - 2);
start = ends[i] + 2;
}
} else {
CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
int stride = _vertex_data->get_format()->get_array(0)->get_stride();
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_tristrip_pcollector.add_level(ends[i] - start);
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLESTRIP,
mins[i], maxs[i] - mins[i] + 1,
ends[i] - start - 2,
vertices + start, D3DFMT_INDEX16,
array_data, stride);
start = ends[i] + 2;
}
}
}
}

View File

@ -2247,22 +2247,36 @@ draw_triangles(const qpGeomTriangles *primitive) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_tristrips(const qpGeomTristrips *primitive) {
_vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
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());
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
if (connect_triangle_strips && _render_mode != RenderModeAttrib::M_wireframe) {
// One long triangle strip, connected by the degenerate vertices
// that have already been set up within the primitive.
_vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
_glDrawRangeElements(GL_TRIANGLE_STRIP,
mins[i], maxs[i], ends[i] - start,
GL_UNSIGNED_SHORT, client_pointer + start);
start = ends[i];
}
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, 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());
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);
start = ends[i] + 2;
}
}
report_my_gl_errors();
}
@ -2273,7 +2287,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_lines(const qpGeomLines *primitive) {
_vertices_tri_pcollector.add_level(primitive->get_num_vertices());
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
_glDrawRangeElements(GL_LINES,
@ -2292,7 +2306,7 @@ draw_lines(const qpGeomLines *primitive) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_points(const qpGeomPoints *primitive) {
_vertices_tri_pcollector.add_level(primitive->get_num_vertices());
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
const unsigned short *client_pointer = setup_primitive(primitive);
_glDrawRangeElements(GL_POINTS,

View File

@ -142,6 +142,15 @@ ConfigVariableBool matrix_palette
"because its support seems to be buggy in certain drivers "
"(ATI FireGL T2 8.103 in particular.)"));
ConfigVariableBool connect_triangle_strips
("connect-triangle-strips", true,
PRC_DESC("Set this true to set a batch of triangle strips to the graphics "
"card as one long triangle strip, connected by degenerate "
"triangles, or false to send them as separate triangle strips "
"with no degenerate triangles. In many cases, using one long "
"triangle strip can help performance by reducing the number "
"of separate graphics calls that have to be made."));
ConfigVariableBool use_qpgeom
("use-qpgeom", false,
PRC_DESC("A temporary variable while the experimental Geom rewrite is "

View File

@ -55,6 +55,7 @@ extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
extern EXPCL_PANDA ConfigVariableBool display_lists;
extern EXPCL_PANDA ConfigVariableBool hardware_animated_vertices;
extern EXPCL_PANDA ConfigVariableBool matrix_palette;
extern EXPCL_PANDA ConfigVariableBool connect_triangle_strips;
extern EXPCL_PANDA ConfigVariableBool use_qpgeom;

View File

@ -56,7 +56,7 @@ qpGeomLines::
////////////////////////////////////////////////////////////////////
// Function: qpGeomLines::make_copy
// Access: Published, Virtual
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomLines::
@ -66,7 +66,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomLines::get_primitive_type
// Access: Published, Virtual
// Access: Public, Virtual
// Description: Returns the fundamental rendering type of this
// primitive: whether it is points, lines, or polygons.
// This is used primarily to set up the appropriate
@ -80,7 +80,7 @@ get_primitive_type() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomLines::get_num_vertices_per_primitive
// Access: Published, Virtual
// Access: Public, Virtual
// Description: If the primitive type is a simple type in which all
// primitives have the same number of vertices, like
// lines, returns the number of vertices per

View File

@ -34,6 +34,7 @@ PUBLISHED:
qpGeomLines(const qpGeomLines &copy);
virtual ~qpGeomLines();
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;

View File

@ -57,7 +57,7 @@ qpGeomLinestrips::
////////////////////////////////////////////////////////////////////
// Function: qpGeomLinestrips::make_copy
// Access: Published, Virtual
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomLinestrips::
@ -67,7 +67,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomLinestrips::get_primitive_type
// Access: Published, Virtual
// Access: Public, Virtual
// Description: Returns the fundamental rendering type of this
// primitive: whether it is points, lines, or polygons.
// This is used primarily to set up the appropriate

View File

@ -34,6 +34,7 @@ PUBLISHED:
qpGeomLinestrips(const qpGeomLinestrips &copy);
virtual ~qpGeomLinestrips();
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;

View File

@ -56,7 +56,7 @@ qpGeomPoints::
////////////////////////////////////////////////////////////////////
// Function: qpGeomPoints::make_copy
// Access: Published, Virtual
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomPoints::
@ -66,7 +66,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomPoints::get_primitive_type
// Access: Published, Virtual
// Access: Public, Virtual
// Description: Returns the fundamental rendering type of this
// primitive: whether it is points, lines, or polygons.
// This is used primarily to set up the appropriate
@ -80,7 +80,7 @@ get_primitive_type() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomPoints::get_num_vertices_per_primitive
// Access: Published, Virtual
// Access: Public, Virtual
// Description: If the primitive type is a simple type in which all
// primitives have the same number of vertices, like
// points, returns the number of vertices per

View File

@ -34,6 +34,7 @@ PUBLISHED:
qpGeomPoints(const qpGeomPoints &copy);
virtual ~qpGeomPoints();
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;

View File

@ -94,137 +94,103 @@ get_vertex(int i) const {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_vertices
// Function: qpGeomPrimitive::get_num_faces
// Access: Published
// Description: Returns a const pointer to the vertex index array so
// application code can read it directly. Do not
// attempt to modify the returned array; use
// modify_vertices() or set_vertices() for this.
// Description: Returns the number of triangles or other fundamental
// type (such as line segments) represented by all the
// primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_vertices() const {
CDReader cdata(_cycler);
return cdata->_vertices;
}
INLINE int qpGeomPrimitive::
get_num_faces() const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_flat_first_vertices
// Access: Published
// Description: Returns a const pointer to the vertex index array,
// suitable for traversing for a renderer that expects
// the key vertex of each triangle in a flat-shaded
// model to be the triangle's first vertex (as DirectX
// does).
//
// The result of this is dependent on the value
// specified to set_shade_model(). If the shade model
// indicates flat_last_vertex, this will return the
// vertices rotated to bring them into first_vertex
// compliance; otherwise, it will be the unmodified
// result from get_vertices().
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_flat_first_vertices() const {
CDReader cdata(_cycler);
if (cdata->_shade_model == SM_flat_last_vertex) {
if (cdata->_rotated_vertices == (const ushort *)NULL) {
return ((qpGeomPrimitive *)this)->do_rotate(cdata);
}
return cdata->_rotated_vertices;
if (num_vertices_per_primitive == 0) {
int num_primitives = get_num_primitives();
int num_vertices = get_num_vertices();
int min_num_vertices_per_primitive = get_min_num_vertices_per_primitive();
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
return num_vertices - (num_primitives * (min_num_vertices_per_primitive - 1)) - ((num_primitives - 1) * num_unused_vertices_per_primitive);
} else {
return cdata->_vertices;
return get_num_primitives();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_flat_last_vertices
// Function: qpGeomPrimitive::get_primitive_num_faces
// Access: Published
// Description: Returns a const pointer to the vertex index array,
// suitable for traversing for a renderer that expects
// the key vertex of each triangle in a flat-shaded
// model to be the triangle's last vertex (as OpenGL
// does).
//
// The result of this is dependent on the value
// specified to set_shade_model(). If the shade model
// indicates flat_first_vertex, this will return the
// vertices rotated to bring them into last_vertex
// compliance; otherwise, it will be the unmodified
// result from get_vertices().
// Description: Returns the number of triangles or other fundamental
// type (such as line segments) represented by the nth
// primitive in this object.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_flat_last_vertices() const {
CDReader cdata(_cycler);
if (cdata->_shade_model == SM_flat_first_vertex) {
if (cdata->_rotated_vertices == (const ushort *)NULL) {
return ((qpGeomPrimitive *)this)->do_rotate(cdata);
}
return cdata->_rotated_vertices;
INLINE int qpGeomPrimitive::
get_primitive_num_faces(int n) const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
if (num_vertices_per_primitive == 0) {
return get_primitive_num_vertices(n) - get_min_num_vertices_per_primitive() + 1;
} else {
return cdata->_vertices;
return 1;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_ends
// Function: qpGeomPrimitive::get_min_vertex
// Access: Published
// Description: Returns a const pointer to the primitive ends
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_ends() or set_ends() for this.
//
// Note that simple primitive types, like triangles, do
// not have a ends array: since all the primitives
// have the same number of vertices, it is not needed.
// Description: Returns the minimum vertex index number used by all
// the primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE CPTA_int qpGeomPrimitive::
get_ends() const {
CDReader cdata(_cycler);
return cdata->_ends;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_mins
// Access: Published
// Description: Returns a const pointer to the primitive mins
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_mins() or set_mins() for this.
//
// Note that simple primitive types, like triangles, do
// not have a mins array.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_mins() const {
INLINE int qpGeomPrimitive::
get_min_vertex() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
CDWriter cdataw(((qpGeomPrimitive *)this)->_cycler, cdata);
((qpGeomPrimitive *)this)->recompute_minmax(cdataw);
return cdataw->_mins;
return cdataw->_min_vertex;
}
return cdata->_mins;
return cdata->_min_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_maxs
// Function: qpGeomPrimitive::get_primitive_min_vertex
// Access: Published
// Description: Returns a const pointer to the primitive maxs
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_maxs() or set_maxs() for this.
//
// Note that simple primitive types, like triangles, do
// not have a maxs array.
// Description: Returns the minimum vertex index number used by the
// nth primitive in this object.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_maxs() const {
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
// Description: Returns the maximum vertex index number used by all
// the primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_max_vertex() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
CDWriter cdataw(((qpGeomPrimitive *)this)->_cycler, cdata);
((qpGeomPrimitive *)this)->recompute_minmax(cdataw);
return cdataw->_maxs;
return cdataw->_max_vertex;
}
return cdata->_maxs;
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];
}
////////////////////////////////////////////////////////////////////
@ -253,74 +219,137 @@ get_modified() const {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_min_vertex
// Access: Published
// Description: Returns the minimum vertex index number used by the
// primitives in this object.
// Function: qpGeomPrimitive::get_vertices
// Access: Public
// Description: Returns a const pointer to the vertex index array so
// application code can read it directly. Do not
// attempt to modify the returned array; use
// modify_vertices() or set_vertices() for this.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_min_vertex() const {
INLINE CPTA_ushort qpGeomPrimitive::
get_vertices() const {
CDReader cdata(_cycler);
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_flat_first_vertices
// Access: Public
// Description: Returns a const pointer to the vertex index array,
// suitable for traversing for a renderer that expects
// the key vertex of each triangle in a flat-shaded
// model to be the triangle's first vertex (as DirectX
// does).
//
// The result of this is dependent on the value
// specified to set_shade_model(). If the shade model
// indicates flat_last_vertex, this will return the
// vertices rotated to bring them into first_vertex
// compliance; otherwise, it will be the unmodified
// result from get_vertices().
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_flat_first_vertices() const {
CDReader cdata(_cycler);
if (cdata->_shade_model == SM_flat_last_vertex) {
if (cdata->_rotated_vertices == (const ushort *)NULL) {
return ((qpGeomPrimitive *)this)->do_rotate(cdata);
}
return cdata->_rotated_vertices;
} else {
return cdata->_vertices;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_flat_last_vertices
// Access: Public
// Description: Returns a const pointer to the vertex index array,
// suitable for traversing for a renderer that expects
// the key vertex of each triangle in a flat-shaded
// model to be the triangle's last vertex (as OpenGL
// does).
//
// The result of this is dependent on the value
// specified to set_shade_model(). If the shade model
// indicates flat_first_vertex, this will return the
// vertices rotated to bring them into last_vertex
// compliance; otherwise, it will be the unmodified
// result from get_vertices().
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_flat_last_vertices() const {
CDReader cdata(_cycler);
if (cdata->_shade_model == SM_flat_first_vertex) {
if (cdata->_rotated_vertices == (const ushort *)NULL) {
return ((qpGeomPrimitive *)this)->do_rotate(cdata);
}
return cdata->_rotated_vertices;
} else {
return cdata->_vertices;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_ends
// Access: Public
// Description: Returns a const pointer to the primitive ends
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_ends() or set_ends() for this.
//
// Note that simple primitive types, like triangles, do
// not have a ends array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
INLINE CPTA_int qpGeomPrimitive::
get_ends() const {
CDReader cdata(_cycler);
return cdata->_ends;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_mins
// Access: Public
// Description: Returns a const pointer to the primitive mins
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_mins() or set_mins() for this.
//
// Note that simple primitive types, like triangles, do
// not have a mins array.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_mins() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
CDWriter cdataw(((qpGeomPrimitive *)this)->_cycler, cdata);
((qpGeomPrimitive *)this)->recompute_minmax(cdataw);
return cdataw->_min_vertex;
return cdataw->_mins;
}
return cdata->_min_vertex;
return cdata->_mins;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_min_vertex
// Access: Published
// Description: Returns the minimum vertex index number used by the
// ith primitive in this object.
// Function: qpGeomPrimitive::get_maxs
// Access: Public
// Description: Returns a const pointer to the primitive maxs
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_maxs() or set_maxs() for this.
//
// Note that simple primitive types, like triangles, do
// not have a maxs array.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_min_vertex(int i) const {
CPTA_ushort mins = get_mins();
nassertr(i >= 0 && i < (int)mins.size(), -1);
return mins[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_max_vertex
// Access: Published
// Description: Returns the maximum vertex index number used by the
// primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_max_vertex() const {
INLINE CPTA_ushort qpGeomPrimitive::
get_maxs() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
CDWriter cdataw(((qpGeomPrimitive *)this)->_cycler, cdata);
((qpGeomPrimitive *)this)->recompute_minmax(cdataw);
return cdataw->_max_vertex;
return cdataw->_maxs;
}
return cdata->_max_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_max_vertex
// Access: Published
// Description: Returns the maximum vertex index number used by the
// ith primitive in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_max_vertex(int i) const {
CPTA_ushort maxs = get_maxs();
nassertr(i >= 0 && i < (int)maxs.size(), -1);
return maxs[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_end
// Access: Published
// Description: Returns the element within the _vertices list at which
// the ith primitive ends.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_primitive_end(int i) const {
return get_primitive_start(i + 1);
return cdata->_maxs;
}
////////////////////////////////////////////////////////////////////

View File

@ -98,6 +98,15 @@ add_vertex(int vertex) {
clear_cache();
CDWriter cdata(_cycler);
int num_primitives = get_num_primitives();
if (num_primitives > 0 &&
cdata->_vertices.size() == 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);
cdata->_rotated_vertices.clear();
@ -166,9 +175,10 @@ add_consecutive_vertices(int start, int num_vertices) {
// Access: Published
// Description: Indicates that the previous n calls to add_vertex(),
// since the last call to close_primitive(), have fully
// defined a new primitive.
// defined a new primitive. Returns true if successful,
// false otherwise.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
bool qpGeomPrimitive::
close_primitive() {
clear_cache();
int num_vertices_per_primitive = get_num_vertices_per_primitive();
@ -183,22 +193,35 @@ close_primitive() {
num_added = (int)cdata->_vertices.size();
} else {
num_added = (int)cdata->_vertices.size() - cdata->_ends.back();
num_added -= get_num_unused_vertices_per_primitive();
}
nassertv(num_added >= get_min_num_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) {
nassertv((cdata->_mins.size() == cdata->_ends.size()) &&
(cdata->_maxs.size() == cdata->_ends.size()));
nassertd((cdata->_mins.size() == cdata->_ends.size()) &&
(cdata->_maxs.size() == cdata->_ends.size())) {
cdata->_got_minmax = false;
}
}
#endif
} else {
#ifndef NDEBUG
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices. Assert that we added the
// correct number of vertices.
nassertv((int)cdata->_vertices.size() % num_vertices_per_primitive == 0);
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();
nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0, false)
#endif
}
return true;
}
////////////////////////////////////////////////////////////////////
@ -219,121 +242,6 @@ clear_vertices() {
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::modify_vertices
// Access: Published
// Description: Returns a modifiable pointer to the vertex index
// list, so application code can directly fiddle with
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
////////////////////////////////////////////////////////////////////
PTA_ushort qpGeomPrimitive::
modify_vertices() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_vertices
// Access: Published
// Description: Completely replaces the vertex index list with a new
// table. Chances are good that you should also replace
// the ends list with set_ends() at the same time.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_vertices(CPTA_ushort vertices) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_vertices = (PTA_ushort &)vertices;
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::modify_ends
// Access: Published
// Description: Returns a modifiable pointer to the primitive ends
// array, so application code can directly fiddle with
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
//
// Note that simple primitive types, like triangles, do
// not have a ends array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
PTA_int qpGeomPrimitive::
modify_ends() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
return cdata->_ends;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_ends
// Access: Published
// Description: Completely replaces the primitive ends array with
// a new table. Chances are good that you should also
// replace the vertices list with set_vertices() at the
// same time.
//
// Note that simple primitive types, like triangles, do
// not have a ends array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_ends(CPTA_int ends) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_ends = (PTA_int &)ends;
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_bytes
// Access: Published
// Description: Returns the number of bytes consumed by the primitive
// and its index table(s).
////////////////////////////////////////////////////////////////////
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);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_vertices_per_primitive
// Access: Published, Virtual
// Description: If the primitive type is a simple type in which all
// primitives have the same number of vertices, like
// triangles, returns the number of vertices per
// primitive. If the primitive type is a more complex
// type in which different primitives might have
// different numbers of vertices, for instance a
// triangle strip, returns 0.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_num_vertices_per_primitive() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_min_num_vertices_per_primitive
// Access: Published, Virtual
// Description: Returns the minimum number of vertices that must be
// added before close_primitive() may legally be called.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_min_num_vertices_per_primitive() const {
return 3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_primitives
// Access: Published
@ -362,56 +270,86 @@ get_num_primitives() const {
// Function: qpGeomPrimitive::get_primitive_start
// Access: Published
// Description: Returns the element within the _vertices list at which
// the ith primitive starts.
// the nth primitive starts.
//
// If i is one more than the highest valid primitive
// vertex, the return value will be one more than the
// last valid vertex. Thus, it is always true that the
// vertices used by a particular primitive i are the set
// get_primitive_start(i) <= vi < get_primitive_start(i
// + 1).
// last valid vertex. Thus, it is generally true that
// the vertices used by a particular primitive i are the
// set get_primitive_start(n) <= vi <
// get_primitive_start(n + 1) (although this range also
// includes the unused vertices between primitives).
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_start(int i) const {
get_primitive_start(int n) const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
CDReader cdata(_cycler);
nassertr(n >= 0 && n <= (int)cdata->_ends.size(), -1);
if (n == 0) {
return 0;
} else {
return cdata->_ends[n - 1] + num_unused_vertices_per_primitive;
}
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices.
return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_end
// Access: Published
// Description: Returns the element within the _vertices list at which
// the nth primitive ends. This is one past the last
// valid element for the nth primitive.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_end(int n) const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
CDReader cdata(_cycler);
nassertr(i >= 0 && i <= (int)cdata->_ends.size(), -1);
if (i == 0) {
return 0;
} else {
return cdata->_ends[i - 1];
}
nassertr(n >= 0 && n < (int)cdata->_ends.size(), -1);
return cdata->_ends[n];
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices.
return i * num_vertices_per_primitive;
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_num_vertices
// Access: Published
// Description: Returns the number of vertices used by the ith
// primitive.
// Description: Returns the number of vertices used by the nth
// primitive. This is the same thing as
// get_primitive_end(n) - get_primitive_start(n).
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_num_vertices(int i) const {
get_primitive_num_vertices(int n) const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
CDReader cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_ends.size(), 0);
if (i == 0) {
nassertr(n >= 0 && n < (int)cdata->_ends.size(), 0);
if (n == 0) {
return cdata->_ends[0];
} else {
return cdata->_ends[i] - cdata->_ends[i - 1];
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
}
} else {
@ -482,6 +420,19 @@ decompose() const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_bytes
// Access: Published
// Description: Returns the number of bytes consumed by the primitive
// and its index table(s).
////////////////////////////////////////////////////////////////////
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);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::output
// Access: Published, Virtual
@ -503,21 +454,149 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< get_type() << ":\n";
int num_primitives = get_num_primitives();
for (int i = 0; i < num_primitives; i++) {
int num_vertices = get_num_vertices();
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
for (int i = 0; i < num_primitives; ++i) {
indent(out, indent_level + 2)
<< "[";
int begin = get_primitive_start(i);
int end = get_primitive_start(i + 1);
int end = get_primitive_end(i);
for (int vi = begin; vi < end; vi++) {
out << " " << get_vertex(vi);
}
out << " ]\n";
out << " ]";
if (end < num_vertices) {
for (int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
if (end + ui < num_vertices) {
out << " " << get_vertex(end + ui);
} else {
out << " ?";
}
}
}
out << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::modify_vertices
// Access: Public
// Description: Returns a modifiable pointer to the vertex index
// list, so application code can directly fiddle with
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
////////////////////////////////////////////////////////////////////
PTA_ushort qpGeomPrimitive::
modify_vertices() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_vertices
// Access: Public
// Description: Completely replaces the vertex index list with a new
// table. Chances are good that you should also replace
// the ends list with set_ends() at the same time.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_vertices(CPTA_ushort vertices) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_vertices = (PTA_ushort &)vertices;
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::modify_ends
// Access: Public
// Description: Returns a modifiable pointer to the primitive ends
// array, so application code can directly fiddle with
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
//
// Note that simple primitive types, like triangles, do
// not have a ends array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
PTA_int qpGeomPrimitive::
modify_ends() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
return cdata->_ends;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_ends
// Access: Public
// Description: Completely replaces the primitive ends array with
// a new table. Chances are good that you should also
// replace the vertices list with set_vertices() at the
// same time.
//
// Note that simple primitive types, like triangles, do
// not have a ends array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_ends(CPTA_int ends) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_ends = (PTA_int &)ends;
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_vertices_per_primitive
// Access: Public, Virtual
// Description: If the primitive type is a simple type in which all
// primitives have the same number of vertices, like
// triangles, returns the number of vertices per
// primitive. If the primitive type is a more complex
// type in which different primitives might have
// different numbers of vertices, for instance a
// triangle strip, returns 0.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_num_vertices_per_primitive() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_min_num_vertices_per_primitive
// Access: Public, Virtual
// Description: Returns the minimum number of vertices that must be
// added before close_primitive() may legally be called.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_min_num_vertices_per_primitive() const {
return 3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_unused_vertices_per_primitive
// Access: Public, Virtual
// Description: Returns the number of vertices that are added between
// primitives that aren't, strictly speaking, part of
// the primitives themselves. This is used, for
// instance, to define degenerate triangles to connect
// otherwise disconnected triangle strips.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_num_unused_vertices_per_primitive() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::clear_cache
// Access: Published
// Access: Public
// Description: Removes all of the previously-cached results of
// decompose().
////////////////////////////////////////////////////////////////////
@ -539,7 +618,7 @@ clear_cache() {
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::prepare
// Access: Published
// Access: Public
// Description: Indicates that the data should be enqueued to be
// prepared in the indicated prepared_objects at the
// beginning of the next frame. This will ensure the
@ -756,6 +835,19 @@ rotate_impl() const {
return get_vertices();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::append_unused_vertices
// Access: Protected, Virtual
// Description: Called when a new primitive is begun (other than the
// first primitive), this should add some degenerate
// vertices between primitives, if the primitive type
// requires that. The second parameter is the first
// vertex that begins the new primitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
append_unused_vertices(PTA_ushort &, int) {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::do_rotate
// Access: Private

View File

@ -105,13 +105,53 @@ PUBLISHED:
INLINE ShadeModel get_shade_model() const;
INLINE void set_shade_model(ShadeModel shade_model);
// 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
// primitive type and without depending on knowledge about the way
// primitives' lengths are encoded. You can also safely build up a
// composite primitive using these methods.
INLINE int get_num_vertices() const;
INLINE int get_vertex(int i) const;
void add_vertex(int vertex);
void add_consecutive_vertices(int start, int num_vertices);
void close_primitive();
bool close_primitive();
void clear_vertices();
int get_num_primitives() const;
int get_primitive_start(int n) const;
int get_primitive_end(int n) const;
int get_primitive_num_vertices(int n) const;
INLINE int get_num_faces() const;
INLINE int get_primitive_num_faces(int n) const;
INLINE int get_min_vertex() const;
INLINE int get_primitive_min_vertex(int n) const;
INLINE int get_max_vertex() const;
INLINE int get_primitive_max_vertex(int n) const;
CPT(qpGeomPrimitive) decompose() const;
int get_num_bytes() const;
INLINE int get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
public:
// These public methods are not intended for high-level usage. They
// are public so that C++ code that absolutely needs fast access to
// the primitive data can get to it, but using them requires
// knowledge about how the component primitives are encoded within
// the GeomPrimitive class, and it's easy to screw something up.
// Also, if too many code samples depend on this internal knowledge,
// it may make it difficult to extend this class later. It is
// recommended that application-level code use the above interfaces
// instead.
INLINE CPTA_ushort get_vertices() const;
INLINE CPTA_ushort get_flat_first_vertices() const;
INLINE CPTA_ushort get_flat_last_vertices() const;
@ -125,29 +165,11 @@ PUBLISHED:
INLINE CPTA_ushort get_mins() const;
INLINE CPTA_ushort get_maxs() const;
int get_num_bytes() const;
INLINE int get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
INLINE int get_min_vertex() const;
INLINE int get_min_vertex(int i) const;
INLINE int get_max_vertex() const;
INLINE int get_max_vertex(int i) const;
virtual int get_num_vertices_per_primitive() const;
virtual int get_min_num_vertices_per_primitive() const;
int get_num_primitives() const;
int get_primitive_start(int i) const;
INLINE int get_primitive_end(int i) const;
int get_primitive_num_vertices(int i) const;
CPT(qpGeomPrimitive) decompose() const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
virtual int get_num_unused_vertices_per_primitive() const;
void clear_cache();
void prepare(PreparedGraphicsObjects *prepared_objects);
public:
@ -170,6 +192,7 @@ public:
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;
virtual CPTA_ushort rotate_impl() const;
virtual void append_unused_vertices(PTA_ushort &vertices, int vertex);
protected:
static PStatCollector _rotate_pcollector;
@ -195,7 +218,6 @@ private:
CPT(qpGeomPrimitive) _decomposed;
};
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:

View File

@ -56,7 +56,7 @@ qpGeomTriangles::
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::make_copy
// Access: Published, Virtual
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomTriangles::
@ -66,7 +66,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::get_primitive_type
// Access: Published, Virtual
// Access: Public, Virtual
// Description: Returns the fundamental rendering type of this
// primitive: whether it is points, lines, or polygons.
// This is used primarily to set up the appropriate
@ -80,7 +80,7 @@ get_primitive_type() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::get_num_vertices_per_primitive
// Access: Published, Virtual
// Access: Public, Virtual
// Description: If the primitive type is a simple type in which all
// primitives have the same number of vertices, like
// triangles, returns the number of vertices per

View File

@ -34,6 +34,7 @@ PUBLISHED:
qpGeomTriangles(const qpGeomTriangles &copy);
virtual ~qpGeomTriangles();
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;

View File

@ -56,7 +56,7 @@ qpGeomTrifans::
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::make_copy
// Access: Published, Virtual
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomTrifans::
@ -66,7 +66,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::get_primitive_type
// Access: Published, Virtual
// Access: Public, Virtual
// Description: Returns the fundamental rendering type of this
// primitive: whether it is points, lines, or polygons.
// This is used primarily to set up the appropriate

View File

@ -34,6 +34,7 @@ PUBLISHED:
qpGeomTrifans(const qpGeomTrifans &copy);
virtual ~qpGeomTrifans();
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;

View File

@ -57,7 +57,7 @@ qpGeomTristrips::
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::make_copy
// Access: Published, Virtual
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomTristrips::
@ -67,7 +67,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::get_primitive_type
// Access: Published, Virtual
// Access: Public, Virtual
// Description: Returns the fundamental rendering type of this
// primitive: whether it is points, lines, or polygons.
// This is used primarily to set up the appropriate
@ -79,6 +79,20 @@ get_primitive_type() const {
return PT_polygons;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::get_num_unused_vertices_per_primitive
// Access: Public, Virtual
// Description: Returns the number of vertices that are added between
// primitives that aren't, strictly speaking, part of
// the primitives themselves. This is used, for
// instance, to define degenerate triangles to connect
// otherwise disconnected triangle strips.
////////////////////////////////////////////////////////////////////
int qpGeomTristrips::
get_num_unused_vertices_per_primitive() const {
return 2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::draw
// Access: Public, Virtual
@ -118,9 +132,11 @@ decompose_impl() const {
if (get_shade_model() == SM_flat_first_vertex) {
// Preserve the first vertex of each component triangle as the
// first vertex of each generated triangle.
int vi = 0;
int vi = -2;
int li = 0;
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += 2;
int end = ends[li];
nassertr(vi + 2 <= end, triangles.p());
nassertr(vi < (int)vertices.size(), this);
@ -154,9 +170,11 @@ decompose_impl() const {
} else {
// Preserve the last vertex of each component triangle as the
// last vertex of each generated triangle.
int vi = 0;
int vi = -2;
int li = 0;
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += 2;
int end = ends[li];
nassertr(vi + 2 <= end, triangles.p());
nassertr(vi < (int)vertices.size(), this);
@ -216,6 +234,13 @@ rotate_impl() const {
int end = (*ei);
int num_vertices = end - begin;
if (begin != 0) {
// Copy in the unused vertices between tristrips.
new_vertices.push_back(new_vertices.back());
new_vertices.push_back(vertices[end - 1]);
begin += 2;
}
if ((num_vertices & 1) == 0) {
for (int vi = end - 1; vi >= begin; --vi) {
new_vertices.push_back(vertices[vi]);
@ -235,6 +260,21 @@ rotate_impl() const {
return new_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::append_unused_vertices
// Access: Protected, Virtual
// Description: Called when a new primitive is begun (other than the
// first primitive), this should add some degenerate
// vertices between primitives, if the primitive type
// requires that. The second parameter is the first
// 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);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::register_with_read_factory
// Access: Public, Static

View File

@ -34,8 +34,10 @@ PUBLISHED:
qpGeomTristrips(const qpGeomTristrips &copy);
virtual ~qpGeomTristrips();
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;
virtual int get_num_unused_vertices_per_primitive() const;
public:
virtual void draw(GraphicsStateGuardianBase *gsg) const;
@ -43,6 +45,7 @@ public:
protected:
virtual CPT(qpGeomPrimitive) decompose_impl() const;
virtual CPTA_ushort rotate_impl() const;
virtual void append_unused_vertices(PTA_ushort &vertices, int vertex);
public:
static void register_with_read_factory();