diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 20d1bc76f6..079bbaa250 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -55,6 +55,7 @@ #include "qpgeomTristrips.h" #include "qpgeomTrifans.h" #include "qpgeomLines.h" +#include "qpGeomVertexReader.h" #include "dxGeomMunger8.h" #include "config_gobj.h" #include "dxVertexBufferContext8.h" @@ -2747,13 +2748,15 @@ draw_triangles(const qpGeomTriangles *primitive) { 0, primitive->get_num_primitives()); } else { + D3DFORMAT index_type = get_index_type(primitive->get_index_type()); + _pD3DDevice->DrawIndexedPrimitiveUP (D3DPT_TRIANGLELIST, primitive->get_min_vertex(), primitive->get_max_vertex() - primitive->get_min_vertex() + 1, primitive->get_num_primitives(), primitive->get_vertices(), - D3DFMT_INDEX16, + index_type, _vertex_data->get_array(0)->get_data(), _vertex_data->get_format()->get_array(0)->get_stride()); } @@ -2768,6 +2771,7 @@ void DXGraphicsStateGuardian8:: draw_tristrips(const qpGeomTristrips *primitive) { int min_vertex = primitive->get_min_vertex(); int max_vertex = primitive->get_max_vertex(); + D3DFORMAT index_type = get_index_type(primitive->get_index_type()); if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) { // One long triangle strip, connected by the degenerate vertices @@ -2788,7 +2792,7 @@ draw_tristrips(const qpGeomTristrips *primitive) { (D3DPT_TRIANGLESTRIP, min_vertex, max_vertex - min_vertex + 1, primitive->get_num_vertices() - 2, - primitive->get_vertices(), D3DFMT_INDEX16, + primitive->get_data(), index_type, _vertex_data->get_array(0)->get_data(), _vertex_data->get_format()->get_array(0)->get_stride()); } @@ -2797,9 +2801,11 @@ draw_tristrips(const qpGeomTristrips *primitive) { // Send the individual triangle strips, stepping over the // degenerate vertices. CPTA_int ends = primitive->get_ends(); - CPTA_ushort mins = primitive->get_mins(); - CPTA_ushort maxs = primitive->get_maxs(); - nassertv(mins.size() == ends.size() && maxs.size() == ends.size()); + int index_stride = primitive->get_index_stride(); + + qpGeomVertexReader mins(primitive->get_mins(), 0); + qpGeomVertexReader maxs(primitive->get_mins(), 0); + nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size()); if (_vbuffer_active) { IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this); @@ -2809,10 +2815,12 @@ draw_tristrips(const qpGeomTristrips *primitive) { unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_tristrip_pcollector.add_level(ends[i] - start); + unsigned int min = mins.get_data1i(); + unsigned int max = maxs.get_data1i(); _pD3DDevice->DrawIndexedPrimitive (D3DPT_TRIANGLESTRIP, - mins[i], maxs[i] - mins[i] + 1, - start, ends[i] - start - 2); + min, max - min + 1, + start * index_stride, ends[i] - start - 2); start = ends[i] + 2; } @@ -2820,16 +2828,18 @@ draw_tristrips(const qpGeomTristrips *primitive) { } else { CPTA_uchar array_data = _vertex_data->get_array(0)->get_data(); int stride = _vertex_data->get_format()->get_array(0)->get_stride(); - CPTA_ushort vertices = primitive->get_vertices(); + CPTA_uchar vertices = primitive->get_data(); unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_tristrip_pcollector.add_level(ends[i] - start); + unsigned int min = mins.get_data1i(); + unsigned int max = maxs.get_data1i(); _pD3DDevice->DrawIndexedPrimitiveUP (D3DPT_TRIANGLESTRIP, - mins[i], maxs[i] - mins[i] + 1, + min, max - min + 1, ends[i] - start - 2, - vertices + start, D3DFMT_INDEX16, + vertices + start * index_stride, index_type, array_data, stride); start = ends[i] + 2; @@ -2847,13 +2857,16 @@ void DXGraphicsStateGuardian8:: draw_trifans(const qpGeomTrifans *primitive) { int min_vertex = primitive->get_min_vertex(); int max_vertex = primitive->get_max_vertex(); + D3DFORMAT index_type = get_index_type(primitive->get_index_type()); // Send the individual triangle fans. There's no connecting fans // with degenerate vertices, so no worries about that. CPTA_int ends = primitive->get_ends(); - CPTA_ushort mins = primitive->get_mins(); - CPTA_ushort maxs = primitive->get_maxs(); - nassertv(mins.size() == ends.size() && maxs.size() == ends.size()); + int index_stride = primitive->get_index_stride(); + + qpGeomVertexReader mins(primitive->get_mins(), 0); + qpGeomVertexReader maxs(primitive->get_mins(), 0); + nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size()); if (_vbuffer_active) { IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this); @@ -2863,10 +2876,12 @@ draw_trifans(const qpGeomTrifans *primitive) { unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_trifan_pcollector.add_level(ends[i] - start); + unsigned int min = mins.get_data1i(); + unsigned int max = maxs.get_data1i(); _pD3DDevice->DrawIndexedPrimitive (D3DPT_TRIANGLEFAN, - mins[i], maxs[i] - mins[i] + 1, - start, ends[i] - start - 2); + min, max - min + 1, + start * index_stride, ends[i] - start - 2); start = ends[i] + 2; } @@ -2874,16 +2889,18 @@ draw_trifans(const qpGeomTrifans *primitive) { } else { CPTA_uchar array_data = _vertex_data->get_array(0)->get_data(); int stride = _vertex_data->get_format()->get_array(0)->get_stride(); - CPTA_ushort vertices = primitive->get_vertices(); + CPTA_uchar vertices = primitive->get_data(); unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_trifan_pcollector.add_level(ends[i] - start); + unsigned int min = mins.get_data1i(); + unsigned int max = maxs.get_data1i(); _pD3DDevice->DrawIndexedPrimitiveUP (D3DPT_TRIANGLEFAN, - mins[i], maxs[i] - mins[i] + 1, + min, max - min + 1, ends[i] - start - 2, - vertices + start, D3DFMT_INDEX16, + vertices + start * index_stride, index_type, array_data, stride); start = ends[i] + 2; @@ -2911,13 +2928,15 @@ draw_lines(const qpGeomLines *primitive) { 0, primitive->get_num_primitives()); } else { + D3DFORMAT index_type = get_index_type(primitive->get_index_type()); + _pD3DDevice->DrawIndexedPrimitiveUP (D3DPT_LINELIST, primitive->get_min_vertex(), primitive->get_max_vertex() - primitive->get_min_vertex() + 1, primitive->get_num_primitives(), - primitive->get_vertices(), - D3DFMT_INDEX16, + primitive->get_data(), + index_type, _vertex_data->get_array(0)->get_data(), _vertex_data->get_format()->get_array(0)->get_stride()); } @@ -4249,6 +4268,27 @@ end_frame() { GraphicsStateGuardian::end_frame(); } +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::get_index_type +// Access: Protected, Static +// Description: Maps from the Geom's internal numeric type symbols +// to DirectX's. +//////////////////////////////////////////////////////////////////// +D3DFORMAT DXGraphicsStateGuardian8:: +get_index_type(qpGeom::NumericType numeric_type) { + switch (numeric_type) { + case qpGeom::NT_uint16: + return D3DFMT_INDEX16; + + case qpGeom::NT_uint32: + return D3DFMT_INDEX32; + } + + dxgsg8_cat.error() + << "Invalid index NumericType value (" << (int)numeric_type << ")\n"; + return D3DFMT_INDEX16; +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::set_draw_buffer // Access: Protected diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 6288e12851..a98053d2da 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -152,6 +152,8 @@ public: INLINE float compute_distance_to(const LPoint3f &point) const; virtual void set_color_clear_value(const Colorf& value); + static D3DFORMAT get_index_type(qpGeom::NumericType numeric_type); + public: // recreate_tex_callback needs these to be public DXScreenData *_pScrn; diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.cxx b/panda/src/dxgsg8/dxIndexBufferContext8.cxx index 02e8e7b4b9..d0d34a1550 100644 --- a/panda/src/dxgsg8/dxIndexBufferContext8.cxx +++ b/panda/src/dxgsg8/dxIndexBufferContext8.cxx @@ -65,9 +65,12 @@ create_ibuffer(DXScreenData &scrn) { _ibuffer = NULL; } + D3DFORMAT index_type = + DXGraphicsStateGuardian8::get_index_type(get_data()->get_index_type()); + HRESULT hr = scrn.pD3DDevice->CreateIndexBuffer (get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY, - D3DFMT_INDEX16, D3DPOOL_MANAGED, &_ibuffer); + index_type, D3DPOOL_MANAGED, &_ibuffer); if (FAILED(hr)) { dxgsg8_cat.warning() << "CreateIndexBuffer failed" << D3DERRORSTRING(hr); @@ -104,7 +107,7 @@ upload_data() { return; } - memcpy(local_pointer, get_data()->get_vertices(), data_size); + memcpy(local_pointer, get_data()->get_data(), data_size); _ibuffer->Unlock(); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index ef3e0ea19c..7f928059b4 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2480,13 +2480,14 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, void CLP(GraphicsStateGuardian):: draw_triangles(const qpGeomTriangles *primitive) { _vertices_tri_pcollector.add_level(primitive->get_num_vertices()); - const unsigned short *client_pointer = setup_primitive(primitive); + const unsigned char *client_pointer = setup_primitive(primitive); _glDrawRangeElements(GL_TRIANGLES, primitive->get_min_vertex(), primitive->get_max_vertex(), primitive->get_num_vertices(), - GL_UNSIGNED_SHORT, client_pointer); + get_numeric_type(primitive->get_index_type()), + client_pointer); report_my_gl_errors(); } @@ -2498,7 +2499,7 @@ draw_triangles(const qpGeomTriangles *primitive) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: draw_tristrips(const qpGeomTristrips *primitive) { - const unsigned short *client_pointer = setup_primitive(primitive); + const unsigned char *client_pointer = setup_primitive(primitive); if (connect_triangle_strips && _render_mode != RenderModeAttrib::M_wireframe) { // One long triangle strip, connected by the degenerate vertices @@ -2508,22 +2509,27 @@ draw_tristrips(const qpGeomTristrips *primitive) { primitive->get_min_vertex(), primitive->get_max_vertex(), primitive->get_num_vertices(), - GL_UNSIGNED_SHORT, client_pointer); + get_numeric_type(primitive->get_index_type()), + client_pointer); } else { // Send the individual triangle strips, stepping over the // degenerate vertices. CPTA_int ends = primitive->get_ends(); - CPTA_ushort mins = primitive->get_mins(); - CPTA_ushort maxs = primitive->get_maxs(); - nassertv(mins.size() == ends.size() && maxs.size() == ends.size()); + int index_stride = primitive->get_index_stride(); + + qpGeomVertexReader mins(primitive->get_mins(), 0); + qpGeomVertexReader maxs(primitive->get_mins(), 0); + nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size()); unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_tristrip_pcollector.add_level(ends[i] - start); _glDrawRangeElements(GL_TRIANGLE_STRIP, - mins[i], maxs[i], ends[i] - start, - GL_UNSIGNED_SHORT, client_pointer + start); + mins.get_data1i(), maxs.get_data1i(), + ends[i] - start, + get_numeric_type(primitive->get_index_type()), + client_pointer + start * index_stride); start = ends[i] + 2; } } @@ -2531,6 +2537,37 @@ draw_tristrips(const qpGeomTristrips *primitive) { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::draw_trifans +// Access: Public, Virtual +// Description: Draws a series of triangle fans. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +draw_trifans(const qpGeomTrifans *primitive) { + const unsigned char *client_pointer = setup_primitive(primitive); + + // Send the individual triangle fans. There's no connecting fans + // with degenerate vertices, so no worries about that. + CPTA_int ends = primitive->get_ends(); + int index_stride = primitive->get_index_stride(); + + qpGeomVertexReader mins(primitive->get_mins(), 0); + qpGeomVertexReader maxs(primitive->get_mins(), 0); + nassertv(mins.get_num_vertices() == ends.size() && maxs.get_num_vertices() == ends.size()); + + unsigned int start = 0; + for (size_t i = 0; i < ends.size(); i++) { + _vertices_trifan_pcollector.add_level(ends[i] - start); + _glDrawRangeElements(GL_TRIANGLE_FAN, + mins.get_data1i(), maxs.get_data1i(), ends[i] - start, + get_numeric_type(primitive->get_index_type()), + client_pointer + start * index_stride); + start = ends[i] + 2; + } + + report_my_gl_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::draw_lines // Access: Public, Virtual @@ -2539,13 +2576,14 @@ draw_tristrips(const qpGeomTristrips *primitive) { void CLP(GraphicsStateGuardian):: draw_lines(const qpGeomLines *primitive) { _vertices_other_pcollector.add_level(primitive->get_num_vertices()); - const unsigned short *client_pointer = setup_primitive(primitive); + const unsigned char *client_pointer = setup_primitive(primitive); _glDrawRangeElements(GL_LINES, primitive->get_min_vertex(), primitive->get_max_vertex(), primitive->get_num_vertices(), - GL_UNSIGNED_SHORT, client_pointer); + get_numeric_type(primitive->get_index_type()), + client_pointer); report_my_gl_errors(); } @@ -2567,13 +2605,14 @@ draw_linestrips(const qpGeomLinestrips *primitive) { void CLP(GraphicsStateGuardian):: draw_points(const qpGeomPoints *primitive) { _vertices_other_pcollector.add_level(primitive->get_num_vertices()); - const unsigned short *client_pointer = setup_primitive(primitive); + const unsigned char *client_pointer = setup_primitive(primitive); _glDrawRangeElements(GL_POINTS, primitive->get_min_vertex(), primitive->get_max_vertex(), primitive->get_num_vertices(), - GL_UNSIGNED_SHORT, client_pointer); + get_numeric_type(primitive->get_index_type()), + client_pointer); report_my_gl_errors(); } @@ -3005,12 +3044,12 @@ apply_index_buffer(IndexBufferContext *ibc) { } if (gibc->changed_size()) { _glBufferData(GL_ELEMENT_ARRAY_BUFFER, gibc->get_data()->get_data_size_bytes(), - gibc->get_data()->get_vertices(), + gibc->get_data()->get_data(), get_usage(gibc->get_data()->get_usage_hint())); } else { _glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, gibc->get_data_size_bytes(), - gibc->get_data()->get_vertices()); + gibc->get_data()->get_data()); } gibc->mark_loaded(); @@ -3059,23 +3098,23 @@ release_index_buffer(IndexBufferContext *ibc) { // this function returns the pointer to the data array // in client memory, that is, the data array passed in. //////////////////////////////////////////////////////////////////// -const unsigned short *CLP(GraphicsStateGuardian):: +const unsigned char *CLP(GraphicsStateGuardian):: setup_primitive(const qpGeomPrimitive *data) { if (!_supports_buffers) { // No support for buffer objects; always render from client. - return data->get_vertices(); + return data->get_data(); } if (!vertex_buffers || _geom_display_list != 0 || data->get_usage_hint() == qpGeom::UH_client) { // The array specifies client rendering only, or buffer objects // are configured off. _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - return data->get_vertices(); + return data->get_data(); } // Prepare the buffer object and bind it. IndexBufferContext *ibc = ((qpGeomPrimitive *)data)->prepare_now(get_prepared_objects(), this); - nassertr(ibc != (IndexBufferContext *)NULL, data->get_vertices()); + nassertr(ibc != (IndexBufferContext *)NULL, data->get_data()); apply_index_buffer(ibc); // NULL is the OpenGL convention for the first byte of the buffer object. @@ -4735,6 +4774,9 @@ get_numeric_type(qpGeom::NumericType numeric_type) { case qpGeom::NT_uint16: return GL_UNSIGNED_SHORT; + case qpGeom::NT_uint32: + return GL_UNSIGNED_INT; + case qpGeom::NT_uint8: case qpGeom::NT_packed_dcba: case qpGeom::NT_packed_dabc: diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 29d5f62ad0..f5c59647b0 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -99,6 +99,7 @@ public: const qpGeomVertexData *vertex_data); virtual void draw_triangles(const qpGeomTriangles *primitive); virtual void draw_tristrips(const qpGeomTristrips *primitive); + virtual void draw_trifans(const qpGeomTrifans *primitive); virtual void draw_lines(const qpGeomLines *primitive); virtual void draw_linestrips(const qpGeomLinestrips *primitive); virtual void draw_points(const qpGeomPoints *primitive); @@ -122,7 +123,7 @@ public: virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data); void apply_index_buffer(IndexBufferContext *ibc); virtual void release_index_buffer(IndexBufferContext *ibc); - const unsigned short *setup_primitive(const qpGeomPrimitive *data); + const unsigned char *setup_primitive(const qpGeomPrimitive *data); virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state); diff --git a/panda/src/gobj/internalName.I b/panda/src/gobj/internalName.I index c0c8f8daff..f19527df3a 100644 --- a/panda/src/gobj/internalName.I +++ b/panda/src/gobj/internalName.I @@ -91,7 +91,9 @@ get_error() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_vertex // Access: Published, Static -// Description: Returns the standard InternalName "vertex". +// Description: Returns the standard InternalName "vertex". This is +// the column header for the 3-d or 4-d vertex position +// information for each vertex. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_vertex() { @@ -104,7 +106,9 @@ get_vertex() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_normal // Access: Published, Static -// Description: Returns the standard InternalName "normal". +// Description: Returns the standard InternalName "normal". This is +// the column header for the 3-d lighting normal for +// each vertex. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_normal() { @@ -117,7 +121,12 @@ get_normal() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_tangent // Access: Published, Static -// Description: Returns the standard InternalName "tangent". +// Description: Returns the standard InternalName "tangent". This is +// the column header for the tangent vector associated +// with each vertex, which is a unit vector +// usually perpendicular to the normal and in the +// direction of the U texture coordinate change. It is +// used for deriving bump maps. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_tangent() { @@ -130,7 +139,13 @@ get_tangent() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_binormal // Access: Published, Static -// Description: Returns the standard InternalName "binormal". +// Description: Returns the standard InternalName "binormal". This is +// the column header for the tangent vector associated +// with each vertex, which is a unit vector +// usually perpendicular to both the normal and the +// tangent, and in the direction of the V texture +// coordinate change. It is used for deriving bump +// maps. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_binormal() { @@ -143,7 +158,11 @@ get_binormal() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_texcoord // Access: Published, Static -// Description: Returns the standard InternalName "texcoord". +// Description: Returns the standard InternalName "texcoord". This +// is the column header for the default texture +// coordinate set for each vertex. It is also used for +// identifying the default texture coordinate set in a +// TextureStage. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_texcoord() { @@ -157,8 +176,10 @@ get_texcoord() { // Function: InternalName::get_texcoord_name // Access: Published, Static // Description: Returns the InternalName "texcoord.name", where name -// is the supplied string. This, by convention, -// represents the named texture coordinate set. +// is the supplied string. This is the column header +// for the named texture coordinate set for each vertex. +// It is also used for identifying the named texture +// coordinate set in a TextureStage. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_texcoord_name(const string &name) { @@ -168,7 +189,9 @@ get_texcoord_name(const string &name) { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_color // Access: Published, Static -// Description: Returns the standard InternalName "color". +// Description: Returns the standard InternalName "color". This is +// the column header for the 4-component color value for +// each vertex. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_color() { @@ -181,7 +204,11 @@ get_color() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_rotate // Access: Published, Static -// Description: Returns the standard InternalName "rotate". +// Description: Returns the standard InternalName "rotate". This is +// the column header for the floating-point rotate +// value, which represents a number of degrees +// counter-clockwise to rotate each point or point +// sprite. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_rotate() { @@ -194,7 +221,11 @@ get_rotate() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_size // Access: Published, Static -// Description: Returns the standard InternalName "size". +// Description: Returns the standard InternalName "size". This is +// the column header for the floating-point size value, +// which overrides the thickness parameter of the +// RenderModeAttrib on a per-vertex (e.g. per-point) +// basis. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_size() { @@ -208,6 +239,10 @@ get_size() { // Function: InternalName::get_aspect_ratio // Access: Published, Static // Description: Returns the standard InternalName "aspect_ratio". +// This is the column header for the floating-point +// aspect ratio value, which is used to define +// non-square points. This number is the ratio x / y, +// where y is the point size (above). //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_aspect_ratio() { @@ -221,6 +256,10 @@ get_aspect_ratio() { // Function: InternalName::get_transform_blend // Access: Published, Static // Description: Returns the standard InternalName "transform_blend". +// This is the column header for the integer +// transform_blend index, which is used to define vertex +// animation on the CPU by indexing to a particular +// vertex weighting from the TransformBlendPalette. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_transform_blend() { @@ -234,6 +273,14 @@ get_transform_blend() { // Function: InternalName::get_transform_weight // Access: Published, Static // Description: Returns the standard InternalName "transform_weight". +// This is the column header for the n-component +// transform_weight value, which is used in conjuntion +// with "transform_index" to define vertex animation on +// the graphics card. The transform_weight value +// specifies the weight of the nth transform. By +// convention, there are 1 fewer weight values than +// transforms, since the weights are assumed to sum to 1 +// (and the last value is therefore implicit). //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_transform_weight() { @@ -247,6 +294,14 @@ get_transform_weight() { // Function: InternalName::get_transform_index // Access: Published, Static // Description: Returns the standard InternalName "transform_index". +// This is the column header for the n-component +// transform_index value, which is used in conjuntion +// with "transform_weight" to define vertex animation on +// the graphics card. The transform_index value +// specifies the nth transform, by lookup in the +// TransformPalette. The transform_index column may be +// omitted, in which case the nth transform is the nth +// entry in the palette. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_transform_index() { @@ -259,16 +314,41 @@ get_transform_index() { //////////////////////////////////////////////////////////////////// // Function: InternalName::get_morph // Access: Published, Static -// Description: Returns an InternalName suitable for defining the -// morph deltas in the GeomVertexData to apply to the -// indicated data type name, using the named slider. +// Description: Returns an InternalName derived from the given base +// column name and the given slider name, which is the +// column header for the offset vector that should be +// applied to the base column name when the named morph +// slider is engaged. +// +// Each morph slider requires a set of n morph columns, +// one for each base column it applies to. //////////////////////////////////////////////////////////////////// INLINE PT(InternalName) InternalName:: get_morph(InternalName *column, const string &slider) { - // Returns column.morph.slider + // This actually returns "column.morph.slider", although that's just + // an implementation detail--as long as it returns a consistent, + // unique name for each combination of column and slider, everything + // is good. return column->append("morph")->append(slider); } +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_index +// Access: Published, Static +// Description: Returns the standard InternalName "index". This is +// the column header for the integer vertex index. It +// is not used in the vertex data itself, but is used in +// the GeomPrimitive structure to index into the vertex +// data. +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_index() { + if (_index == (InternalName *)NULL) { + _index = InternalName::make("index"); + } + return _index; +} + INLINE ostream & operator << (ostream &out, const InternalName &tcn) { tcn.output(out); diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx index 520a01289e..05dfdd2cff 100644 --- a/panda/src/gobj/internalName.cxx +++ b/panda/src/gobj/internalName.cxx @@ -38,6 +38,7 @@ PT(InternalName) InternalName::_aspect_ratio; PT(InternalName) InternalName::_transform_blend; PT(InternalName) InternalName::_transform_weight; PT(InternalName) InternalName::_transform_index; +PT(InternalName) InternalName::_index; TypeHandle InternalName::_type_handle; TypeHandle InternalName::_texcoord_type_handle; diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h index 75e058bae2..120104593c 100644 --- a/panda/src/gobj/internalName.h +++ b/panda/src/gobj/internalName.h @@ -78,6 +78,7 @@ PUBLISHED: INLINE static PT(InternalName) get_transform_weight(); INLINE static PT(InternalName) get_transform_index(); INLINE static PT(InternalName) get_morph(InternalName *column, const string &slider); + INLINE static PT(InternalName) get_index(); private: PT(InternalName) _parent; @@ -101,6 +102,7 @@ private: static PT(InternalName) _transform_blend; static PT(InternalName) _transform_weight; static PT(InternalName) _transform_index; + static PT(InternalName) _index; public: // Datagram stuff diff --git a/panda/src/gobj/qpgeomEnums.cxx b/panda/src/gobj/qpgeomEnums.cxx index 02b57abb1c..aa6b9f0c15 100644 --- a/panda/src/gobj/qpgeomEnums.cxx +++ b/panda/src/gobj/qpgeomEnums.cxx @@ -28,6 +28,9 @@ operator << (ostream &out, qpGeomEnums::NumericType numeric_type) { case qpGeomEnums::NT_uint16: return out << "uint16"; + case qpGeomEnums::NT_uint32: + return out << "uint32"; + case qpGeomEnums::NT_packed_dcba: return out << "packed_dcba"; diff --git a/panda/src/gobj/qpgeomEnums.h b/panda/src/gobj/qpgeomEnums.h index 93c69619a6..2c5b57d62f 100644 --- a/panda/src/gobj/qpgeomEnums.h +++ b/panda/src/gobj/qpgeomEnums.h @@ -169,6 +169,7 @@ PUBLISHED: enum NumericType { NT_uint8, // An integer 0..255 NT_uint16, // An integer 0..65535 + NT_uint32, // An integer 0..4294967296 NT_packed_dcba, // DirectX style, four byte values packed in a uint32 NT_packed_dabc, // DirectX packed color order (ARGB) NT_float32, // A floating-point number diff --git a/panda/src/gobj/qpgeomLines.cxx b/panda/src/gobj/qpgeomLines.cxx index 0b0a6631eb..0612659725 100644 --- a/panda/src/gobj/qpgeomLines.cxx +++ b/panda/src/gobj/qpgeomLines.cxx @@ -121,20 +121,26 @@ draw(GraphicsStateGuardianBase *gsg) const { // Access: Protected, Virtual // Description: The virtual implementation of do_rotate(). //////////////////////////////////////////////////////////////////// -CPTA_ushort qpGeomLines:: +CPT(qpGeomVertexArrayData) qpGeomLines:: rotate_impl() const { // To rotate lines, we just move reverse the pairs of vertices. - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); - PTA_ushort new_vertices; - new_vertices.reserve(vertices.size()); + PT(qpGeomVertexArrayData) new_vertices = + new qpGeomVertexArrayData(*vertices); + qpGeomVertexReader from(vertices, 0); + qpGeomVertexWriter to(new_vertices, 0); - for (int begin = 0; begin < (int)vertices.size(); begin += 2) { - new_vertices.push_back(vertices[begin + 1]); - new_vertices.push_back(vertices[begin]); + int num_vertices = vertices->get_num_vertices(); + + for (int begin = 0; begin < num_vertices; begin += 2) { + from.set_vertex(begin + 1); + to.set_data1i(from.get_data1i()); + from.set_vertex(begin); + to.set_data1i(from.get_data1i()); } - nassertr(new_vertices.size() == vertices.size(), CPTA_ushort()); + nassertr(to.is_at_end(), NULL); return new_vertices; } diff --git a/panda/src/gobj/qpgeomLines.h b/panda/src/gobj/qpgeomLines.h index 26f9b34a0d..954ababfb6 100644 --- a/panda/src/gobj/qpgeomLines.h +++ b/panda/src/gobj/qpgeomLines.h @@ -45,7 +45,7 @@ public: virtual void draw(GraphicsStateGuardianBase *gsg) const; protected: - virtual CPTA_ushort rotate_impl() const; + virtual CPT(qpGeomVertexArrayData) rotate_impl() const; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomLinestrips.cxx b/panda/src/gobj/qpgeomLinestrips.cxx index 8e1929bf47..a38ce42351 100644 --- a/panda/src/gobj/qpgeomLinestrips.cxx +++ b/panda/src/gobj/qpgeomLinestrips.cxx @@ -18,6 +18,7 @@ #include "qpgeomLinestrips.h" #include "qpgeomLines.h" +#include "qpgeomVertexRewriter.h" #include "pStatTimer.h" #include "bamReader.h" #include "bamWriter.h" @@ -131,7 +132,8 @@ CPT(qpGeomPrimitive) qpGeomLinestrips:: decompose_impl() const { PT(qpGeomLines) lines = new qpGeomLines(get_usage_hint()); lines->set_shade_model(get_shade_model()); - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); + qpGeomVertexReader index(vertices, 0); CPTA_int ends = get_ends(); int vi = 0; @@ -139,20 +141,19 @@ decompose_impl() const { while (li < (int)ends.size()) { int end = ends[li]; nassertr(vi + 1 <= end, lines.p()); - nassertr(vi < (int)vertices.size(), this); - int v0 = vertices[vi]; + int v0 = index.get_data1i(); ++vi; while (vi < end) { - lines->add_vertex(v0); - lines->add_vertex(vertices[vi]); - nassertr(vi < (int)vertices.size(), this); - v0 = vertices[vi]; - lines->close_primitive(); + int v1 = index.get_data1i(); ++vi; + lines->add_vertex(v0); + lines->add_vertex(v1); + v0 = v1; + lines->close_primitive(); } ++li; } - nassertr(vi == (int)vertices.size(), lines.p()); + nassertr(vi == vertices->get_num_vertices() && index.is_at_end(), NULL); return lines.p(); } @@ -162,25 +163,28 @@ decompose_impl() const { // Access: Protected, Virtual // Description: The virtual implementation of do_rotate(). //////////////////////////////////////////////////////////////////// -CPTA_ushort qpGeomLinestrips:: +CPT(qpGeomVertexArrayData) qpGeomLinestrips:: rotate_impl() const { // To rotate a line strip, we just reverse the vertices. - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); CPTA_int ends = get_ends(); - PTA_ushort new_vertices; - new_vertices.reserve(vertices.size()); + PT(qpGeomVertexArrayData) new_vertices = + new qpGeomVertexArrayData(*vertices); + qpGeomVertexReader from(vertices, 0); + qpGeomVertexWriter to(new_vertices, 0); int begin = 0; CPTA_int::const_iterator ei; for (ei = ends.begin(); ei != ends.end(); ++ei) { int end = (*ei); for (int vi = end - 1; vi >= begin; --vi) { - new_vertices.push_back(vertices[vi]); + from.set_vertex(vi); + to.set_data1i(from.get_data1i()); } begin = end; } - nassertr(new_vertices.size() == vertices.size(), CPTA_ushort()); + nassertr(to.is_at_end(), NULL); return new_vertices; } diff --git a/panda/src/gobj/qpgeomLinestrips.h b/panda/src/gobj/qpgeomLinestrips.h index c11f1991de..1820ea5491 100644 --- a/panda/src/gobj/qpgeomLinestrips.h +++ b/panda/src/gobj/qpgeomLinestrips.h @@ -45,7 +45,7 @@ public: protected: virtual CPT(qpGeomPrimitive) decompose_impl() const; - virtual CPTA_ushort rotate_impl() const; + virtual CPT(qpGeomVertexArrayData) rotate_impl() const; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomPrimitive.I b/panda/src/gobj/qpgeomPrimitive.I index b6fe27b0e3..9965d3f66b 100644 --- a/panda/src/gobj/qpgeomPrimitive.I +++ b/panda/src/gobj/qpgeomPrimitive.I @@ -65,8 +65,7 @@ set_shade_model(qpGeomPrimitive::ShadeModel shade_model) { //////////////////////////////////////////////////////////////////// INLINE qpGeomPrimitive::UsageHint qpGeomPrimitive:: get_usage_hint() const { - CDReader cdata(_cycler); - return cdata->_usage_hint; + return get_vertices()->get_usage_hint(); } //////////////////////////////////////////////////////////////////// @@ -77,8 +76,19 @@ get_usage_hint() const { //////////////////////////////////////////////////////////////////// INLINE void qpGeomPrimitive:: set_usage_hint(qpGeomPrimitive::UsageHint usage_hint) { - CDWriter cdata(_cycler); - cdata->_usage_hint = usage_hint; + modify_vertices()->set_usage_hint(usage_hint); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_index_type +// Access: Public +// Description: Returns the numeric type of the index column. +// Normally, this will be either NT_uint16 or NT_uint32. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomPrimitive::NumericType qpGeomPrimitive:: +get_index_type() const { + CDReader cdata(_cycler); + return cdata->_index_type; } //////////////////////////////////////////////////////////////////// @@ -90,19 +100,7 @@ set_usage_hint(qpGeomPrimitive::UsageHint usage_hint) { INLINE int qpGeomPrimitive:: get_num_vertices() const { CDReader cdata(_cycler); - return cdata->_vertices.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: qpGeomPrimitive::get_vertex -// Access: Published -// Description: Returns the ith vertex index in the table. -//////////////////////////////////////////////////////////////////// -INLINE int qpGeomPrimitive:: -get_vertex(int i) const { - CDReader cdata(_cycler); - nassertr(i >= 0 && i < (int)cdata->_vertices.size(), -1); - return cdata->_vertices[i]; + return cdata->_vertices->get_num_vertices(); } //////////////////////////////////////////////////////////////////// @@ -162,19 +160,6 @@ get_min_vertex() const { return cdata->_min_vertex; } -//////////////////////////////////////////////////////////////////// -// Function: qpGeomPrimitive::get_primitive_min_vertex -// Access: Published -// Description: Returns the minimum vertex index number used by the -// nth primitive in this object. -//////////////////////////////////////////////////////////////////// -INLINE int qpGeomPrimitive:: -get_primitive_min_vertex(int n) const { - CPTA_ushort mins = get_mins(); - nassertr(n >= 0 && n < (int)mins.size(), -1); - return mins[n]; -} - //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::get_max_vertex // Access: Published @@ -192,19 +177,6 @@ get_max_vertex() const { return cdata->_max_vertex; } -//////////////////////////////////////////////////////////////////// -// Function: qpGeomPrimitive::get_primitive_max_vertex -// Access: Published -// Description: Returns the maximum vertex index number used by the -// nth primitive in this object. -//////////////////////////////////////////////////////////////////// -INLINE int qpGeomPrimitive:: -get_primitive_max_vertex(int n) const { - CPTA_ushort maxs = get_maxs(); - nassertr(n >= 0 && n < (int)maxs.size(), -1); - return maxs[n]; -} - //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::get_data_size_bytes // Access: Published @@ -214,7 +186,7 @@ get_primitive_max_vertex(int n) const { INLINE int qpGeomPrimitive:: get_data_size_bytes() const { CDReader cdata(_cycler); - return cdata->_vertices.size() * sizeof(short); + return cdata->_vertices->get_data_size_bytes(); } //////////////////////////////////////////////////////////////////// @@ -238,12 +210,35 @@ get_modified() const { // attempt to modify the returned array; use // modify_vertices() or set_vertices() for this. //////////////////////////////////////////////////////////////////// -INLINE CPTA_ushort qpGeomPrimitive:: +INLINE const qpGeomVertexArrayData *qpGeomPrimitive:: get_vertices() const { CDReader cdata(_cycler); return cdata->_vertices; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_index_stride +// Access: Public +// Description: A convenience function to return the gap between +// successive index numbers, in bytes, of the index +// data. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomPrimitive:: +get_index_stride() const { + return get_vertices()->get_array_format()->get_stride(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_data +// Access: Public +// Description: A convenience function to return the actual data of +// the index array. +//////////////////////////////////////////////////////////////////// +INLINE CPTA_uchar qpGeomPrimitive:: +get_data() const { + return get_vertices()->get_data(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::get_ends // Access: Public @@ -273,7 +268,7 @@ get_ends() const { // Note that simple primitive types, like triangles, do // not have a mins array. //////////////////////////////////////////////////////////////////// -INLINE CPTA_ushort qpGeomPrimitive:: +INLINE const qpGeomVertexArrayData *qpGeomPrimitive:: get_mins() const { CDReader cdata(_cycler); if (!cdata->_got_minmax) { @@ -295,7 +290,7 @@ get_mins() const { // Note that simple primitive types, like triangles, do // not have a maxs array. //////////////////////////////////////////////////////////////////// -INLINE CPTA_ushort qpGeomPrimitive:: +INLINE const qpGeomVertexArrayData *qpGeomPrimitive:: get_maxs() const { CDReader cdata(_cycler); if (!cdata->_got_minmax) { @@ -313,8 +308,8 @@ get_maxs() const { //////////////////////////////////////////////////////////////////// INLINE qpGeomPrimitive::CData:: CData() : - _usage_hint(UH_unspecified), _shade_model(SM_smooth), + _index_type(NT_uint16), _got_minmax(true), _min_vertex(0), _max_vertex(0) @@ -328,8 +323,8 @@ CData() : //////////////////////////////////////////////////////////////////// INLINE qpGeomPrimitive::CData:: CData(const qpGeomPrimitive::CData ©) : - _usage_hint(copy._usage_hint), _shade_model(copy._shade_model), + _index_type(copy._index_type), _vertices(copy._vertices), _ends(copy._ends), _mins(copy._mins), diff --git a/panda/src/gobj/qpgeomPrimitive.cxx b/panda/src/gobj/qpgeomPrimitive.cxx index 9cb2be8030..66daa3c04e 100644 --- a/panda/src/gobj/qpgeomPrimitive.cxx +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -22,6 +22,8 @@ #include "qpgeomVertexArrayFormat.h" #include "qpgeomVertexColumn.h" #include "qpgeomVertexReader.h" +#include "qpgeomVertexWriter.h" +#include "qpgeomVertexRewriter.h" #include "preparedGraphicsObjects.h" #include "internalName.h" #include "bamReader.h" @@ -33,6 +35,16 @@ TypeHandle qpGeomPrimitive::_type_handle; PStatCollector qpGeomPrimitive::_decompose_pcollector("Cull:Munge:Decompose"); PStatCollector qpGeomPrimitive::_rotate_pcollector("Cull:Munge:Rotate"); +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::Default Constructor +// Access: Protected +// Description: Constructs an invalid object. Only used when reading +// from bam. +//////////////////////////////////////////////////////////////////// +qpGeomPrimitive:: +qpGeomPrimitive() { +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::Constructor // Access: Published @@ -40,7 +52,14 @@ PStatCollector qpGeomPrimitive::_rotate_pcollector("Cull:Munge:Rotate"); //////////////////////////////////////////////////////////////////// qpGeomPrimitive:: qpGeomPrimitive(qpGeomPrimitive::UsageHint usage_hint) { - set_usage_hint(usage_hint); + CDWriter cdata(_cycler); + + CPT(qpGeomVertexArrayFormat) new_format = + qpGeomVertexArrayFormat::register_format + (new qpGeomVertexArrayFormat(InternalName::get_index(), 1, + cdata->_index_type, C_index)); + + cdata->_vertices = new qpGeomVertexArrayData(new_format, usage_hint); } //////////////////////////////////////////////////////////////////// @@ -78,6 +97,52 @@ get_geom_rendering() const { return 0; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::set_index_type +// Access: Published +// Description: Changes the numeric type of the index column. +// Normally, this should be either NT_uint16 or +// NT_uint32. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +set_index_type(qpGeomPrimitive::NumericType index_type) { + CDWriter cdata(_cycler); + cdata->_index_type = index_type; + + CPT(qpGeomVertexArrayFormat) new_format = + qpGeomVertexArrayFormat::register_format + (new qpGeomVertexArrayFormat(InternalName::get_index(), 1, index_type, + C_index)); + + if (cdata->_vertices->get_array_format() != new_format) { + PT(qpGeomVertexArrayData) new_vertices = + new qpGeomVertexArrayData(new_format, cdata->_vertices->get_usage_hint()); + qpGeomVertexReader from(cdata->_vertices, 0); + qpGeomVertexWriter to(new_vertices, 0); + + while (!from.is_at_end()) { + to.add_data1i(from.get_data1i()); + } + cdata->_vertices = new_vertices; + cdata->_got_minmax = false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_vertex +// Access: Published +// Description: Returns the ith vertex index in the table. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_vertex(int i) const { + CDReader cdata(_cycler); + nassertr(i >= 0 && i < (int)cdata->_vertices->get_num_vertices(), -1); + + qpGeomVertexReader index(cdata->_vertices, 0); + index.set_vertex(i); + return index.get_data1i(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::add_vertex // Access: Published @@ -90,39 +155,22 @@ get_geom_rendering() const { //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: add_vertex(int vertex) { - unsigned short short_vertex = vertex; - nassertv((int)short_vertex == vertex); - CDWriter cdata(_cycler); int num_primitives = get_num_primitives(); if (num_primitives > 0 && - (int)cdata->_vertices.size() == get_primitive_end(num_primitives - 1)) { + (int)cdata->_vertices->get_num_vertices() == get_primitive_end(num_primitives - 1)) { // If we are beginning a new primitive, give the derived class a // chance to insert some degenerate vertices. append_unused_vertices(cdata->_vertices, vertex); } - cdata->_vertices.push_back(short_vertex); + qpGeomVertexWriter index(cdata->_vertices, 0); + index.set_vertex(index.get_num_vertices()); - if (cdata->_got_minmax) { - cdata->_min_vertex = min(cdata->_min_vertex, short_vertex); - cdata->_max_vertex = max(cdata->_max_vertex, short_vertex); + index.add_data1i(vertex); - if (get_num_vertices_per_primitive() == 0) { - // Complex primitives also update their per-primitive minmax. - size_t pi = cdata->_ends.size(); - if (pi < cdata->_mins.size()) { - cdata->_mins[pi] = min(cdata->_mins[pi], short_vertex); - cdata->_maxs[pi] = max(cdata->_maxs[pi], short_vertex); - } else { - cdata->_mins.push_back(short_vertex); - cdata->_maxs.push_back(short_vertex); - } - nassertv((cdata->_mins.size() == cdata->_ends.size() + 1) && - (cdata->_maxs.size() == cdata->_ends.size() + 1)); - } - } + cdata->_got_minmax = false; } //////////////////////////////////////////////////////////////////// @@ -137,42 +185,25 @@ add_consecutive_vertices(int start, int num_vertices) { return; } int end = (start + num_vertices) - 1; - unsigned short short_start = start; - unsigned short short_end = end; - nassertv((int)short_start == start && (int)short_end == end); CDWriter cdata(_cycler); int num_primitives = get_num_primitives(); if (num_primitives > 0 && - (int)cdata->_vertices.size() == get_primitive_end(num_primitives - 1)) { + (int)cdata->_vertices->get_num_vertices() == get_primitive_end(num_primitives - 1)) { // If we are beginning a new primitive, give the derived class a // chance to insert some degenerate vertices. append_unused_vertices(cdata->_vertices, start); } - for (unsigned short v = short_start; v <= short_end; ++v) { - cdata->_vertices.push_back(v); + qpGeomVertexWriter index(cdata->_vertices, 0); + index.set_vertex(index.get_num_vertices()); + + for (int v = start; v <= end; ++v) { + index.add_data1i(v); } - if (cdata->_got_minmax) { - cdata->_min_vertex = min(cdata->_min_vertex, short_start); - cdata->_max_vertex = max(cdata->_max_vertex, short_end); - - if (get_num_vertices_per_primitive() == 0) { - // Complex primitives also update their per-primitive minmax. - size_t pi = cdata->_ends.size(); - if (pi < cdata->_mins.size()) { - cdata->_mins[pi] = min(cdata->_mins[pi], short_start); - cdata->_maxs[pi] = max(cdata->_maxs[pi], short_end); - } else { - cdata->_mins.push_back(short_start); - cdata->_maxs.push_back(short_end); - } - nassertv((cdata->_mins.size() == cdata->_ends.size() + 1) && - (cdata->_maxs.size() == cdata->_ends.size() + 1)); - } - } + cdata->_got_minmax = false; } //////////////////////////////////////////////////////////////////// @@ -214,23 +245,14 @@ close_primitive() { #ifndef NDEBUG int num_added; if (cdata->_ends.empty()) { - num_added = (int)cdata->_vertices.size(); + num_added = (int)cdata->_vertices->get_num_vertices(); } else { - num_added = (int)cdata->_vertices.size() - cdata->_ends.back(); + num_added = (int)cdata->_vertices->get_num_vertices() - cdata->_ends.back(); num_added -= get_num_unused_vertices_per_primitive(); } nassertr(num_added >= get_min_num_vertices_per_primitive(), false); #endif - cdata->_ends.push_back((int)cdata->_vertices.size()); - -#ifndef NDEBUG - if (cdata->_got_minmax) { - nassertd((cdata->_mins.size() == cdata->_ends.size()) && - (cdata->_maxs.size() == cdata->_ends.size())) { - cdata->_got_minmax = false; - } - } -#endif + cdata->_ends.push_back((int)cdata->_vertices->get_num_vertices()); } else { #ifndef NDEBUG @@ -240,7 +262,7 @@ close_primitive() { int num_vertices_per_primitive = get_num_vertices_per_primitive(); int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive(); - int num_vertices = cdata->_vertices.size(); + int num_vertices = cdata->_vertices->get_num_vertices(); nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0, false) #endif } @@ -257,7 +279,8 @@ close_primitive() { void qpGeomPrimitive:: clear_vertices() { CDWriter cdata(_cycler); - cdata->_vertices.clear(); + cdata->_vertices = new qpGeomVertexArrayData + (cdata->_vertices->get_array_format(), cdata->_vertices->get_usage_hint()); cdata->_ends.clear(); cdata->_mins.clear(); cdata->_maxs.clear(); @@ -274,13 +297,12 @@ void qpGeomPrimitive:: offset_vertices(int offset) { CDWriter cdata(_cycler); - cdata->_mins.clear(); - cdata->_maxs.clear(); cdata->_got_minmax = false; - PTA_ushort::iterator vi; - for (vi = cdata->_vertices.begin(); vi != cdata->_vertices.end(); ++vi) { - (*vi) += offset; + qpGeomVertexRewriter index(cdata->_vertices, 0); + + while (!index.is_at_end()) { + index.set_data1i(index.get_data1i() + offset); } } @@ -304,7 +326,7 @@ get_num_primitives() const { } else { // This is a simple primitive type like a triangle: each primitive // uses the same number of vertices. - return ((int)cdata->_vertices.size() / num_vertices_per_primitive); + return ((int)cdata->_vertices->get_num_vertices() / num_vertices_per_primitive); } } @@ -401,6 +423,38 @@ get_primitive_num_vertices(int n) const { } } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_primitive_min_vertex +// Access: Published +// Description: Returns the minimum vertex index number used by the +// nth primitive in this object. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_primitive_min_vertex(int n) const { + CDReader cdata(_cycler); + nassertr(n >= 0 && n < (int)cdata->_mins->get_num_vertices(), -1); + + qpGeomVertexReader index(cdata->_mins, 0); + index.set_vertex(n); + return index.get_data1i(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_primitive_max_vertex +// Access: Published +// Description: Returns the maximum vertex index number used by the +// nth primitive in this object. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_primitive_max_vertex(int n) const { + CDReader cdata(_cycler); + nassertr(n >= 0 && n < (int)cdata->_maxs->get_num_vertices(), -1); + + qpGeomVertexReader index(cdata->_maxs, 0); + index.set_vertex(n); + return index.get_data1i(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::decompose // Access: Published @@ -446,9 +500,9 @@ rotate() const { } PStatTimer timer(_rotate_pcollector); - CPTA_ushort rotated_vertices = rotate_impl(); + CPT(qpGeomVertexArrayData) rotated_vertices = rotate_impl(); - if (rotated_vertices.is_null()) { + if (rotated_vertices == (qpGeomVertexArrayData *)NULL) { return this; } @@ -466,8 +520,8 @@ rotate() const { int qpGeomPrimitive:: get_num_bytes() const { CDReader cdata(_cycler); - return (cdata->_vertices.size() + cdata->_mins.size() + cdata->_maxs.size()) * sizeof(short) + - cdata->_ends.size() * sizeof(int) + sizeof(qpGeomPrimitive); + return (cdata->_vertices->get_data_size_bytes() + + cdata->_ends.size() * sizeof(int) + sizeof(qpGeomPrimitive)); } //////////////////////////////////////////////////////////////////// @@ -537,9 +591,14 @@ write(ostream &out, int indent_level) const { // this data. Use with caution, since there are no // checks that the data will be left in a stable state. //////////////////////////////////////////////////////////////////// -PTA_ushort qpGeomPrimitive:: +qpGeomVertexArrayData *qpGeomPrimitive:: modify_vertices() { CDWriter cdata(_cycler); + if (cdata->_vertices->get_ref_count() > 1) { + cdata->_vertices = new qpGeomVertexArrayData(*cdata->_vertices); + } + + cdata->_modified = qpGeom::get_next_modified(); cdata->_got_minmax = false; return cdata->_vertices; } @@ -552,9 +611,11 @@ modify_vertices() { // the ends list with set_ends() at the same time. //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: -set_vertices(CPTA_ushort vertices) { +set_vertices(const qpGeomVertexArrayData *vertices) { CDWriter cdata(_cycler); - cdata->_vertices = (PTA_ushort &)vertices; + cdata->_vertices = (qpGeomVertexArrayData *)vertices; + + cdata->_modified = qpGeom::get_next_modified(); cdata->_got_minmax = false; } @@ -573,6 +634,8 @@ set_vertices(CPTA_ushort vertices) { PTA_int qpGeomPrimitive:: modify_ends() { CDWriter cdata(_cycler); + + cdata->_modified = qpGeom::get_next_modified(); cdata->_got_minmax = false; return cdata->_ends; } @@ -593,6 +656,8 @@ void qpGeomPrimitive:: set_ends(CPTA_int ends) { CDWriter cdata(_cycler); cdata->_ends = (PTA_int &)ends; + + cdata->_modified = qpGeom::get_next_modified(); cdata->_got_minmax = false; } @@ -782,11 +847,11 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, CDReader cdata(_cycler); + qpGeomVertexReader index(cdata->_vertices, 0); + if (got_mat) { - PTA_ushort::const_iterator ii; - for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) { - int index = (int)(*ii); - reader.set_vertex(index); + while (!index.is_at_end()) { + reader.set_vertex(index.get_data1i()); const LVecBase3f &vertex = reader.get_data3f(); if (found_any) { @@ -803,10 +868,8 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, } } } else { - PTA_ushort::const_iterator ii; - for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) { - int index = (int)(*ii); - reader.set_vertex(index); + while (!index.is_at_end()) { + reader.set_vertex(index.get_data1i()); LPoint3f vertex = mat.xform_point(reader.get_data3f()); if (found_any) { @@ -849,11 +912,11 @@ decompose_impl() const { // Access: Protected, Virtual // Description: The virtual implementation of rotate(). //////////////////////////////////////////////////////////////////// -CPTA_ushort qpGeomPrimitive:: +CPT(qpGeomVertexArrayData) qpGeomPrimitive:: rotate_impl() const { // The default implementation doesn't even try to do anything. - nassertr(false, CPTA_ushort()); - return CPTA_ushort(); + nassertr(false, NULL); + return NULL; } //////////////////////////////////////////////////////////////////// @@ -866,7 +929,7 @@ rotate_impl() const { // vertex that begins the new primitive. //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: -append_unused_vertices(PTA_ushort &, int) { +append_unused_vertices(qpGeomVertexArrayData *, int) { } //////////////////////////////////////////////////////////////////// @@ -877,7 +940,7 @@ append_unused_vertices(PTA_ushort &, int) { //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: recompute_minmax(qpGeomPrimitive::CDWriter &cdata) { - if (cdata->_vertices.empty()) { + if (cdata->_vertices->get_num_vertices() == 0) { cdata->_min_vertex = 0; cdata->_max_vertex = 0; cdata->_mins.clear(); @@ -886,55 +949,65 @@ recompute_minmax(qpGeomPrimitive::CDWriter &cdata) { } else if (get_num_vertices_per_primitive() == 0) { // This is a complex primitive type like a triangle strip; compute // the minmax of each primitive (as well as the overall minmax). - cdata->_mins = PTA_ushort::empty_array(cdata->_ends.size()); - cdata->_maxs = PTA_ushort::empty_array(cdata->_ends.size()); - + qpGeomVertexReader index(cdata->_vertices, 0); + + cdata->_mins = new qpGeomVertexArrayData + (cdata->_vertices->get_array_format(), UH_unspecified); + cdata->_maxs = new qpGeomVertexArrayData + (cdata->_vertices->get_array_format(), UH_unspecified); + + qpGeomVertexWriter mins(cdata->_mins, 0); + qpGeomVertexWriter maxs(cdata->_maxs, 0); + int pi = 0; int vi = 0; - int num_vertices = (int)cdata->_vertices.size(); - unsigned short vertex = cdata->_vertices[vi]; + unsigned int vertex = index.get_data1i(); cdata->_min_vertex = vertex; - cdata->_mins[pi] = vertex; cdata->_max_vertex = vertex; - cdata->_maxs[pi] = vertex; + unsigned int min_prim = vertex; + unsigned int max_prim = vertex; ++vi; - while (vi < num_vertices) { - unsigned short vertex = cdata->_vertices[vi]; + while (!index.is_at_end()) { + unsigned int vertex = index.get_data1i(); cdata->_min_vertex = min(cdata->_min_vertex, vertex); cdata->_max_vertex = max(cdata->_max_vertex, vertex); - + if (vi == cdata->_ends[pi]) { + mins.add_data1i(min_prim); + maxs.add_data1i(max_prim); + min_prim = vertex; + max_prim = vertex; ++pi; - if (pi < (int)cdata->_ends.size()) { - cdata->_mins[pi] = vertex; - cdata->_maxs[pi] = vertex; - } + } else { - nassertv(pi < (int)cdata->_ends.size()); - cdata->_mins[pi] = min(cdata->_mins[pi], vertex); - cdata->_maxs[pi] = max(cdata->_maxs[pi], vertex); + min_prim = min(min_prim, vertex); + max_prim = min(max_prim, vertex); } ++vi; } + mins.add_data1i(min_prim); + maxs.add_data1i(max_prim); + nassertv(mins.get_num_vertices() == cdata->_ends.size()); } else { // This is a simple primitive type like a triangle; just compute // the overall minmax. - PTA_ushort::const_iterator ii = cdata->_vertices.begin(); - cdata->_min_vertex = (*ii); - cdata->_max_vertex = (*ii); + qpGeomVertexReader index(cdata->_vertices, 0); + cdata->_mins.clear(); cdata->_maxs.clear(); - - ++ii; - while (ii != cdata->_vertices.end()) { - cdata->_min_vertex = min(cdata->_min_vertex, (*ii)); - cdata->_max_vertex = max(cdata->_max_vertex, (*ii)); - - ++ii; + + unsigned int vertex = index.get_data1i(); + cdata->_min_vertex = vertex; + cdata->_max_vertex = vertex; + + while (!index.is_at_end()) { + unsigned int vertex = index.get_data1i(); + cdata->_min_vertex = min(cdata->_min_vertex, vertex); + cdata->_max_vertex = max(cdata->_max_vertex, vertex); } } @@ -986,13 +1059,29 @@ make_copy() const { //////////////////////////////////////////////////////////////////// void qpGeomPrimitive::CData:: write_datagram(BamWriter *manager, Datagram &dg) const { - dg.add_uint8(_usage_hint); dg.add_uint8(_shade_model); + dg.add_uint8(_index_type); - WRITE_PTA(manager, dg, IPD_ushort::write_datagram, _vertices); + manager->write_pointer(dg, _vertices); WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + _vertices = DCAST(qpGeomVertexArrayData, p_list[pi++]); + + return pi; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::CData::fillin // Access: Public, Virtual @@ -1002,10 +1091,10 @@ write_datagram(BamWriter *manager, Datagram &dg) const { //////////////////////////////////////////////////////////////////// void qpGeomPrimitive::CData:: fillin(DatagramIterator &scan, BamReader *manager) { - _usage_hint = (UsageHint)scan.get_uint8(); _shade_model = (ShadeModel)scan.get_uint8(); - - READ_PTA(manager, scan, IPD_ushort::read_datagram, _vertices); + _index_type = (NumericType)scan.get_uint8(); + + manager->read_pointer(scan); READ_PTA(manager, scan, IPD_int::read_datagram, _ends); _modified = qpGeom::get_next_modified(); diff --git a/panda/src/gobj/qpgeomPrimitive.h b/panda/src/gobj/qpgeomPrimitive.h index 128746a7d4..3e231e4364 100644 --- a/panda/src/gobj/qpgeomPrimitive.h +++ b/panda/src/gobj/qpgeomPrimitive.h @@ -21,11 +21,11 @@ #include "pandabase.h" #include "qpgeomEnums.h" +#include "qpgeomVertexArrayData.h" #include "typedWritableReferenceCount.h" #include "luse.h" #include "updateSeq.h" #include "pointerTo.h" -#include "pta_ushort.h" #include "pta_int.h" #include "pStatCollector.h" #include "cycleData.h" @@ -63,6 +63,9 @@ class FactoryParams; // This is part of the experimental Geom rewrite. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA qpGeomPrimitive : public TypedWritableReferenceCount, public qpGeomEnums { +protected: + qpGeomPrimitive(); + PUBLISHED: qpGeomPrimitive(UsageHint usage_hint); qpGeomPrimitive(const qpGeomPrimitive ©); @@ -79,6 +82,9 @@ PUBLISHED: INLINE UsageHint get_usage_hint() const; INLINE void set_usage_hint(UsageHint usage_hint); + INLINE NumericType get_index_type() const; + void set_index_type(NumericType index_type); + // The following published methods are provided for safe, high-level // iteration through the vertices and sub-primitives within the // GeomPrimitive class. These work correctly regardless of the @@ -87,7 +93,7 @@ PUBLISHED: // composite primitive using these methods. INLINE int get_num_vertices() const; - INLINE int get_vertex(int i) const; + int get_vertex(int i) const; void add_vertex(int vertex); void add_consecutive_vertices(int start, int num_vertices); void add_next_vertices(int num_vertices); @@ -104,9 +110,9 @@ PUBLISHED: INLINE int get_primitive_num_faces(int n) const; INLINE int get_min_vertex() const; - INLINE int get_primitive_min_vertex(int n) const; + int get_primitive_min_vertex(int n) const; INLINE int get_max_vertex() const; - INLINE int get_primitive_max_vertex(int n) const; + int get_primitive_max_vertex(int n) const; CPT(qpGeomPrimitive) decompose() const; CPT(qpGeomPrimitive) rotate() const; @@ -131,16 +137,19 @@ public: // recommended that application-level code use the above interfaces // instead. - INLINE CPTA_ushort get_vertices() const; - PTA_ushort modify_vertices(); - void set_vertices(CPTA_ushort vertices); + INLINE const qpGeomVertexArrayData *get_vertices() const; + qpGeomVertexArrayData *modify_vertices(); + void set_vertices(const qpGeomVertexArrayData *vertices); + + INLINE int get_index_stride() const; + INLINE CPTA_uchar get_data() const; INLINE CPTA_int get_ends() const; PTA_int modify_ends(); void set_ends(CPTA_int ends); - INLINE CPTA_ushort get_mins() const; - INLINE CPTA_ushort get_maxs() const; + INLINE const qpGeomVertexArrayData *get_mins() const; + INLINE const qpGeomVertexArrayData *get_maxs() const; virtual int get_num_vertices_per_primitive() const; virtual int get_min_num_vertices_per_primitive() const; @@ -167,8 +176,9 @@ public: protected: virtual CPT(qpGeomPrimitive) decompose_impl() const; - virtual CPTA_ushort rotate_impl() const; - virtual void append_unused_vertices(PTA_ushort &vertices, int vertex); + virtual CPT(qpGeomVertexArrayData) rotate_impl() const; + virtual void append_unused_vertices(qpGeomVertexArrayData *vertices, + int vertex); private: // A GeomPrimitive keeps a list (actually, a map) of all the @@ -186,14 +196,15 @@ private: INLINE CData(const CData ©); virtual CycleData *make_copy() const; virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); virtual void fillin(DatagramIterator &scan, BamReader *manager); - UsageHint _usage_hint; ShadeModel _shade_model; - PTA_ushort _vertices; + NumericType _index_type; + PT(qpGeomVertexArrayData) _vertices; PTA_int _ends; - PTA_ushort _mins; - PTA_ushort _maxs; + PT(qpGeomVertexArrayData) _mins; + PT(qpGeomVertexArrayData) _maxs; UpdateSeq _modified; bool _got_minmax; diff --git a/panda/src/gobj/qpgeomTriangles.cxx b/panda/src/gobj/qpgeomTriangles.cxx index cf08ef3af2..9eb91f6966 100644 --- a/panda/src/gobj/qpgeomTriangles.cxx +++ b/panda/src/gobj/qpgeomTriangles.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "qpgeomTriangles.h" +#include "qpgeomVertexRewriter.h" #include "pStatTimer.h" #include "bamReader.h" #include "bamWriter.h" @@ -110,25 +111,31 @@ draw(GraphicsStateGuardianBase *gsg) const { // Access: Protected, Virtual // Description: The virtual implementation of do_rotate(). //////////////////////////////////////////////////////////////////// -CPTA_ushort qpGeomTriangles:: +CPT(qpGeomVertexArrayData) qpGeomTriangles:: rotate_impl() const { // To rotate triangles, we just move one vertex from the front to // the back, or vice-versa; but we have to know what direction we're // going. - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); ShadeModel shade_model = get_shade_model(); - PTA_ushort new_vertices; - new_vertices.reserve(vertices.size()); + PT(qpGeomVertexArrayData) new_vertices = + new qpGeomVertexArrayData(*vertices); + qpGeomVertexReader from(vertices, 0); + qpGeomVertexWriter to(new_vertices, 0); + int num_vertices = vertices->get_num_vertices(); + switch (shade_model) { case SM_flat_first_vertex: // Move the first vertex to the end. { - for (int begin = 0; begin < (int)vertices.size(); begin += 3) { - new_vertices.push_back(vertices[begin + 1]); - new_vertices.push_back(vertices[begin + 2]); - new_vertices.push_back(vertices[begin]); + for (int begin = 0; begin < num_vertices; begin += 3) { + from.set_vertex(begin + 1); + to.set_data1i(from.get_data1i()); + to.set_data1i(from.get_data1i()); + from.set_vertex(begin); + to.set_data1i(from.get_data1i()); } } break; @@ -136,10 +143,12 @@ rotate_impl() const { case SM_flat_last_vertex: // Move the last vertex to the front. { - for (int begin = 0; begin < (int)vertices.size(); begin += 3) { - new_vertices.push_back(vertices[begin + 2]); - new_vertices.push_back(vertices[begin]); - new_vertices.push_back(vertices[begin + 1]); + for (int begin = 0; begin < num_vertices; begin += 3) { + from.set_vertex(begin + 2); + to.set_data1i(from.get_data1i()); + from.set_vertex(begin); + to.set_data1i(from.get_data1i()); + to.set_data1i(from.get_data1i()); } } break; @@ -149,7 +158,7 @@ rotate_impl() const { nassertr(false, vertices); } - nassertr(new_vertices.size() == vertices.size(), vertices); + nassertr(to.is_at_end(), NULL); return new_vertices; } diff --git a/panda/src/gobj/qpgeomTriangles.h b/panda/src/gobj/qpgeomTriangles.h index 33dd045085..fbef160669 100644 --- a/panda/src/gobj/qpgeomTriangles.h +++ b/panda/src/gobj/qpgeomTriangles.h @@ -44,7 +44,7 @@ public: virtual void draw(GraphicsStateGuardianBase *gsg) const; protected: - virtual CPTA_ushort rotate_impl() const; + virtual CPT(qpGeomVertexArrayData) rotate_impl() const; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomTrifans.cxx b/panda/src/gobj/qpgeomTrifans.cxx index ccf0dd86eb..9af598eafb 100644 --- a/panda/src/gobj/qpgeomTrifans.cxx +++ b/panda/src/gobj/qpgeomTrifans.cxx @@ -18,6 +18,7 @@ #include "qpgeomTrifans.h" #include "qpgeomTriangles.h" +#include "qpgeomVertexRewriter.h" #include "bamReader.h" #include "bamWriter.h" @@ -119,33 +120,35 @@ CPT(qpGeomPrimitive) qpGeomTrifans:: decompose_impl() const { PT(qpGeomTriangles) triangles = new qpGeomTriangles(get_usage_hint()); triangles->set_shade_model(get_shade_model()); - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); + qpGeomVertexReader index(vertices, 0); CPTA_int ends = get_ends(); + int num_vertices = vertices->get_num_vertices(); + int vi = 0; int li = 0; while (li < (int)ends.size()) { int end = ends[li]; nassertr(vi + 2 <= end, triangles.p()); - nassertr(vi < (int)vertices.size(), this); - int v0 = vertices[vi]; + int v0 = index.get_data1i(); ++vi; - nassertr(vi < (int)vertices.size(), this); - int v1 = vertices[vi]; + int v1 = index.get_data1i(); ++vi; while (vi < end) { + int v2 = index.get_data1i(); + ++vi; triangles->add_vertex(v0); triangles->add_vertex(v1); - triangles->add_vertex(vertices[vi]); - nassertr(vi < (int)vertices.size(), this); - v1 = vertices[vi]; + triangles->add_vertex(v2); + nassertr(vi < num_vertices, this); + v1 = v2; triangles->close_primitive(); - ++vi; } ++li; } - nassertr(vi == (int)vertices.size(), triangles.p()); + nassertr(vi == num_vertices && index.is_at_end(), NULL); return triangles.p(); } @@ -155,12 +158,12 @@ decompose_impl() const { // Access: Protected, Virtual // Description: The virtual implementation of do_rotate(). //////////////////////////////////////////////////////////////////// -CPTA_ushort qpGeomTrifans:: +CPT(qpGeomVertexArrayData) qpGeomTrifans:: rotate_impl() const { // Actually, we can't rotate fans without chaging the winding order. // It's an error to define a flat shade model for a GeomTrifan. - nassertr(false, CPTA_ushort()); - return CPTA_ushort(); + nassertr(false, NULL); + return NULL; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomTrifans.h b/panda/src/gobj/qpgeomTrifans.h index 00b0f89f09..5e81511a55 100644 --- a/panda/src/gobj/qpgeomTrifans.h +++ b/panda/src/gobj/qpgeomTrifans.h @@ -44,7 +44,7 @@ public: protected: virtual CPT(qpGeomPrimitive) decompose_impl() const; - virtual CPTA_ushort rotate_impl() const; + virtual CPT(qpGeomVertexArrayData) rotate_impl() const; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomTristrips.cxx b/panda/src/gobj/qpgeomTristrips.cxx index 733d78bf64..892d0e041d 100644 --- a/panda/src/gobj/qpgeomTristrips.cxx +++ b/panda/src/gobj/qpgeomTristrips.cxx @@ -18,6 +18,7 @@ #include "qpgeomTristrips.h" #include "qpgeomTriangles.h" +#include "qpgeomVertexRewriter.h" #include "pStatTimer.h" #include "bamReader.h" #include "bamWriter.h" @@ -134,9 +135,12 @@ CPT(qpGeomPrimitive) qpGeomTristrips:: decompose_impl() const { PT(qpGeomTriangles) triangles = new qpGeomTriangles(get_usage_hint()); triangles->set_shade_model(get_shade_model()); - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); + qpGeomVertexReader index(vertices, 0); CPTA_int ends = get_ends(); + int num_vertices = vertices->get_num_vertices(); + // We need a slightly different algorithm for SM_flat_first_vertex // than for SM_flat_last_vertex, to preserve the key vertex in the // right place. The remaining shade models can use either @@ -149,35 +153,34 @@ decompose_impl() const { while (li < (int)ends.size()) { // Skip unused vertices between tristrips. vi += 2; + index.set_vertex(vi); int end = ends[li]; - nassertr(vi + 2 <= end, triangles.p()); - nassertr(vi < (int)vertices.size(), this); - int v0 = vertices[vi]; + nassertr(vi + 2 <= end, NULL); + int v0 = index.get_data1i(); ++vi; - nassertr(vi < (int)vertices.size(), this); - int v1 = vertices[vi]; + int v1 = index.get_data1i(); ++vi; bool reversed = false; while (vi < end) { triangles->add_vertex(v0); + int v2 = index.get_data1i(); + ++vi; if (reversed) { - triangles->add_vertex(vertices[vi]); + triangles->add_vertex(v2); triangles->add_vertex(v1); reversed = false; } else { triangles->add_vertex(v1); - triangles->add_vertex(vertices[vi]); + triangles->add_vertex(v2); reversed = true; } v0 = v1; - nassertr(vi < (int)vertices.size(), this); - v1 = vertices[vi]; + v1 = v2; triangles->close_primitive(); - ++vi; } ++li; } - nassertr(vi == (int)vertices.size(), triangles.p()); + nassertr(vi == num_vertices && index.is_at_end(), NULL); } else { // Preserve the last vertex of each component triangle as the @@ -187,13 +190,12 @@ decompose_impl() const { while (li < (int)ends.size()) { // Skip unused vertices between tristrips. vi += 2; + index.set_vertex(vi); int end = ends[li]; - nassertr(vi + 2 <= end, triangles.p()); - nassertr(vi < (int)vertices.size(), this); - int v0 = vertices[vi]; + nassertr(vi + 2 <= end, NULL); + int v0 = index.get_data1i(); ++vi; - nassertr(vi < (int)vertices.size(), this); - int v1 = vertices[vi]; + int v1 = index.get_data1i(); ++vi; bool reversed = false; while (vi < end) { @@ -206,16 +208,16 @@ decompose_impl() const { triangles->add_vertex(v1); reversed = true; } - triangles->add_vertex(vertices[vi]); - v0 = v1; - nassertr(vi < (int)vertices.size(), this); - v1 = vertices[vi]; - triangles->close_primitive(); + int v2 = index.get_data1i(); ++vi; + triangles->add_vertex(v2); + v0 = v1; + v1 = v2; + triangles->close_primitive(); } ++li; } - nassertr(vi == (int)vertices.size(), triangles.p()); + nassertr(vi == num_vertices && index.is_at_end(), NULL); } return triangles.p(); @@ -226,21 +228,24 @@ decompose_impl() const { // Access: Protected, Virtual // Description: The virtual implementation of do_rotate(). //////////////////////////////////////////////////////////////////// -CPTA_ushort qpGeomTristrips:: +CPT(qpGeomVertexArrayData) qpGeomTristrips:: rotate_impl() const { // To rotate a triangle strip with an even number of vertices, we // just reverse the vertices. But if we have an odd number of // vertices, that doesn't work--in fact, nothing works (without also // changing the winding order), so we don't allow an odd number of // vertices in a flat-shaded tristrip. - CPTA_ushort vertices = get_vertices(); + CPT(qpGeomVertexArrayData) vertices = get_vertices(); CPTA_int ends = get_ends(); - PTA_ushort new_vertices; - new_vertices.reserve(vertices.size()); + PT(qpGeomVertexArrayData) new_vertices = + new qpGeomVertexArrayData(*vertices); + qpGeomVertexReader from(vertices, 0); + qpGeomVertexWriter to(new_vertices, 0); bool any_odd = false; int begin = 0; + int last_added = 0; CPTA_int::const_iterator ei; for (ei = ends.begin(); ei != ends.end(); ++ei) { int end = (*ei); @@ -248,27 +253,25 @@ rotate_impl() const { if (begin != 0) { // Copy in the unused vertices between tristrips. - new_vertices.push_back(new_vertices.back()); - new_vertices.push_back(vertices[end - 1]); + to.set_data1i(last_added); + from.set_vertex(end - 1); + to.set_data1i(from.get_data1i()); begin += 2; } - if ((num_vertices & 1) == 0) { - for (int vi = end - 1; vi >= begin; --vi) { - new_vertices.push_back(vertices[vi]); - } - } else { - any_odd = true; + // If this assertion is triggered, there was a triangle strip with + // an odd number of vertices, which is not allowed. + nassertr((num_vertices & 1) == 0, NULL); + for (int vi = end - 1; vi >= begin; --vi) { + from.set_vertex(vi); + last_added = from.get_data1i(); + to.set_data1i(last_added); } begin = end; } - nassertr(new_vertices.size() == vertices.size(), vertices); - // If this assertion is triggered, there was a triangle strip with - // an odd number of vertices and either SM_flat_first_vertex or - // SM_flat_last_vertex specified--which is not allowed. - nassertr(!any_odd, CPTA_ushort()); + nassertr(to.is_at_end(), NULL); return new_vertices; } @@ -282,9 +285,16 @@ rotate_impl() const { // vertex that begins the new primitive. //////////////////////////////////////////////////////////////////// void qpGeomTristrips:: -append_unused_vertices(PTA_ushort &vertices, int vertex) { - vertices.push_back(vertices.back()); - vertices.push_back(vertex); +append_unused_vertices(qpGeomVertexArrayData *vertices, int vertex) { + qpGeomVertexReader from(vertices, 0); + from.set_vertex(from.get_num_vertices() - 1); + int prev = from.get_data1i(); + + qpGeomVertexWriter to(vertices, 0); + to.set_vertex(to.get_num_vertices()); + + to.add_data1i(prev); + to.add_data1i(vertex); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomTristrips.h b/panda/src/gobj/qpgeomTristrips.h index 080cb43065..456ba58a37 100644 --- a/panda/src/gobj/qpgeomTristrips.h +++ b/panda/src/gobj/qpgeomTristrips.h @@ -45,8 +45,9 @@ public: protected: virtual CPT(qpGeomPrimitive) decompose_impl() const; - virtual CPTA_ushort rotate_impl() const; - virtual void append_unused_vertices(PTA_ushort &vertices, int vertex); + virtual CPT(qpGeomVertexArrayData) rotate_impl() const; + virtual void append_unused_vertices(qpGeomVertexArrayData *vertices, + int vertex); public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomVertexColumn.cxx b/panda/src/gobj/qpgeomVertexColumn.cxx index b3ab47e659..8ee3a0d6e1 100644 --- a/panda/src/gobj/qpgeomVertexColumn.cxx +++ b/panda/src/gobj/qpgeomVertexColumn.cxx @@ -47,6 +47,10 @@ setup() { _component_bytes = 2; // sizeof(PN_uint16) break; + case NT_uint32: + _component_bytes = 4; // sizeof(PN_uint32) + break; + case NT_uint8: _component_bytes = 1; break; diff --git a/panda/src/gobj/qpgeomVertexReader.I b/panda/src/gobj/qpgeomVertexReader.I index a78138959a..e39091e8a4 100644 --- a/panda/src/gobj/qpgeomVertexReader.I +++ b/panda/src/gobj/qpgeomVertexReader.I @@ -25,15 +25,9 @@ //////////////////////////////////////////////////////////////////// INLINE qpGeomVertexReader:: qpGeomVertexReader(const qpGeomVertexData *vertex_data) : - _vertex_data(vertex_data), - _array(0), - _column(NULL), - _pointer(NULL), - _start_vertex(0), - _read_vertex(0), - _num_vertices(0), - _reader(NULL) + _vertex_data(vertex_data) { + initialize(); } //////////////////////////////////////////////////////////////////// @@ -45,15 +39,9 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data) : //////////////////////////////////////////////////////////////////// INLINE qpGeomVertexReader:: qpGeomVertexReader(const qpGeomVertexData *vertex_data, const string &name) : - _vertex_data(vertex_data), - _array(0), - _column(NULL), - _pointer(NULL), - _start_vertex(0), - _read_vertex(0), - _num_vertices(0), - _reader(NULL) + _vertex_data(vertex_data) { + initialize(); set_column(name); } @@ -67,18 +55,39 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data, const string &name) : INLINE qpGeomVertexReader:: qpGeomVertexReader(const qpGeomVertexData *vertex_data, const InternalName *name) : - _vertex_data(vertex_data), - _array(0), - _column(NULL), - _pointer(NULL), - _start_vertex(0), - _read_vertex(0), - _num_vertices(0), - _reader(NULL) + _vertex_data(vertex_data) { + initialize(); set_column(name); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexReader::Constructor +// Access: Published +// Description: Constructs a new reader to process the vertices of +// the indicated array only. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexReader:: +qpGeomVertexReader(const qpGeomVertexArrayData *array_data) : + _array_data(array_data) +{ + initialize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexReader::Constructor +// Access: Published +// Description: Constructs a new reader to process the vertices of +// the indicated array only. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexReader:: +qpGeomVertexReader(const qpGeomVertexArrayData *array_data, int column) : + _array_data(array_data) +{ + initialize(); + set_column(column); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexReader::Destructor // Access: Published @@ -96,13 +105,25 @@ INLINE qpGeomVertexReader:: // Function: qpGeomVertexReader::get_vertex_data // Access: Published // Description: Returns the vertex data object that the -// reader is processing. +// reader is processing. This may return NULL if the +// reader was constructed with just an array pointer. //////////////////////////////////////////////////////////////////// INLINE const qpGeomVertexData *qpGeomVertexReader:: get_vertex_data() const { return _vertex_data; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexReader::get_array_data +// Access: Published +// Description: Returns the particular array object that the +// reader is currently processing. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexArrayData *qpGeomVertexReader:: +get_array_data() const { + return _array_data; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexReader::set_column // Access: Published @@ -118,8 +139,14 @@ get_vertex_data() const { //////////////////////////////////////////////////////////////////// INLINE bool qpGeomVertexReader:: set_column(int column) { - return set_column(_vertex_data->get_format()->get_array_with(column), - _vertex_data->get_format()->get_column(column)); + if (_vertex_data != (const qpGeomVertexData *)NULL) { + return set_column(_vertex_data->get_format()->get_array_with(column), + _vertex_data->get_format()->get_column(column)); + } + if (_array_data != (const qpGeomVertexArrayData *)NULL) { + return set_column(0, _array_data->get_array_format()->get_column(column)); + } + return false; } //////////////////////////////////////////////////////////////////// @@ -155,8 +182,15 @@ set_column(const string &name) { //////////////////////////////////////////////////////////////////// INLINE bool qpGeomVertexReader:: set_column(const InternalName *name) { - return set_column(_vertex_data->get_format()->get_array_with(name), - _vertex_data->get_format()->get_column(name)); + if (_vertex_data != (const qpGeomVertexData *)NULL) { + return set_column(_vertex_data->get_format()->get_array_with(name), + _vertex_data->get_format()->get_column(name)); + } + if (_array_data != (const qpGeomVertexArrayData *)NULL) { + return set_column(0, _array_data->get_array_format()->get_column(name)); + } + + return false; } //////////////////////////////////////////////////////////////////// @@ -369,9 +403,11 @@ INLINE void qpGeomVertexReader:: set_pointer(int vertex) { nassertv(_column != (qpGeomVertexColumn *)NULL); _read_vertex = vertex; - CPT(qpGeomVertexArrayData) array_data = _vertex_data->get_array(_array); - _pointer = array_data->get_data() + _column->get_start() + _stride * _read_vertex; - _num_vertices = array_data->get_num_vertices(); + if (_vertex_data != (const qpGeomVertexData *)NULL) { + _array_data = _vertex_data->get_array(_array); + } + _pointer = _array_data->get_data() + _column->get_start() + _stride * _read_vertex; + _num_vertices = _array_data->get_num_vertices(); } //////////////////////////////////////////////////////////////////// @@ -382,8 +418,14 @@ set_pointer(int vertex) { //////////////////////////////////////////////////////////////////// INLINE const unsigned char *qpGeomVertexReader:: inc_pointer() { +#ifndef NDEBUG nassertr(_read_vertex < _num_vertices, empty_buffer); - nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer); + if (_vertex_data != (const qpGeomVertexData *)NULL){ + nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer); + } else { + nassertr(_pointer == _array_data->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer); + } +#endif const unsigned char *orig_pointer = _pointer; _pointer += _stride; diff --git a/panda/src/gobj/qpgeomVertexReader.cxx b/panda/src/gobj/qpgeomVertexReader.cxx index aa0f70b200..4b963e1654 100644 --- a/panda/src/gobj/qpgeomVertexReader.cxx +++ b/panda/src/gobj/qpgeomVertexReader.cxx @@ -41,14 +41,24 @@ const unsigned char qpGeomVertexReader::empty_buffer[100] = { 0 }; //////////////////////////////////////////////////////////////////// bool qpGeomVertexReader:: set_column(int array, const qpGeomVertexColumn *column) { + if (_vertex_data == (const qpGeomVertexData *)NULL && + _array_data == (const qpGeomVertexArrayData *)NULL) { + return false; + } + // Delete the old reader, if we've got one. if (_reader != (Reader *)NULL) { delete _reader; _reader = NULL; } - if (array < 0 || array >= _vertex_data->get_num_arrays() || - column == (qpGeomVertexColumn *)NULL) { + int num_arrays = 1; + if (_vertex_data != (const qpGeomVertexData *)NULL) { + num_arrays = _vertex_data->get_num_arrays(); + } + + if (array < 0 || array >= num_arrays || + column == (const qpGeomVertexColumn *)NULL) { // Clear the data type. _array = -1; _column = NULL; @@ -61,7 +71,11 @@ set_column(int array, const qpGeomVertexColumn *column) { } else { _array = array; _column = column; - _stride = _vertex_data->get_format()->get_array(_array)->get_stride(); + if (_vertex_data != (const qpGeomVertexData *)NULL) { + _stride = _vertex_data->get_format()->get_array(_array)->get_stride(); + } else { + _stride = _array_data->get_array_format()->get_stride(); + } set_pointer(_start_vertex); @@ -73,6 +87,22 @@ set_column(int array, const qpGeomVertexColumn *column) { } } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexReader::initialize +// Access: Private +// Description: Called only by the constructor. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexReader:: +initialize() { + _array = 0; + _column = NULL; + _pointer = NULL; + _start_vertex = 0; + _read_vertex = 0; + _num_vertices = 0; + _reader = NULL; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexReader::make_reader // Access: Private @@ -203,6 +233,9 @@ get_data1f(const unsigned char *pointer) { case NT_uint16: return *(const PN_uint16 *)pointer; + case NT_uint32: + return *(const PN_uint32 *)pointer; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -246,6 +279,13 @@ get_data2f(const unsigned char *pointer) { } return _v2; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _v2.set(pi[0], pi[1]); + } + return _v2; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -306,6 +346,13 @@ get_data3f(const unsigned char *pointer) { } return _v3; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _v3.set(pi[0], pi[1], pi[2]); + } + return _v3; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -375,6 +422,13 @@ get_data4f(const unsigned char *pointer) { } return _v4; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _v4.set(pi[0], pi[1], pi[2], pi[3]); + } + return _v4; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -421,6 +475,9 @@ get_data1i(const unsigned char *pointer) { case NT_uint16: return *(const PN_uint16 *)pointer; + case NT_uint32: + return *(const PN_uint32 *)pointer; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -470,6 +527,14 @@ get_data2i(const unsigned char *pointer) { } return _i; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _i[0] = pi[0]; + _i[1] = pi[1]; + } + return _i; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -539,6 +604,15 @@ get_data3i(const unsigned char *pointer) { } return _i; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _i[0] = pi[0]; + _i[1] = pi[1]; + _i[2] = pi[2]; + } + return _i; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -625,6 +699,16 @@ get_data4i(const unsigned char *pointer) { } return _i; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _i[0] = pi[0]; + _i[1] = pi[1]; + _i[2] = pi[2]; + _i[3] = pi[3]; + } + return _i; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -746,6 +830,13 @@ get_data4f(const unsigned char *pointer) { } return _v4; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _v4.set(pi[0], pi[1], pi[2], pi[3]); + } + return _v4; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; @@ -817,6 +908,13 @@ get_data4f(const unsigned char *pointer) { } return _v4; + case NT_uint32: + { + const PN_uint32 *pi = (const PN_uint32 *)pointer; + _v4.set(pi[0], pi[1], pi[2], pi[3]); + } + return _v4; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; diff --git a/panda/src/gobj/qpgeomVertexReader.h b/panda/src/gobj/qpgeomVertexReader.h index e47a5e1866..fa332820af 100644 --- a/panda/src/gobj/qpgeomVertexReader.h +++ b/panda/src/gobj/qpgeomVertexReader.h @@ -66,9 +66,13 @@ PUBLISHED: const string &name); INLINE qpGeomVertexReader(const qpGeomVertexData *vertex_data, const InternalName *name); + INLINE qpGeomVertexReader(const qpGeomVertexArrayData *array_data); + INLINE qpGeomVertexReader(const qpGeomVertexArrayData *array_data, + int column); INLINE ~qpGeomVertexReader(); INLINE const qpGeomVertexData *get_vertex_data() const; + INLINE const qpGeomVertexArrayData *get_array_data() const; INLINE bool set_column(int column); INLINE bool set_column(const string &name); @@ -99,11 +103,14 @@ PUBLISHED: private: class Reader; + void initialize(); + INLINE void set_pointer(int vertex); INLINE const unsigned char *inc_pointer(); Reader *make_reader() const; CPT(qpGeomVertexData) _vertex_data; + CPT(qpGeomVertexArrayData) _array_data; int _array; const qpGeomVertexColumn *_column; int _stride; diff --git a/panda/src/gobj/qpgeomVertexRewriter.I b/panda/src/gobj/qpgeomVertexRewriter.I index b9e76dac2c..a3d1ffcda7 100644 --- a/panda/src/gobj/qpgeomVertexRewriter.I +++ b/panda/src/gobj/qpgeomVertexRewriter.I @@ -60,6 +60,33 @@ qpGeomVertexRewriter(qpGeomVertexData *vertex_data, const InternalName *name) : set_column(name); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::Constructor +// Access: Published +// Description: Constructs a new rewriter to process the vertices of +// the indicated array only. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexRewriter:: +qpGeomVertexRewriter(qpGeomVertexArrayData *array_data) : + qpGeomVertexWriter(array_data), + qpGeomVertexReader(array_data) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::Constructor +// Access: Published +// Description: Constructs a new rewriter to process the vertices of +// the indicated array only. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexRewriter:: +qpGeomVertexRewriter(qpGeomVertexArrayData *array_data, int column) : + qpGeomVertexWriter(array_data), + qpGeomVertexReader(array_data) +{ + set_column(column); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexRewriter::Destructor // Access: Published @@ -82,6 +109,19 @@ get_vertex_data() const { return qpGeomVertexWriter::get_vertex_data(); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::get_array_data +// Access: Published +// Description: Returns the particular array object that the +// rewriter is currently processing. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexArrayData *qpGeomVertexRewriter:: +get_array_data() const { + nassertr(qpGeomVertexWriter::get_array_data() == + qpGeomVertexReader::get_array_data(), NULL); + return qpGeomVertexWriter::get_array_data(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexRewriter::set_column // Access: Published diff --git a/panda/src/gobj/qpgeomVertexRewriter.h b/panda/src/gobj/qpgeomVertexRewriter.h index b019a9d8a5..d0e2a94e11 100644 --- a/panda/src/gobj/qpgeomVertexRewriter.h +++ b/panda/src/gobj/qpgeomVertexRewriter.h @@ -49,9 +49,13 @@ PUBLISHED: const string &name); INLINE qpGeomVertexRewriter(qpGeomVertexData *vertex_data, const InternalName *name); + INLINE qpGeomVertexRewriter(qpGeomVertexArrayData *array_data); + INLINE qpGeomVertexRewriter(qpGeomVertexArrayData *array_data, + int column); INLINE ~qpGeomVertexRewriter(); INLINE qpGeomVertexData *get_vertex_data() const; + INLINE qpGeomVertexArrayData *get_array_data() const; INLINE bool set_column(int column); INLINE bool set_column(const string &name); diff --git a/panda/src/gobj/qpgeomVertexWriter.I b/panda/src/gobj/qpgeomVertexWriter.I index de2a17643f..25fbd9037d 100644 --- a/panda/src/gobj/qpgeomVertexWriter.I +++ b/panda/src/gobj/qpgeomVertexWriter.I @@ -25,15 +25,9 @@ //////////////////////////////////////////////////////////////////// INLINE qpGeomVertexWriter:: qpGeomVertexWriter(qpGeomVertexData *vertex_data) : - _vertex_data(vertex_data), - _array(0), - _column(NULL), - _pointer(NULL), - _start_vertex(0), - _write_vertex(0), - _num_vertices(0), - _writer(NULL) + _vertex_data(vertex_data) { + initialize(); } //////////////////////////////////////////////////////////////////// @@ -45,15 +39,9 @@ qpGeomVertexWriter(qpGeomVertexData *vertex_data) : //////////////////////////////////////////////////////////////////// INLINE qpGeomVertexWriter:: qpGeomVertexWriter(qpGeomVertexData *vertex_data, const string &name) : - _vertex_data(vertex_data), - _array(0), - _column(NULL), - _pointer(NULL), - _start_vertex(0), - _write_vertex(0), - _num_vertices(0), - _writer(NULL) + _vertex_data(vertex_data) { + initialize(); set_column(name); } @@ -66,18 +54,39 @@ qpGeomVertexWriter(qpGeomVertexData *vertex_data, const string &name) : //////////////////////////////////////////////////////////////////// INLINE qpGeomVertexWriter:: qpGeomVertexWriter(qpGeomVertexData *vertex_data, const InternalName *name) : - _vertex_data(vertex_data), - _array(0), - _column(NULL), - _pointer(NULL), - _start_vertex(0), - _write_vertex(0), - _num_vertices(0), - _writer(NULL) + _vertex_data(vertex_data) { + initialize(); set_column(name); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexWriter::Constructor +// Access: Published +// Description: Constructs a new writer to process the vertices of +// the indicated array only. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexWriter:: +qpGeomVertexWriter(qpGeomVertexArrayData *array_data) : + _array_data(array_data) +{ + initialize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexWriter::Constructor +// Access: Published +// Description: Constructs a new writer to process the vertices of +// the indicated array only. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexWriter:: +qpGeomVertexWriter(qpGeomVertexArrayData *array_data, int column) : + _array_data(array_data) +{ + initialize(); + set_column(column); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexWriter::Destructor // Access: Published @@ -95,13 +104,25 @@ INLINE qpGeomVertexWriter:: // Function: qpGeomVertexWriter::get_vertex_data // Access: Published // Description: Returns the vertex data object that the -// writer is processing. +// writer is processing. This may return NULL if the +// writer was constructed with just an array pointer. //////////////////////////////////////////////////////////////////// INLINE qpGeomVertexData *qpGeomVertexWriter:: get_vertex_data() const { return _vertex_data; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexWriter::get_array_data +// Access: Published +// Description: Returns the particular array object that the +// writer is currently processing. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexArrayData *qpGeomVertexWriter:: +get_array_data() const { + return _array_data; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexWriter::set_column // Access: Published @@ -117,11 +138,14 @@ get_vertex_data() const { //////////////////////////////////////////////////////////////////// INLINE bool qpGeomVertexWriter:: set_column(int column) { - if (_vertex_data == (qpGeomVertexData *)NULL) { - return false; + if (_vertex_data != (qpGeomVertexData *)NULL) { + return set_column(_vertex_data->get_format()->get_array_with(column), + _vertex_data->get_format()->get_column(column)); } - return set_column(_vertex_data->get_format()->get_array_with(column), - _vertex_data->get_format()->get_column(column)); + if (_array_data != (qpGeomVertexArrayData *)NULL) { + return set_column(0, _array_data->get_array_format()->get_column(column)); + } + return false; } //////////////////////////////////////////////////////////////////// @@ -157,11 +181,15 @@ set_column(const string &name) { //////////////////////////////////////////////////////////////////// INLINE bool qpGeomVertexWriter:: set_column(const InternalName *name) { - if (_vertex_data == (qpGeomVertexData *)NULL) { - return false; + if (_vertex_data != (qpGeomVertexData *)NULL) { + return set_column(_vertex_data->get_format()->get_array_with(name), + _vertex_data->get_format()->get_column(name)); } - return set_column(_vertex_data->get_format()->get_array_with(name), - _vertex_data->get_format()->get_column(name)); + if (_array_data != (qpGeomVertexArrayData *)NULL) { + return set_column(0, _array_data->get_array_format()->get_column(name)); + } + + return false; } //////////////////////////////////////////////////////////////////// @@ -679,9 +707,11 @@ INLINE void qpGeomVertexWriter:: set_pointer(int vertex) { nassertv(_column != (qpGeomVertexColumn *)NULL); _write_vertex = vertex; - PT(qpGeomVertexArrayData) array_data = _vertex_data->modify_array(_array); - _pointer = array_data->modify_data() + _column->get_start() + _stride * _write_vertex; - _num_vertices = array_data->get_num_vertices(); + if (_vertex_data != (qpGeomVertexData *)NULL) { + _array_data = _vertex_data->modify_array(_array); + } + _pointer = _array_data->modify_data() + _column->get_start() + _stride * _write_vertex; + _num_vertices = _array_data->get_num_vertices(); } //////////////////////////////////////////////////////////////////// @@ -692,8 +722,14 @@ set_pointer(int vertex) { //////////////////////////////////////////////////////////////////// INLINE unsigned char *qpGeomVertexWriter:: inc_pointer() { +#ifndef NDEBUG nassertr(_write_vertex < _num_vertices, empty_buffer); - nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer); + if (_vertex_data != (qpGeomVertexData *)NULL){ + nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer); + } else { + nassertr(_pointer == _array_data->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer); + } +#endif unsigned char *orig_pointer = _pointer; _pointer += _stride; @@ -713,7 +749,11 @@ INLINE unsigned char *qpGeomVertexWriter:: inc_add_pointer() { if (_write_vertex >= _num_vertices) { // Reset the data pointer. - _vertex_data->set_num_vertices(max(_write_vertex + 1, _vertex_data->get_num_vertices())); + if (_vertex_data != (qpGeomVertexData *)NULL) { + _vertex_data->set_num_vertices(max(_write_vertex + 1, _vertex_data->get_num_vertices())); + } else { + _array_data->set_num_vertices(max(_write_vertex + 1, _array_data->get_num_vertices())); + } set_pointer(_write_vertex); } return inc_pointer(); diff --git a/panda/src/gobj/qpgeomVertexWriter.cxx b/panda/src/gobj/qpgeomVertexWriter.cxx index 1801be9a1c..f5149d2fba 100644 --- a/panda/src/gobj/qpgeomVertexWriter.cxx +++ b/panda/src/gobj/qpgeomVertexWriter.cxx @@ -41,7 +41,8 @@ unsigned char qpGeomVertexWriter::empty_buffer[100] = { 0 }; //////////////////////////////////////////////////////////////////// bool qpGeomVertexWriter:: set_column(int array, const qpGeomVertexColumn *column) { - if (_vertex_data == (qpGeomVertexData *)NULL) { + if (_vertex_data == (qpGeomVertexData *)NULL && + _array_data == (qpGeomVertexArrayData *)NULL) { return false; } @@ -51,8 +52,13 @@ set_column(int array, const qpGeomVertexColumn *column) { _writer = NULL; } - if (array < 0 || array >= _vertex_data->get_num_arrays() || - column == (qpGeomVertexColumn *)NULL) { + int num_arrays = 1; + if (_vertex_data != (qpGeomVertexData *)NULL) { + num_arrays = _vertex_data->get_num_arrays(); + } + + if (array < 0 || array >= num_arrays || + column == (const qpGeomVertexColumn *)NULL) { // Clear the data type. _array = -1; _column = NULL; @@ -65,7 +71,11 @@ set_column(int array, const qpGeomVertexColumn *column) { } else { _array = array; _column = column; - _stride = _vertex_data->get_format()->get_array(_array)->get_stride(); + if (_vertex_data != (qpGeomVertexData *)NULL) { + _stride = _vertex_data->get_format()->get_array(_array)->get_stride(); + } else { + _stride = _array_data->get_array_format()->get_stride(); + } set_pointer(_start_vertex); @@ -77,6 +87,22 @@ set_column(int array, const qpGeomVertexColumn *column) { } } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexWriter::initialize +// Access: Private +// Description: Called only by the constructor. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexWriter:: +initialize() { + _array = 0; + _column = NULL; + _pointer = NULL; + _start_vertex = 0; + _write_vertex = 0; + _num_vertices = 0; + _writer = NULL; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexWriter::make_writer // Access: Private @@ -189,6 +215,10 @@ set_data1f(unsigned char *pointer, float data) { *(PN_uint16 *)pointer = (unsigned int)data; break; + case NT_uint32: + *(PN_uint32 *)pointer = (unsigned int)data; + break; + case NT_packed_dcba: case NT_packed_dabc: nassertv(false); @@ -241,6 +271,14 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { } break; + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = (unsigned int)data[0]; + pi[1] = (unsigned int)data[1]; + } + break; + case NT_packed_dcba: case NT_packed_dabc: nassertv(false); @@ -300,6 +338,15 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { } break; + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = (unsigned int)data[0]; + pi[1] = (unsigned int)data[1]; + pi[2] = (unsigned int)data[2]; + } + break; + case NT_packed_dcba: case NT_packed_dabc: nassertv(false); @@ -361,6 +408,16 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { pi[3] = (unsigned int)data[3]; } break; + + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = (unsigned int)data[0]; + pi[1] = (unsigned int)data[1]; + pi[2] = (unsigned int)data[2]; + pi[3] = (unsigned int)data[3]; + } + break; case NT_packed_dcba: maybe_scale_color(data); @@ -398,10 +455,17 @@ set_data1i(unsigned char *pointer, int a) { switch (_column->get_numeric_type()) { case NT_uint8: *pointer = a; + nassertv((*pointer) == a); break; case NT_uint16: *(PN_uint16 *)pointer = a; + nassertv(*(PN_uint16 *)pointer == a); + break; + + case NT_uint32: + *(PN_uint32 *)pointer = a; + nassertv(*(PN_uint32 *)pointer == a); break; case NT_packed_dcba: @@ -455,6 +519,14 @@ set_data2i(unsigned char *pointer, int a, int b) { pi[1] = b; } break; + + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = a; + pi[1] = b; + } + break; case NT_packed_dcba: case NT_packed_dabc: @@ -513,6 +585,15 @@ set_data3i(unsigned char *pointer, int a, int b, int c) { pi[2] = c; } break; + + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = a; + pi[1] = b; + pi[2] = c; + } + break; case NT_packed_dcba: case NT_packed_dabc: @@ -574,6 +655,16 @@ set_data4i(unsigned char *pointer, int a, int b, int c, int d) { pi[3] = d; } break; + + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = a; + pi[1] = b; + pi[2] = c; + pi[3] = d; + } + break; case NT_packed_dcba: *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(d, c, b, a); @@ -678,6 +769,16 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { pi[3] = (unsigned int)data[3]; } break; + + case NT_uint32: + { + PN_uint32 *pi = (PN_uint32 *)pointer; + pi[0] = (unsigned int)data[0]; + pi[1] = (unsigned int)data[1]; + pi[2] = (unsigned int)data[2]; + pi[3] = (unsigned int)data[3]; + } + break; case NT_packed_dcba: maybe_scale_color(data); @@ -846,4 +947,5 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { void qpGeomVertexWriter::Writer_uint16_1:: set_data1i(unsigned char *pointer, int data) { *(PN_uint16 *)pointer = data; + nassertv(*(PN_uint16 *)pointer == data); } diff --git a/panda/src/gobj/qpgeomVertexWriter.h b/panda/src/gobj/qpgeomVertexWriter.h index 7457be1ce2..655e7165aa 100644 --- a/panda/src/gobj/qpgeomVertexWriter.h +++ b/panda/src/gobj/qpgeomVertexWriter.h @@ -79,9 +79,13 @@ PUBLISHED: const string &name); INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data, const InternalName *name); + INLINE qpGeomVertexWriter(qpGeomVertexArrayData *array_data); + INLINE qpGeomVertexWriter(qpGeomVertexArrayData *array_data, + int column); INLINE ~qpGeomVertexWriter(); INLINE qpGeomVertexData *get_vertex_data() const; + INLINE qpGeomVertexArrayData *get_array_data() const; INLINE bool set_column(int column); INLINE bool set_column(const string &name); @@ -134,12 +138,15 @@ PUBLISHED: private: class Writer; + void initialize(); + INLINE void set_pointer(int vertex); INLINE unsigned char *inc_pointer(); INLINE unsigned char *inc_add_pointer(); Writer *make_writer() const; PT(qpGeomVertexData) _vertex_data; + PT(qpGeomVertexArrayData) _array_data; int _array; const qpGeomVertexColumn *_column; int _stride; diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 29d59f579c..7dc6b15889 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -264,18 +264,18 @@ munge_points_to_quads(const CullTraverser *traverser) { int num_points = primitive->get_max_vertex() + 1; int num_vertices = primitive->get_num_vertices(); PointData *points = (PointData *)alloca(num_points * sizeof(PointData)); - unsigned short *vertices = (unsigned short *)alloca(num_vertices * sizeof(unsigned short)); - unsigned short *vertices_end = vertices + num_vertices; + unsigned int *vertices = (unsigned int *)alloca(num_vertices * sizeof(unsigned int)); + unsigned int *vertices_end = vertices + num_vertices; - memcpy(vertices, primitive->get_vertices(), - num_vertices * sizeof(unsigned short)); - - unsigned short *vi; + qpGeomVertexReader index(primitive->get_vertices(), 0); + unsigned int *vi; for (vi = vertices; vi != vertices_end; ++vi) { // Get the point in eye-space coordinates. - vertex.set_vertex(*vi); - points[*vi]._eye = modelview.xform_point(vertex.get_data3f()); - points[*vi]._dist = gsg->compute_distance_to(points[*vi]._eye); + unsigned int v = index.get_data1i(); + (*vi) = v; + vertex.set_vertex(v); + points[v]._eye = modelview.xform_point(vertex.get_data3f()); + points[v]._dist = gsg->compute_distance_to(points[v]._eye); } // Now sort the points in order from back-to-front so they will