connect-triangle-strips
This commit is contained in:
parent
160099a0ec
commit
08241a99ea
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ PUBLISHED:
|
|||
qpGeomLines(const qpGeomLines ©);
|
||||
virtual ~qpGeomLines();
|
||||
|
||||
public:
|
||||
virtual PT(qpGeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ PUBLISHED:
|
|||
qpGeomLinestrips(const qpGeomLinestrips ©);
|
||||
virtual ~qpGeomLinestrips();
|
||||
|
||||
public:
|
||||
virtual PT(qpGeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ PUBLISHED:
|
|||
qpGeomPoints(const qpGeomPoints ©);
|
||||
virtual ~qpGeomPoints();
|
||||
|
||||
public:
|
||||
virtual PT(qpGeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ PUBLISHED:
|
|||
qpGeomTriangles(const qpGeomTriangles ©);
|
||||
virtual ~qpGeomTriangles();
|
||||
|
||||
public:
|
||||
virtual PT(qpGeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ PUBLISHED:
|
|||
qpGeomTrifans(const qpGeomTrifans ©);
|
||||
virtual ~qpGeomTrifans();
|
||||
|
||||
public:
|
||||
virtual PT(qpGeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@ PUBLISHED:
|
|||
qpGeomTristrips(const qpGeomTristrips ©);
|
||||
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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue