diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 2d1162464b..bfeec77c3c 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -748,6 +748,15 @@ void GraphicsStateGuardian:: draw_points(const qpGeomPoints *) { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::draw_sprites +// Access: Public, Virtual +// Description: Draws a series of rectangular sprite polygons. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +draw_sprites(const qpGeomSprites *) { +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::end_draw_primitives() // Access: Public, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index d9295afeb5..3938687581 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -160,6 +160,7 @@ public: virtual void draw_lines(const qpGeomLines *primitive); virtual void draw_linestrips(const qpGeomLinestrips *primitive); virtual void draw_points(const qpGeomPoints *primitive); + virtual void draw_sprites(const qpGeomSprites *primitive); virtual void end_draw_primitives(); virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index 26cd017c5f..ff853ac51c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -526,3 +526,14 @@ issue_flat_shading(Geom *geom) { // Otherwise, it's a uniform-colored primitive; we can take either one. } } + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::SpriteData::Ordering +// Access: Public +// Description: Orders the sprites from back-to-front for correct +// transparency sorting in draw_sprites(). +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(GraphicsStateGuardian)::SpriteData:: +operator < (const SpriteData &other) const { + return _eye[2] < other._eye[2]; +} diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index f2890083ff..ce4926eede 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -28,6 +28,8 @@ #include "qpgeomLines.h" #include "qpgeomLinestrips.h" #include "qpgeomPoints.h" +#include "qpgeomSprites.h" +#include "qpgeomVertexReader.h" #include "graphicsWindow.h" #include "lens.h" #include "perspectiveLens.h" @@ -62,6 +64,7 @@ #include "pnmImage.h" #include "config_gobj.h" #include "mutexHolder.h" +#include "indirectLess.h" #ifdef DO_PSTATS #include "pStatTimer.h" #endif @@ -138,6 +141,10 @@ issue_scaled_color_gl(const Geom *geom, Geom::ColorIterator &citerator, // defined by the GL, just so it will always be safe to call the // extension functions. +static void APIENTRY +null_glPointParameterfv(GLenum, const GLfloat *) { +} + static void APIENTRY null_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { @@ -364,6 +371,31 @@ reset() { get_extra_extensions(); report_extensions(); + _supports_point_parameters = false; + + if (is_at_least_version(1, 4)) { + _supports_point_parameters = true; + _glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) + get_extension_func(GLPREFIX_QUOTED, "PointParameterfv"); + + } else if (has_extension("GL_ARB_point_parameters")) { + _supports_point_parameters = true; + _glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) + get_extension_func(GLPREFIX_QUOTED, "PointParameterfvARB"); + } + if (_supports_point_parameters) { + if (_glPointParameterfv == NULL) { + GLCAT.warning() + << "glPointParameterfv advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; + _supports_point_parameters = false; + } + } + if (!_supports_point_parameters) { + _glPointParameterfv = null_glPointParameterfv; + } + + _supports_point_sprite = false; + _supports_vertex_blend = has_extension("GL_ARB_vertex_blend"); if (_supports_vertex_blend) { @@ -764,8 +796,7 @@ reset() { << "max clip planes = " << _max_clip_planes << "\n"; } - _current_projection_mat = LMatrix4f::ident_mat(); - _projection_mat_stack_count = 0; + _projection_mat = LMatrix4f::ident_mat(); if (_supports_multitexture) { GLint max_texture_stages; @@ -786,6 +817,8 @@ reset() { _last_max_stage_index = 0; _auto_antialias_mode = false; _render_mode = RenderModeAttrib::M_filled; + _point_size = 1.0f; + _point_perspective = false; _transform_stale = false; _vertex_blending_enabled = false; @@ -915,6 +948,8 @@ prepare_display_region() { GLCAT.error() << "Invalid NULL display region in prepare_display_region()\n"; enable_scissor(false); + _viewport_width = 1; + _viewport_height = 1; } else if (_current_display_region != _actual_display_region) { _actual_display_region = _current_display_region; @@ -926,11 +961,15 @@ prepare_display_region() { GLsizei width = GLsizei(w); GLsizei height = GLsizei(h); - enable_scissor( true ); - GLP(Scissor)( x, y, width, height ); - GLP(Viewport)( x, y, width, height ); + enable_scissor(true); + GLP(Scissor)(x, y, width, height); + GLP(Viewport)(x, y, width, height); + _viewport_width = width; + _viewport_height = height; } report_my_gl_errors(); + + do_point_size(); } //////////////////////////////////////////////////////////////////// @@ -955,7 +994,7 @@ prepare_lens() { return false; } - const LMatrix4f &projection_mat = _current_lens->get_projection_mat(); + const LMatrix4f &lens_mat = _current_lens->get_projection_mat(); // The projection matrix must always be right-handed Y-up, even if // our coordinate system of choice is otherwise, because certain GL @@ -964,25 +1003,27 @@ prepare_lens() { // other arbitrary) coordinate system, we'll use a Y-up projection // matrix, and store the conversion to our coordinate system of // choice in the modelview matrix. - LMatrix4f new_projection_mat = + _projection_mat = LMatrix4f::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) * - projection_mat; + lens_mat; if (_scene_setup->get_inverted()) { // If the scene is supposed to be inverted, then invert the // projection matrix. static LMatrix4f invert_mat = LMatrix4f::scale_mat(1.0f, -1.0f, 1.0f); - new_projection_mat *= invert_mat; + _projection_mat *= invert_mat; } #ifdef GSG_VERBOSE GLCAT.spam() - << "glMatrixMode(GL_PROJECTION): " << new_projection_mat << endl; + << "glMatrixMode(GL_PROJECTION): " << _projection_mat << endl; #endif GLP(MatrixMode)(GL_PROJECTION); - GLP(LoadMatrixf)(new_projection_mat.get_data()); + GLP(LoadMatrixf)(_projection_mat.get_data()); report_my_gl_errors(); + do_point_size(); + return true; } @@ -2513,6 +2554,169 @@ draw_points(const qpGeomPoints *primitive) { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::draw_sprites +// Access: Public, Virtual +// Description: Draws a series of rectangular sprite polygons. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +draw_sprites(const qpGeomSprites *primitive) { + bool has_rotate = _vertex_data->has_column(InternalName::get_rotate()); + bool has_scale_x = _vertex_data->has_column(InternalName::get_scale_x()); + bool has_scale_y = _vertex_data->has_column(InternalName::get_scale_y()); + if (!_supports_point_sprite || + has_rotate || has_scale_x || has_scale_y) { + // In this case, we have to draw the sprites as a series of + // polygons, because either the GL doesn't support the + // point_sprite extension, or the vertex data requires some + // nonstandard adjustments not covered by point_sprite. + + // This is kind of a shame because we have already prepared the + // vertex buffer, and it turns out we're not going to use it. Oh + // well, too bad. + + // Now clear the projection and modelview matrices, since we'll do + // the transformation to camera space ourselves. + GLP(MatrixMode)(GL_PROJECTION); + GLP(PushMatrix)(); + GLP(LoadIdentity)(); + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PushMatrix)(); + GLP(LoadIdentity)(); + + bool has_color = _vertex_data->has_column(InternalName::get_color()); + + // First, get all of the points in eye space. + const LMatrix4f &modelview = _transform->get_mat(); + qpGeomVertexReader vertex(_vertex_data, InternalName::get_vertex()); + qpGeomVertexReader color(_vertex_data, InternalName::get_color()); + qpGeomVertexReader rotate(_vertex_data, InternalName::get_rotate()); + qpGeomVertexReader scale_x(_vertex_data, InternalName::get_scale_x()); + qpGeomVertexReader scale_y(_vertex_data, InternalName::get_scale_y()); + + int num_sprites = primitive->get_num_vertices(); + SpriteData *sprites = (SpriteData *)alloca(num_sprites * sizeof(SpriteData)); + SpriteData **sprite_pointers = (SpriteData **)alloca(num_sprites * sizeof(SpriteData *)); + + SpriteData *sd = sprites; + SpriteData *sd_end = sprites + num_sprites; + SpriteData **sdp = sprite_pointers; + SpriteData **sdp_end = sprite_pointers + num_sprites; + + for (int i = 0; i < num_sprites; ++i) { + int vi = primitive->get_vertex(i); + + nassertv(sd < sd_end && sdp < sdp_end); + if (has_color) { + color.set_vertex(vi); + sd->_color = color.get_data4f(); + } + if (has_rotate) { + rotate.set_vertex(vi); + sd->_rotate = rotate.get_data1f(); + } + if (has_scale_x) { + scale_x.set_vertex(vi); + sd->_scale_x = scale_x.get_data1f(); + } else { + sd->_scale_x = 1.0f; + } + if (has_scale_y) { + scale_y.set_vertex(vi); + sd->_scale_y = scale_y.get_data1f(); + } else { + sd->_scale_y = 1.0f; + } + + // The point in eye-space coordinates. + vertex.set_vertex(vi); + sd->_eye = modelview.xform_point(vertex.get_data3f()); + (*sdp) = sd; + ++sd; + ++sdp; + } + + // Now sort the sprites in order from back-to-front so they will + // render properly with transparency, at least with each other. + ::sort(sprite_pointers, sprite_pointers + num_sprites, + IndirectLess()); + + // Point radius, converted from pixels into camera space. + float rx = _gl_point_size / _viewport_width; + float ry = _gl_point_size / _viewport_height; + + // Go through the sprites, now in sorted order, and render a quad + // for each one. + GLP(Begin)(GL_QUADS); + for (sdp = sprite_pointers; sdp < sdp_end; ++sdp) { + sd = (*sdp); + if (has_color) { + GLP(Color4fv)(sd->_color.get_data()); + } + // The point in eye-space coordinates. + const LPoint3f &eye = sd->_eye; + + // The point in camera-space coordinates. + LPoint4f p4 = LPoint4f(eye[0], eye[1], eye[2], 1.0f) * _projection_mat; + LPoint3f c(p4[0] / p4[3], p4[1] / p4[3], p4[2] / p4[3]); + + // Define the first two corners based on the scales in X and Y. + LPoint2f c0(sd->_scale_x, sd->_scale_y); + LPoint2f c1(-sd->_scale_x, sd->_scale_y); + + if (has_rotate) { + // If we have a rotate factor, apply it to those two corners. + LMatrix3f mat = LMatrix3f::rotate_mat(sd->_rotate); + c0 = c0 * mat; + c1 = c1 * mat; + } + + // Now scale the corners to compensate for the aspect ratio of + // the viewport (as well as applying the current + // RenderModeAttrib's thickness, i.e. point size). + c0.set(c0[0] * rx, c0[1] * ry); + c1.set(c1[0] * rx, c1[1] * ry); + + if (_point_perspective) { + // If _point_perspective is in effect, we should divide the + // radius by the distance from the camera plane (which is + // -eye[2]), to emulate the glPointParameters() behavior. + float scale = (-1.0f / eye[2]); + c0 *= scale; + c1 *= scale; + } + + GLP(TexCoord2f)(1.0f, 0.0f); + GLP(Vertex3f)(c[0] + c0[0], c[1] + c0[1], c[2]); + GLP(TexCoord2f)(0.0f, 0.0f); + GLP(Vertex3f)(c[0] + c1[0], c[1] + c1[1], c[2]); + GLP(TexCoord2f)(0.0f, 1.0f); + GLP(Vertex3f)(c[0] - c0[0], c[1] - c0[1], c[2]); + GLP(TexCoord2f)(1.0f, 1.0f); + GLP(Vertex3f)(c[0] - c1[0], c[1] - c1[1], c[2]); + } + GLP(End)(); + + GLP(MatrixMode)(GL_PROJECTION); + GLP(PopMatrix)(); + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PopMatrix)(); + + } else { + // In this case, the sprites are simple squares, so we can take + // advantage of the point_sprite extension to draw them quickly. + _vertices_other_pcollector.add_level(primitive->get_num_vertices()); + const unsigned short *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); + } + report_my_gl_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::end_draw_primitives() // Access: Public, Virtual @@ -3421,6 +3625,8 @@ issue_material(const MaterialAttrib *attrib) { void CLP(GraphicsStateGuardian):: issue_render_mode(const RenderModeAttrib *attrib) { _render_mode = attrib->get_mode(); + _point_size = attrib->get_thickness(); + _point_perspective = attrib->get_perspective(); switch (_render_mode) { case RenderModeAttrib::M_unchanged: @@ -3442,10 +3648,10 @@ issue_render_mode(const RenderModeAttrib *attrib) { } // The thickness affects both the line width and the point size. - GLP(LineWidth)(attrib->get_thickness()); - GLP(PointSize)(attrib->get_thickness()); - + GLP(LineWidth)(_point_size); report_my_gl_errors(); + + do_point_size(); } //////////////////////////////////////////////////////////////////// @@ -6058,6 +6264,52 @@ do_issue_texture() { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::do_point_size +// Access: Protected +// Description: Internally sets the point size parameters after any +// of the properties have changed that might affect +// this. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +do_point_size() { + if (!_point_perspective) { + // Normal, constant-sized points. Here _point_size is a width in + // pixels. + GLP(PointSize)(_point_size); + _gl_point_size = _point_size; + static LVecBase3f constant(1.0f, 0.0f, 0.0f); + _glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, constant.get_data()); + + } else { + // Perspective-sized points. Here _point_size is a width in 3-d + // units. To arrange that, we need to figure out the appropriate + // scaling factor based on the current viewport and projection + // matrix. + LVector3f width(_point_size, 0.0f, 1.0f); + width = width * _projection_mat; + _gl_point_size = width[0] * _viewport_width; + + if (!_supports_point_parameters) { + // Actually, this OpenGL driver doesn't support the + // glPointParameter() extension. That means we can't get + // perspective correct points anyway. Maybe we should render + // them as sprites? As a stopgap, we'll just ask for 1-pixel + // points. + GLP(PointSize)(1.0f); + + } else { + // This driver does support the extension, so get the + // appropriate width. + GLP(PointSize)(width[0] * _viewport_width); + static LVecBase3f square(0.0f, 0.0f, 1.0f); + _glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, square.get_data()); + } + } + + report_my_gl_errors(); +} + #ifndef NDEBUG //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::build_phony_mipmaps diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 462db6859d..a446e2d987 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -51,6 +51,7 @@ class Light; // system GL version matches or exceeds the GL version in which these // functions are defined, and the system gl.h sometimes doesn't // declare these typedefs. +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); @@ -100,6 +101,7 @@ public: virtual void draw_tristrips(const qpGeomTristrips *primitive); virtual void draw_lines(const qpGeomLines *primitive); virtual void draw_points(const qpGeomPoints *primitive); + virtual void draw_sprites(const qpGeomSprites *primitive); virtual void end_draw_primitives(); INLINE bool draw_display_list(GeomContext *gc); @@ -263,6 +265,7 @@ protected: void do_auto_rescale_normal(); void do_issue_texture(); + void do_point_size(); #ifndef NDEBUG void build_phony_mipmaps(Texture *tex); @@ -302,9 +305,9 @@ protected: int _max_lights; int _max_clip_planes; - LMatrix4f _current_projection_mat; - int _projection_mat_stack_count; - + LMatrix4f _projection_mat; + int _viewport_width; + int _viewport_height; CPT(TextureAttrib) _current_texture; CPT(TexMatrixAttrib) _current_tex_mat; bool _needs_tex_mat; @@ -313,6 +316,9 @@ protected: bool _tex_gen_modifies_mat; bool _auto_antialias_mode; RenderModeAttrib::Mode _render_mode; + float _point_size; + float _gl_point_size; + bool _point_perspective; bool _transform_stale; bool _vertex_blending_enabled; @@ -335,6 +341,11 @@ protected: pset _extensions; public: + bool _supports_point_parameters; + PFNGLPOINTPARAMETERFVPROC _glPointParameterfv; + + bool _supports_point_sprite; + bool _supports_vertex_blend; PFNGLWEIGHTPOINTERARBPROC _glWeightPointerARB; PFNGLVERTEXBLENDARBPROC _glVertexBlendARB; @@ -381,6 +392,17 @@ public: typedef pvector DeletedDisplayLists; DeletedDisplayLists _deleted_display_lists; + // This class is used internally by draw_sprites(). + class SpriteData { + public: + INLINE bool operator < (const SpriteData &other) const; + Vertexf _eye; + Colorf _color; + float _rotate; + float _scale_x; + float _scale_y; + }; + public: static GraphicsStateGuardian * make_GlGraphicsStateGuardian(const FactoryParams ¶ms); diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index be2de40009..ec5ee65757 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -27,6 +27,7 @@ qpgeomLines.h \ qpgeomLinestrips.h \ qpgeomPoints.h \ + qpgeomSprites.h \ qpgeomUsageHint.h \ qpgeomVertexArrayData.h qpgeomVertexArrayData.I \ qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \ @@ -79,6 +80,7 @@ qpgeomLines.cxx \ qpgeomLinestrips.cxx \ qpgeomPoints.cxx \ + qpgeomSprites.cxx \ qpgeomVertexArrayData.cxx \ qpgeomVertexArrayFormat.cxx \ qpgeomCacheEntry.cxx \ @@ -128,6 +130,7 @@ qpgeomLines.h \ qpgeomLinestrips.h \ qpgeomPoints.h \ + qpgeomSprites.h \ qpgeomUsageHint.h \ qpgeomVertexArrayData.h qpgeomVertexArrayData.I \ qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \ diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index ddc7cf58be..6fc0913e0b 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -31,6 +31,7 @@ #include "qpgeomLines.h" #include "qpgeomLinestrips.h" #include "qpgeomPoints.h" +#include "qpgeomSprites.h" #include "qpgeomVertexArrayData.h" #include "qpgeomVertexArrayFormat.h" #include "qpgeomVertexData.h" @@ -256,6 +257,7 @@ ConfigureFn(config_gobj) { qpGeomLines::init_type(); qpGeomLinestrips::init_type(); qpGeomPoints::init_type(); + qpGeomSprites::init_type(); qpGeomVertexArrayData::init_type(); qpGeomVertexArrayFormat::init_type(); qpGeomVertexData::init_type(); @@ -300,6 +302,7 @@ ConfigureFn(config_gobj) { qpGeomLines::register_with_read_factory(); qpGeomLinestrips::register_with_read_factory(); qpGeomPoints::register_with_read_factory(); + qpGeomSprites::register_with_read_factory(); qpGeomVertexArrayData::register_with_read_factory(); qpGeomVertexArrayFormat::register_with_read_factory(); qpGeomVertexData::register_with_read_factory(); diff --git a/panda/src/gobj/gobj_composite1.cxx b/panda/src/gobj/gobj_composite1.cxx index b0324116f2..587aedef44 100644 --- a/panda/src/gobj/gobj_composite1.cxx +++ b/panda/src/gobj/gobj_composite1.cxx @@ -20,6 +20,7 @@ #include "qpgeomLines.cxx" #include "qpgeomLinestrips.cxx" #include "qpgeomPoints.cxx" +#include "qpgeomSprites.cxx" #include "qpgeomVertexArrayData.cxx" #include "qpgeomVertexArrayFormat.cxx" #include "qpgeomCacheEntry.cxx" diff --git a/panda/src/gobj/internalName.I b/panda/src/gobj/internalName.I index 0c1d0c885c..490ec2098d 100644 --- a/panda/src/gobj/internalName.I +++ b/panda/src/gobj/internalName.I @@ -178,6 +178,45 @@ get_color() { return _color; } +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_rotate +// Access: Published, Static +// Description: Returns the standard InternalName "rotate". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_rotate() { + if (_rotate == (InternalName *)NULL) { + _rotate = InternalName::make("rotate"); + } + return _rotate; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_scale_x +// Access: Published, Static +// Description: Returns the standard InternalName "scale_x". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_scale_x() { + if (_scale_x == (InternalName *)NULL) { + _scale_x = InternalName::make("scale_x"); + } + return _scale_x; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_scale_y +// Access: Published, Static +// Description: Returns the standard InternalName "scale_y". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_scale_y() { + if (_scale_y == (InternalName *)NULL) { + _scale_y = InternalName::make("scale_y"); + } + return _scale_y; +} + //////////////////////////////////////////////////////////////////// // Function: InternalName::get_transform_blend // Access: Published, Static diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx index 0a84853bdd..56f14c3c83 100644 --- a/panda/src/gobj/internalName.cxx +++ b/panda/src/gobj/internalName.cxx @@ -32,6 +32,9 @@ PT(InternalName) InternalName::_tangent; PT(InternalName) InternalName::_binormal; PT(InternalName) InternalName::_texcoord; PT(InternalName) InternalName::_color; +PT(InternalName) InternalName::_rotate; +PT(InternalName) InternalName::_scale_x; +PT(InternalName) InternalName::_scale_y; PT(InternalName) InternalName::_transform_blend; PT(InternalName) InternalName::_transform_weight; PT(InternalName) InternalName::_transform_index; diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h index 0fe4b73916..6b2424a32f 100644 --- a/panda/src/gobj/internalName.h +++ b/panda/src/gobj/internalName.h @@ -71,6 +71,9 @@ PUBLISHED: INLINE static PT(InternalName) get_texcoord(); INLINE static PT(InternalName) get_texcoord_name(const string &name); INLINE static PT(InternalName) get_color(); + INLINE static PT(InternalName) get_rotate(); + INLINE static PT(InternalName) get_scale_x(); + INLINE static PT(InternalName) get_scale_y(); INLINE static PT(InternalName) get_transform_blend(); INLINE static PT(InternalName) get_transform_weight(); INLINE static PT(InternalName) get_transform_index(); @@ -92,6 +95,9 @@ private: static PT(InternalName) _binormal; static PT(InternalName) _texcoord; static PT(InternalName) _color; + static PT(InternalName) _rotate; + static PT(InternalName) _scale_x; + static PT(InternalName) _scale_y; static PT(InternalName) _transform_blend; static PT(InternalName) _transform_weight; static PT(InternalName) _transform_index; diff --git a/panda/src/gobj/qpgeomPrimitive.cxx b/panda/src/gobj/qpgeomPrimitive.cxx index d77223727a..749f3a4adf 100644 --- a/panda/src/gobj/qpgeomPrimitive.cxx +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -138,6 +138,9 @@ add_vertex(int vertex) { //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: add_consecutive_vertices(int start, int num_vertices) { + if (num_vertices == 0) { + return; + } clear_cache(); int end = (start + num_vertices) - 1; unsigned short short_start = start; @@ -472,7 +475,8 @@ get_num_bytes() const { //////////////////////////////////////////////////////////////////// bool qpGeomPrimitive:: check_valid(const qpGeomVertexData *vertex_data) const { - return get_max_vertex() < vertex_data->get_num_vertices(); + return get_num_vertices() == 0 || + get_max_vertex() < vertex_data->get_num_vertices(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomSprites.cxx b/panda/src/gobj/qpgeomSprites.cxx new file mode 100644 index 0000000000..20d7dfaa78 --- /dev/null +++ b/panda/src/gobj/qpgeomSprites.cxx @@ -0,0 +1,148 @@ +// Filename: qpgeomSprites.cxx +// Created by: drose (05Apr05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "qpgeomSprites.h" +#include "pStatTimer.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle qpGeomSprites::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomSprites:: +qpGeomSprites(qpGeomUsageHint::UsageHint usage_hint) : + qpGeomPrimitive(usage_hint) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomSprites:: +qpGeomSprites(const qpGeomSprites ©) : + qpGeomPrimitive(copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomSprites:: +~qpGeomSprites() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +PT(qpGeomPrimitive) qpGeomSprites:: +make_copy() const { + return new qpGeomSprites(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::get_primitive_type +// Access: Public, Virtual +// Description: Returns the fundamental rendering type of this +// primitive: whether it is sprites, lines, or polygons. +// This is used primarily to set up the appropriate +// antialiasing settings when AntialiasAttrib::M_auto is +// in effect. +//////////////////////////////////////////////////////////////////// +qpGeomPrimitive::PrimitiveType qpGeomSprites:: +get_primitive_type() const { + return PT_polygons; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::get_num_vertices_per_primitive +// Access: Public, Virtual +// Description: If the primitive type is a simple type in which all +// primitives have the same number of vertices, like +// sprites, returns the number of vertices per +// primitive. If the primitive type is a more complex +// type in which different primitives might have +// different numbers of vertices, for instance a +// sprite strip, returns 0. +//////////////////////////////////////////////////////////////////// +int qpGeomSprites:: +get_num_vertices_per_primitive() const { + return 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::get_min_num_vertices_per_primitive +// Access: Public, Virtual +// Description: Returns the minimum number of vertices that must be +// added before close_primitive() may legally be called. +//////////////////////////////////////////////////////////////////// +int qpGeomSprites:: +get_min_num_vertices_per_primitive() const { + return 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::draw +// Access: Public, Virtual +// Description: Calls the appropriate method on the GSG to draw the +// primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomSprites:: +draw(GraphicsStateGuardianBase *gsg) const { + gsg->draw_sprites(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeomSprites:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomSprites::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeom is encountered +// in the Bam file. It should create the qpGeom +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomSprites:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomSprites *object = new qpGeomSprites(qpGeomUsageHint::UH_client); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} diff --git a/panda/src/gobj/qpgeomSprites.h b/panda/src/gobj/qpgeomSprites.h new file mode 100644 index 0000000000..d8bf34e656 --- /dev/null +++ b/panda/src/gobj/qpgeomSprites.h @@ -0,0 +1,90 @@ +// Filename: qpgeomSprites.h +// Created by: drose (05Apr05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef qpGEOMSPRITES_H +#define qpGEOMSPRITES_H + +#include "pandabase.h" +#include "qpgeomPrimitive.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomSprites +// Description : Defines a collection of rectangular polygons with the +// same texture applied to all of them. This is most +// useful for particle systems. +// +// Each sprite is defined by a single vertex, at the +// center of the polygon. Each polygon may optionally +// be rotated by a certain angle, and/or scaled in x and +// y; if needed, these parameters are specified +// per-vertex with the optional "rotate", "scale_x", and +// "scale_y" vertex data column names. +// +// The overall scale of the sprites is controlled by the +// current RenderModeAttrib::get_thickness() and +// get_perspective() parameters. If present, scale_x +// and scale_y apply an additional per-sprite scale. +// The UV range is always (0, 0) in the upper left +// corner to (1, 1) in the lower right; use a +// TexMatrixAttrib to adjust this. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomSprites : public qpGeomPrimitive { +PUBLISHED: + qpGeomSprites(qpGeomUsageHint::UsageHint usage_hint); + qpGeomSprites(const qpGeomSprites ©); + virtual ~qpGeomSprites(); + +public: + virtual PT(qpGeomPrimitive) make_copy() const; + virtual PrimitiveType get_primitive_type() const; + + virtual int get_num_vertices_per_primitive() const; + virtual int get_min_num_vertices_per_primitive() const; + +public: + virtual void draw(GraphicsStateGuardianBase *gsg) const; + +public: + static void register_with_read_factory(); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + qpGeomPrimitive::init_type(); + register_type(_type_handle, "qpGeomSprites", + qpGeomPrimitive::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class qpGeom; +}; + +#endif diff --git a/panda/src/gobj/qpgeomVertexWriter.I b/panda/src/gobj/qpgeomVertexWriter.I index 941c8d5d52..69798457e8 100644 --- a/panda/src/gobj/qpgeomVertexWriter.I +++ b/panda/src/gobj/qpgeomVertexWriter.I @@ -117,8 +117,11 @@ get_vertex_data() const { //////////////////////////////////////////////////////////////////// INLINE bool qpGeomVertexWriter:: set_column(int column) { + if (_vertex_data == (qpGeomVertexData *)NULL) { + return false; + } return set_column(_vertex_data->get_format()->get_array_with(column), - _vertex_data->get_format()->get_column(column)); + _vertex_data->get_format()->get_column(column)); } //////////////////////////////////////////////////////////////////// @@ -154,8 +157,11 @@ set_column(const string &name) { //////////////////////////////////////////////////////////////////// INLINE bool qpGeomVertexWriter:: set_column(const InternalName *name) { + if (_vertex_data == (qpGeomVertexData *)NULL) { + return false; + } return set_column(_vertex_data->get_format()->get_array_with(name), - _vertex_data->get_format()->get_column(name)); + _vertex_data->get_format()->get_column(name)); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomVertexWriter.cxx b/panda/src/gobj/qpgeomVertexWriter.cxx index abd057df54..8922126e6a 100644 --- a/panda/src/gobj/qpgeomVertexWriter.cxx +++ b/panda/src/gobj/qpgeomVertexWriter.cxx @@ -41,6 +41,10 @@ unsigned char qpGeomVertexWriter::empty_buffer[100] = { 0 }; //////////////////////////////////////////////////////////////////// bool qpGeomVertexWriter:: set_column(int array, const qpGeomVertexColumn *column) { + if (_vertex_data == (qpGeomVertexData *)NULL) { + return false; + } + // Delete the old writer, if we've got one. if (_writer != (Writer *)NULL) { delete _writer; @@ -55,9 +59,9 @@ set_column(int array, const qpGeomVertexColumn *column) { _stride = 0; _write_vertex = _start_vertex; _num_vertices = 0; - + return false; - + } else { _array = array; _column = column; diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index a24f4bb35c..b6e98c22c8 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -55,6 +55,7 @@ class qpGeomTrifans; class qpGeomLines; class qpGeomLinestrips; class qpGeomPoints; +class qpGeomSprites; class qpGeomMunger; class PreparedGraphicsObjects; @@ -196,6 +197,7 @@ public: virtual void draw_lines(const qpGeomLines *primitive)=0; virtual void draw_linestrips(const qpGeomLinestrips *primitive)=0; virtual void draw_points(const qpGeomPoints *primitive)=0; + virtual void draw_sprites(const qpGeomSprites *primitive)=0; virtual void end_draw_primitives()=0; virtual void framebuffer_copy_to_texture diff --git a/panda/src/particlesystem/baseParticleRenderer.h b/panda/src/particlesystem/baseParticleRenderer.h index a8b43a5da5..27298043c3 100644 --- a/panda/src/particlesystem/baseParticleRenderer.h +++ b/panda/src/particlesystem/baseParticleRenderer.h @@ -67,8 +67,6 @@ PUBLISHED: public: virtual BaseParticleRenderer *make_copy() = 0; - friend class ParticleSystem; - protected: ParticleRendererAlphaMode _alpha_mode; @@ -105,6 +103,8 @@ private: virtual void init_geoms() = 0; virtual void render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) = 0; + + friend class ParticleSystem; }; #include "baseParticleRenderer.I" diff --git a/panda/src/particlesystem/lineParticleRenderer.cxx b/panda/src/particlesystem/lineParticleRenderer.cxx index 520e498a93..58f27f7832 100644 --- a/panda/src/particlesystem/lineParticleRenderer.cxx +++ b/panda/src/particlesystem/lineParticleRenderer.cxx @@ -17,8 +17,11 @@ //////////////////////////////////////////////////////////////////// #include "lineParticleRenderer.h" - #include "boundingSphere.h" +#include "geomNode.h" +#include "qpgeom.h" +#include "qpgeomVertexWriter.h" +#include "geomLine.h" //////////////////////////////////////////////////////////////////// // Function : LineParticleRenderer @@ -30,8 +33,8 @@ LineParticleRenderer:: LineParticleRenderer() : _head_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)), _tail_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)) { - _line_primitive = new GeomLine; - init_geoms(); + + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -47,8 +50,7 @@ LineParticleRenderer(const Colorf& head, BaseParticleRenderer(alpha_mode), _head_color(head), _tail_color(tail) { - _line_primitive = new GeomLine; - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -63,8 +65,7 @@ LineParticleRenderer(const LineParticleRenderer& copy) : _head_color = copy._head_color; _tail_color = copy._tail_color; - _line_primitive = new GeomLine; - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -117,11 +118,10 @@ kill_particle(int) { void LineParticleRenderer:: resize_pool(int new_size) { - _vertex_array = PTA_Vertexf::empty_array(new_size * 2); - _color_array = PTA_Colorf::empty_array(new_size * 2); - - _line_primitive->set_coords(_vertex_array); - _line_primitive->set_colors(_color_array, G_PER_VERTEX); + if (!use_qpgeom) { + _vertex_array = PTA_Vertexf::empty_array(new_size * 2); + _color_array = PTA_Colorf::empty_array(new_size * 2); + } _max_pool_size = new_size; @@ -136,7 +136,21 @@ resize_pool(int new_size) { void LineParticleRenderer:: init_geoms() { - _line_primitive->set_num_prims(0); + if (use_qpgeom) { + PT(qpGeom) qpgeom = new qpGeom; + _line_primitive = qpgeom; + _vdata = new qpGeomVertexData + ("particles", qpGeomVertexFormat::get_v3cp(), + qpGeomUsageHint::UH_dynamic); + qpgeom->set_vertex_data(_vdata); + _lines = new qpGeomLines(qpGeomUsageHint::UH_dynamic); + qpgeom->add_primitive(_lines); + + } else { + _line_primitive = new GeomLine; + _line_primitive->set_coords(_vertex_array); + _line_primitive->set_colors(_color_array, G_PER_VERTEX); + } GeomNode *render_node = get_render_node(); render_node->remove_all_geoms(); @@ -162,6 +176,11 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { Vertexf *cur_vert = &_vertex_array[0]; Colorf *cur_color = &_color_array[0]; + qpGeomVertexWriter vertex(_vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(_vdata, InternalName::get_color()); + if (use_qpgeom) { + _lines->clear_vertices(); + } // init the aabb @@ -176,24 +195,24 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { if (cur_particle->get_alive() == false) continue; - LPoint3f pos = cur_particle->get_position(); + LPoint3f position = cur_particle->get_position(); // adjust the aabb - if (pos.get_x() > _aabb_max.get_x()) - _aabb_max[0] = pos.get_x(); - if (pos.get_x() < _aabb_min.get_x()) - _aabb_min[0] = pos.get_x(); + if (position[0] > _aabb_max[0]) + _aabb_max[0] = position[0]; + if (position[0] < _aabb_min[0]) + _aabb_min[0] = position[0]; - if (pos.get_y() > _aabb_max.get_y()) - _aabb_max[1] = pos.get_y(); - if (pos.get_y() < _aabb_min.get_y()) - _aabb_min[1] = pos.get_y(); + if (position[1] > _aabb_max[1]) + _aabb_max[1] = position[1]; + if (position[1] < _aabb_min[1]) + _aabb_min[1] = position[1]; - if (pos.get_z() > _aabb_max.get_z()) - _aabb_max[2] = pos.get_z(); - if (pos.get_z() < _aabb_min.get_z()) - _aabb_min[2] = pos.get_z(); + if (position[2] > _aabb_max[2]) + _aabb_max[2] = position[2]; + if (position[2] < _aabb_min[2]) + _aabb_min[2] = position[2]; // draw the particle. @@ -222,18 +241,29 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { // one line from current position to last position - *cur_vert++ = pos; - *cur_vert++ = cur_particle->get_last_position(); + if (use_qpgeom) { + vertex.add_data3f(position); + vertex.add_data3f(cur_particle->get_last_position()); + color.add_data4f(head_color); + color.add_data4f(tail_color); + _lines->add_next_vertices(2); + _lines->close_primitive(); + } else { + *cur_vert++ = position; + *cur_vert++ = cur_particle->get_last_position(); - *cur_color++ = head_color; - *cur_color++ = tail_color; + *cur_color++ = head_color; + *cur_color++ = tail_color; + } remaining_particles--; if (remaining_particles == 0) break; } - _line_primitive->set_num_prims(ttl_particles); + if (!use_qpgeom) { + _line_primitive->set_num_prims(ttl_particles); + } // done filling geomline node, now do the bb stuff diff --git a/panda/src/particlesystem/lineParticleRenderer.h b/panda/src/particlesystem/lineParticleRenderer.h index c2a3ad28dd..3bdb093b13 100644 --- a/panda/src/particlesystem/lineParticleRenderer.h +++ b/panda/src/particlesystem/lineParticleRenderer.h @@ -25,7 +25,8 @@ #include "pointerTo.h" #include "pointerToArray.h" #include "geom.h" -#include "geomLine.h" +#include "qpgeomVertexData.h" +#include "qpgeomLines.h" //////////////////////////////////////////////////////////////////// // Class : LineParticleRenderer @@ -58,10 +59,12 @@ private: Colorf _head_color; Colorf _tail_color; - PT(GeomLine) _line_primitive; + PT(Geom) _line_primitive; + PT(qpGeomLines) _lines; PTA_Vertexf _vertex_array; PTA_Colorf _color_array; + PT(qpGeomVertexData) _vdata; int _max_pool_size; diff --git a/panda/src/particlesystem/pointParticleRenderer.cxx b/panda/src/particlesystem/pointParticleRenderer.cxx index d65e97c344..b69d8151e3 100644 --- a/panda/src/particlesystem/pointParticleRenderer.cxx +++ b/panda/src/particlesystem/pointParticleRenderer.cxx @@ -19,6 +19,9 @@ #include "pointParticleRenderer.h" #include "boundingSphere.h" #include "geomNode.h" +#include "geomPoint.h" +#include "qpgeom.h" +#include "qpgeomVertexWriter.h" //////////////////////////////////////////////////////////////////// // Function : PointParticleRenderer @@ -36,9 +39,8 @@ PointParticleRenderer(ParticleRendererAlphaMode am, _start_color(sc), _end_color(ec), _blend_type(bt), _blend_method(bm) { - _point_primitive = new GeomPoint; set_point_size(point_size); - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -49,8 +51,7 @@ PointParticleRenderer(ParticleRendererAlphaMode am, PointParticleRenderer:: PointParticleRenderer(const PointParticleRenderer& copy) : - BaseParticleRenderer(copy), - _max_pool_size(0) + BaseParticleRenderer(copy) { _blend_type = copy._blend_type; _blend_method = copy._blend_method; @@ -58,8 +59,7 @@ PointParticleRenderer(const PointParticleRenderer& copy) : _end_color = copy._end_color; _point_size = copy._point_size; _thick = copy._thick; - _point_primitive = new GeomPoint; - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -69,7 +69,7 @@ PointParticleRenderer(const PointParticleRenderer& copy) : //////////////////////////////////////////////////////////////////// PointParticleRenderer:: -~PointParticleRenderer(void) { +~PointParticleRenderer() { } //////////////////////////////////////////////////////////////////// @@ -79,7 +79,7 @@ PointParticleRenderer:: //////////////////////////////////////////////////////////////////// BaseParticleRenderer *PointParticleRenderer:: -make_copy(void) { +make_copy() { return new PointParticleRenderer(*this); } @@ -97,11 +97,10 @@ resize_pool(int new_size) { _max_pool_size = new_size; - _vertex_array = PTA_Vertexf::empty_array(new_size); - _color_array = PTA_Colorf::empty_array(new_size); - - _point_primitive->set_coords(_vertex_array); - _point_primitive->set_colors(_color_array, G_PER_VERTEX); + if (!use_qpgeom) { + _vertex_array = PTA_Vertexf::empty_array(new_size); + _color_array = PTA_Colorf::empty_array(new_size); + } init_geoms(); } @@ -113,9 +112,22 @@ resize_pool(int new_size) { //////////////////////////////////////////////////////////////////// void PointParticleRenderer:: -init_geoms(void) { +init_geoms() { + if (use_qpgeom) { + PT(qpGeom) qpgeom = new qpGeom; + _point_primitive = qpgeom; + _vdata = new qpGeomVertexData + ("particles", qpGeomVertexFormat::get_v3cp(), + qpGeomUsageHint::UH_dynamic); + qpgeom->set_vertex_data(_vdata); + _points = new qpGeomPoints(qpGeomUsageHint::UH_dynamic); + qpgeom->add_primitive(_points); - _point_primitive->set_num_prims(0); + } else { + _point_primitive = new GeomPoint; + _point_primitive->set_coords(_vertex_array); + _point_primitive->set_colors(_color_array, G_PER_VERTEX); + } GeomNode *render_node = get_render_node(); render_node->remove_all_geoms(); @@ -228,6 +240,8 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { Vertexf *cur_vert = &_vertex_array[0]; Colorf *cur_color = &_color_array[0]; + qpGeomVertexWriter vertex(_vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(_vdata, InternalName::get_color()); // init the aabb @@ -239,34 +253,41 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { for (i = 0; i < (int)po_vector.size(); i++) { cur_particle = (BaseParticle *) po_vector[i].p(); - if (cur_particle->get_alive() == false) + if (!cur_particle->get_alive()) continue; + LPoint3f position = cur_particle->get_position(); + // x aabb adjust - if (cur_particle->get_position().get_x() > _aabb_max.get_x()) - _aabb_max[0] = cur_particle->get_position().get_x(); - else if (cur_particle->get_position().get_x() < _aabb_min.get_x()) - _aabb_min[0] = cur_particle->get_position().get_x(); + if (position[0] > _aabb_max[0]) + _aabb_max[0] = position[0]; + else if (position[0] < _aabb_min[0]) + _aabb_min[0] = position[0]; // y aabb adjust - if (cur_particle->get_position().get_y() > _aabb_max.get_y()) - _aabb_max[1] = cur_particle->get_position().get_y(); - else if (cur_particle->get_position().get_y() < _aabb_min.get_y()) - _aabb_min[1] = cur_particle->get_position().get_y(); + if (position[1] > _aabb_max[1]) + _aabb_max[1] = position[1]; + else if (position[1] < _aabb_min[1]) + _aabb_min[1] = position[1]; // z aabb adjust - if (cur_particle->get_position().get_z() > _aabb_max.get_z()) - _aabb_max[2] = cur_particle->get_position().get_z(); - else if (cur_particle->get_position().get_z() < _aabb_min.get_z()) - _aabb_min[2] = cur_particle->get_position().get_z(); + if (position[2] > _aabb_max[2]) + _aabb_max[2] = position[2]; + else if (position[2] < _aabb_min[2]) + _aabb_min[2] = position[2]; // stuff it into the arrays - *cur_vert++ = cur_particle->get_position(); - *cur_color++ = create_color(cur_particle); + if (use_qpgeom) { + vertex.add_data3f(position); + color.add_data4f(create_color(cur_particle)); + } else { + *cur_vert++ = position; + *cur_color++ = create_color(cur_particle); + } // maybe jump out early? @@ -275,7 +296,12 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { break; } - _point_primitive->set_num_prims(ttl_particles); + if (use_qpgeom) { + _points->clear_vertices(); + _points->add_next_vertices(ttl_particles); + } else { + _point_primitive->set_num_prims(ttl_particles); + } // done filling geompoint node, now do the bb stuff diff --git a/panda/src/particlesystem/pointParticleRenderer.h b/panda/src/particlesystem/pointParticleRenderer.h index 844bce3f99..ef3c4811c8 100644 --- a/panda/src/particlesystem/pointParticleRenderer.h +++ b/panda/src/particlesystem/pointParticleRenderer.h @@ -26,7 +26,8 @@ #include "pointerToArray.h" #include "luse.h" #include "geom.h" -#include "geomPoint.h" +#include "qpgeomVertexData.h" +#include "qpgeomPoints.h" //////////////////////////////////////////////////////////////////// // Class : PointParticleRenderer @@ -76,10 +77,12 @@ private: float _point_size; CPT(RenderAttrib) _thick; - PT(GeomPoint) _point_primitive; + PT(Geom) _point_primitive; + PT(qpGeomPoints) _points; PTA_Vertexf _vertex_array; PTA_Colorf _color_array; + PT(qpGeomVertexData) _vdata; int _max_pool_size; diff --git a/panda/src/particlesystem/sparkleParticleRenderer.cxx b/panda/src/particlesystem/sparkleParticleRenderer.cxx index 3795edf5d3..486f5d7b7e 100644 --- a/panda/src/particlesystem/sparkleParticleRenderer.cxx +++ b/panda/src/particlesystem/sparkleParticleRenderer.cxx @@ -17,9 +17,11 @@ //////////////////////////////////////////////////////////////////// #include "sparkleParticleRenderer.h" - #include "boundingSphere.h" #include "geomNode.h" +#include "qpgeom.h" +#include "qpgeomVertexWriter.h" +#include "geomLine.h" //////////////////////////////////////////////////////////////////// // Function : SparkleParticleRenderer @@ -33,8 +35,7 @@ SparkleParticleRenderer() : _edge_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)), _birth_radius(0.1f), _death_radius(0.1f) { - _line_primitive = new GeomLine; - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -51,8 +52,7 @@ SparkleParticleRenderer(const Colorf& center, const Colorf& edge, _center_color(center), _edge_color(edge), _birth_radius(birth_radius), _death_radius(death_radius), _life_scale(life_scale) { - _line_primitive = new GeomLine; - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -69,8 +69,7 @@ SparkleParticleRenderer(const SparkleParticleRenderer& copy) : _death_radius = copy._death_radius; _life_scale = copy._life_scale; - _line_primitive = new GeomLine; - init_geoms(); + resize_pool(0); } //////////////////////////////////////////////////////////////////// @@ -118,11 +117,10 @@ kill_particle(int) { //////////////////////////////////////////////////////////////////// void SparkleParticleRenderer:: resize_pool(int new_size) { - _vertex_array = PTA_Vertexf::empty_array(new_size * 12); - _color_array = PTA_Colorf::empty_array(new_size * 12); - - _line_primitive->set_coords(_vertex_array); - _line_primitive->set_colors(_color_array, G_PER_VERTEX); + if (!use_qpgeom) { + _vertex_array = PTA_Vertexf::empty_array(new_size * 12); + _color_array = PTA_Colorf::empty_array(new_size * 12); + } _max_pool_size = new_size; @@ -136,7 +134,21 @@ resize_pool(int new_size) { //////////////////////////////////////////////////////////////////// void SparkleParticleRenderer:: init_geoms() { - _line_primitive->set_num_prims(0); + if (use_qpgeom) { + PT(qpGeom) qpgeom = new qpGeom; + _line_primitive = qpgeom; + _vdata = new qpGeomVertexData + ("particles", qpGeomVertexFormat::get_v3cp(), + qpGeomUsageHint::UH_dynamic); + qpgeom->set_vertex_data(_vdata); + _lines = new qpGeomLines(qpGeomUsageHint::UH_dynamic); + qpgeom->add_primitive(_lines); + + } else { + _line_primitive = new GeomLine; + _line_primitive->set_coords(_vertex_array); + _line_primitive->set_colors(_color_array, G_PER_VERTEX); + } GeomNode *render_node = get_render_node(); render_node->remove_all_geoms(); @@ -161,6 +173,11 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { Vertexf *cur_vert = &_vertex_array[0]; Colorf *cur_color = &_color_array[0]; + qpGeomVertexWriter vertex(_vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(_vdata, InternalName::get_color()); + if (use_qpgeom) { + _lines->clear_vertices(); + } // init the aabb @@ -175,22 +192,24 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { if (cur_particle->get_alive() == false) continue; + LPoint3f position = cur_particle->get_position(); + // adjust the aabb - if (cur_particle->get_position().get_x() > _aabb_max.get_x()) - _aabb_max[0] = cur_particle->get_position().get_x(); - else if (cur_particle->get_position().get_x() < _aabb_min.get_x()) - _aabb_min[0] = cur_particle->get_position().get_x(); + if (position[0] > _aabb_max[0]) + _aabb_max[0] = position[0]; + else if (position[0] < _aabb_min[0]) + _aabb_min[0] = position[0]; - if (cur_particle->get_position().get_y() > _aabb_max.get_y()) - _aabb_max[1] = cur_particle->get_position().get_y(); - else if (cur_particle->get_position().get_y() < _aabb_min.get_y()) - _aabb_min[1] = cur_particle->get_position().get_y(); + if (position[1] > _aabb_max[1]) + _aabb_max[1] = position[1]; + else if (position[1] < _aabb_min[1]) + _aabb_min[1] = position[1]; - if (cur_particle->get_position().get_z() > _aabb_max.get_z()) - _aabb_max[2] = cur_particle->get_position().get_z(); - else if (cur_particle->get_position().get_z() < _aabb_min.get_z()) - _aabb_min[2] = cur_particle->get_position().get_z(); + if (position[2] > _aabb_max[2]) + _aabb_max[2] = position[2]; + else if (position[2] < _aabb_min[2]) + _aabb_min[2] = position[2]; // draw the particle. @@ -198,7 +217,6 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { float neg_radius = -radius; float alpha; - LPoint3f pos = cur_particle->get_position(); Colorf center_color = _center_color; Colorf edge_color = _edge_color; @@ -223,38 +241,81 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { // 6 lines coming from the center point. - *cur_vert++ = pos; - *cur_vert++ = pos + Vertexf(radius, 0.0f, 0.0f); - *cur_vert++ = pos; - *cur_vert++ = pos + Vertexf(neg_radius, 0.0f, 0.0f); - *cur_vert++ = pos; - *cur_vert++ = pos + Vertexf(0.0f, radius, 0.0f); - *cur_vert++ = pos; - *cur_vert++ = pos + Vertexf(0.0f, neg_radius, 0.0f); - *cur_vert++ = pos; - *cur_vert++ = pos + Vertexf(0.0f, 0.0f, radius); - *cur_vert++ = pos; - *cur_vert++ = pos + Vertexf(0.0f, 0.0f, neg_radius); + if (use_qpgeom) { + vertex.add_data3f(position); + vertex.add_data3f(position + Vertexf(radius, 0.0f, 0.0f)); + vertex.add_data3f(position); + vertex.add_data3f(position + Vertexf(neg_radius, 0.0f, 0.0f)); + vertex.add_data3f(position); + vertex.add_data3f(position + Vertexf(0.0f, radius, 0.0f)); + vertex.add_data3f(position); + vertex.add_data3f(position + Vertexf(0.0f, neg_radius, 0.0f)); + vertex.add_data3f(position); + vertex.add_data3f(position + Vertexf(0.0f, 0.0f, radius)); + vertex.add_data3f(position); + vertex.add_data3f(position + Vertexf(0.0f, 0.0f, neg_radius)); - *cur_color++ = center_color; - *cur_color++ = edge_color; - *cur_color++ = center_color; - *cur_color++ = edge_color; - *cur_color++ = center_color; - *cur_color++ = edge_color; - *cur_color++ = center_color; - *cur_color++ = edge_color; - *cur_color++ = center_color; - *cur_color++ = edge_color; - *cur_color++ = center_color; - *cur_color++ = edge_color; + color.add_data4f(center_color); + color.add_data4f(edge_color); + color.add_data4f(center_color); + color.add_data4f(edge_color); + color.add_data4f(center_color); + color.add_data4f(edge_color); + color.add_data4f(center_color); + color.add_data4f(edge_color); + color.add_data4f(center_color); + color.add_data4f(edge_color); + color.add_data4f(center_color); + color.add_data4f(edge_color); + + _lines->add_next_vertices(2); + _lines->close_primitive(); + _lines->add_next_vertices(2); + _lines->close_primitive(); + _lines->add_next_vertices(2); + _lines->close_primitive(); + _lines->add_next_vertices(2); + _lines->close_primitive(); + _lines->add_next_vertices(2); + _lines->close_primitive(); + _lines->add_next_vertices(2); + _lines->close_primitive(); + } else { + *cur_vert++ = position; + *cur_vert++ = position + Vertexf(radius, 0.0f, 0.0f); + *cur_vert++ = position; + *cur_vert++ = position + Vertexf(neg_radius, 0.0f, 0.0f); + *cur_vert++ = position; + *cur_vert++ = position + Vertexf(0.0f, radius, 0.0f); + *cur_vert++ = position; + *cur_vert++ = position + Vertexf(0.0f, neg_radius, 0.0f); + *cur_vert++ = position; + *cur_vert++ = position + Vertexf(0.0f, 0.0f, radius); + *cur_vert++ = position; + *cur_vert++ = position + Vertexf(0.0f, 0.0f, neg_radius); + + *cur_color++ = center_color; + *cur_color++ = edge_color; + *cur_color++ = center_color; + *cur_color++ = edge_color; + *cur_color++ = center_color; + *cur_color++ = edge_color; + *cur_color++ = center_color; + *cur_color++ = edge_color; + *cur_color++ = center_color; + *cur_color++ = edge_color; + *cur_color++ = center_color; + *cur_color++ = edge_color; + } remaining_particles--; if (remaining_particles == 0) break; } - _line_primitive->set_num_prims(6 * ttl_particles); + if (!use_qpgeom) { + _line_primitive->set_num_prims(6 * ttl_particles); + } // done filling geomline node, now do the bb stuff diff --git a/panda/src/particlesystem/sparkleParticleRenderer.h b/panda/src/particlesystem/sparkleParticleRenderer.h index e07eb3c2ed..a9f83db0e5 100644 --- a/panda/src/particlesystem/sparkleParticleRenderer.h +++ b/panda/src/particlesystem/sparkleParticleRenderer.h @@ -25,7 +25,8 @@ #include "pointerTo.h" #include "pointerToArray.h" #include "geom.h" -#include "geomLine.h" +#include "qpgeomVertexData.h" +#include "qpgeomLines.h" enum SparkleParticleLifeScale { SP_NO_SCALE, @@ -78,10 +79,12 @@ private: float _birth_radius; float _death_radius; - PT(GeomLine) _line_primitive; + PT(Geom) _line_primitive; + PT(qpGeomLines) _lines; PTA_Vertexf _vertex_array; PTA_Colorf _color_array; + PT(qpGeomVertexData) _vdata; int _max_pool_size; diff --git a/panda/src/particlesystem/spriteParticleRenderer.I b/panda/src/particlesystem/spriteParticleRenderer.I index b6f016dc47..865c888031 100644 --- a/panda/src/particlesystem/spriteParticleRenderer.I +++ b/panda/src/particlesystem/spriteParticleRenderer.I @@ -34,10 +34,12 @@ get_source_type() const { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_texture(Texture *tex) { - _sprite_primitive->set_texture(tex); - _sprite_primitive->set_ll_uv(TexCoordf(0.0f, 0.0f)); - _sprite_primitive->set_ur_uv(TexCoordf(1.0f, 1.0f)); + _texture = tex; + set_ll_uv(TexCoordf(0.0f, 0.0f)); + set_ur_uv(TexCoordf(1.0f, 1.0f)); _source_type = ST_texture; + + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -50,7 +52,7 @@ set_texture(Texture *tex) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_ll_uv(const TexCoordf &ll_uv) { - _sprite_primitive->set_ll_uv(ll_uv); + _ll_uv = ll_uv; } //////////////////////////////////////////////////////////////////// @@ -63,7 +65,7 @@ set_ll_uv(const TexCoordf &ll_uv) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_ur_uv(const TexCoordf &ur_uv) { - _sprite_primitive->set_ur_uv(ur_uv); + _ur_uv = ur_uv; } //////////////////////////////////////////////////////////////////// @@ -81,16 +83,14 @@ set_color(const Colorf &color) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_x_scale_flag(bool animate_x_ratio) { - if (animate_x_ratio == true && _animate_x_ratio == false) { + if (animate_x_ratio && !_animate_x_ratio) { _x_texel_array = PTA_float::empty_array(_pool_size); - _sprite_primitive->set_x_texel_ratio(_x_texel_array, G_PER_PRIM); - } - else if (animate_x_ratio == false && _animate_x_ratio == true) { + } else if (!animate_x_ratio && _animate_x_ratio) { _x_texel_array = PTA_float::empty_array(1); - _sprite_primitive->set_x_texel_ratio(_x_texel_array, G_OVERALL); } _animate_x_ratio = animate_x_ratio; + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -99,16 +99,14 @@ set_x_scale_flag(bool animate_x_ratio) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_y_scale_flag(bool animate_y_ratio) { - if (animate_y_ratio == true && _animate_y_ratio == false) { + if (animate_y_ratio && !_animate_y_ratio) { _y_texel_array = PTA_float::empty_array(_pool_size); - _sprite_primitive->set_y_texel_ratio(_y_texel_array, G_PER_PRIM); - } - else if (animate_y_ratio == false && _animate_y_ratio == true) { + } else if (!animate_y_ratio && _animate_y_ratio) { _y_texel_array = PTA_float::empty_array(1); - _sprite_primitive->set_y_texel_ratio(_y_texel_array, G_OVERALL); } _animate_y_ratio = animate_y_ratio; + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -117,16 +115,14 @@ set_y_scale_flag(bool animate_y_ratio) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_anim_angle_flag(bool animate_theta) { - if (animate_theta == true && _animate_theta == false) { + if (animate_theta && !_animate_theta) { _theta_array = PTA_float::empty_array(_pool_size); - _sprite_primitive->set_thetas(_theta_array, G_PER_PRIM); - } - else if (animate_theta == false && _animate_theta == true) { + } else if (!animate_theta && _animate_theta) { _theta_array = PTA_float::empty_array(_pool_size); - _sprite_primitive->set_thetas(_theta_array, G_OVERALL); } _animate_theta = animate_theta; + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -135,7 +131,8 @@ set_anim_angle_flag(bool animate_theta) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_initial_x_scale(float initial_x_scale) { - _initial_x_texel_ratio = initial_x_scale; + _initial_x_scale = initial_x_scale; + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -144,7 +141,7 @@ set_initial_x_scale(float initial_x_scale) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_final_x_scale(float final_x_scale) { - _final_x_texel_ratio = final_x_scale; + _final_x_scale = final_x_scale; } //////////////////////////////////////////////////////////////////// @@ -153,7 +150,8 @@ set_final_x_scale(float final_x_scale) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_initial_y_scale(float initial_y_scale) { - _initial_y_texel_ratio = initial_y_scale; + _initial_y_scale = initial_y_scale; + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -162,7 +160,7 @@ set_initial_y_scale(float initial_y_scale) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_final_y_scale(float final_y_scale) { - _final_y_texel_ratio = final_y_scale; + _final_y_scale = final_y_scale; } //////////////////////////////////////////////////////////////////// @@ -172,6 +170,7 @@ set_final_y_scale(float final_y_scale) { INLINE void SpriteParticleRenderer:: set_nonanimated_theta(float theta) { _theta = theta; + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -189,7 +188,7 @@ set_alpha_blend_method(ParticleRendererBlendMethod bm) { //////////////////////////////////////////////////////////////////// INLINE void SpriteParticleRenderer:: set_alpha_disable(bool ad) { - _sprite_primitive->set_alpha_disable(ad); + _alpha_disable = ad; } //////////////////////////////////////////////////////////////////// @@ -198,7 +197,7 @@ set_alpha_disable(bool ad) { //////////////////////////////////////////////////////////////////// INLINE Texture *SpriteParticleRenderer:: get_texture() const { - return _sprite_primitive->get_texture(); + return _texture; } //////////////////////////////////////////////////////////////////// @@ -209,7 +208,7 @@ get_texture() const { //////////////////////////////////////////////////////////////////// INLINE const TexCoordf &SpriteParticleRenderer:: get_ll_uv() const { - return _sprite_primitive->get_ll_uv(); + return _ll_uv; } //////////////////////////////////////////////////////////////////// @@ -220,7 +219,7 @@ get_ll_uv() const { //////////////////////////////////////////////////////////////////// INLINE const TexCoordf &SpriteParticleRenderer:: get_ur_uv() const { - return _sprite_primitive->get_ur_uv(); + return _ur_uv; } //////////////////////////////////////////////////////////////////// @@ -265,7 +264,7 @@ get_anim_angle_flag() const { //////////////////////////////////////////////////////////////////// INLINE float SpriteParticleRenderer:: get_initial_x_scale() const { - return _initial_x_texel_ratio; + return _initial_x_scale; } //////////////////////////////////////////////////////////////////// @@ -274,7 +273,7 @@ get_initial_x_scale() const { //////////////////////////////////////////////////////////////////// INLINE float SpriteParticleRenderer:: get_final_x_scale() const { - return _final_x_texel_ratio; + return _final_x_scale; } //////////////////////////////////////////////////////////////////// @@ -283,7 +282,7 @@ get_final_x_scale() const { //////////////////////////////////////////////////////////////////// INLINE float SpriteParticleRenderer:: get_initial_y_scale() const { - return _initial_y_texel_ratio; + return _initial_y_scale; } //////////////////////////////////////////////////////////////////// @@ -292,7 +291,7 @@ get_initial_y_scale() const { //////////////////////////////////////////////////////////////////// INLINE float SpriteParticleRenderer:: get_final_y_scale() const { - return _final_y_texel_ratio; + return _final_y_scale; } //////////////////////////////////////////////////////////////////// @@ -319,5 +318,5 @@ get_alpha_blend_method() const { //////////////////////////////////////////////////////////////////// INLINE bool SpriteParticleRenderer:: get_alpha_disable() const { - return _sprite_primitive->get_alpha_disable(); + return _alpha_disable; } diff --git a/panda/src/particlesystem/spriteParticleRenderer.cxx b/panda/src/particlesystem/spriteParticleRenderer.cxx index a60312a5b6..556b024541 100644 --- a/panda/src/particlesystem/spriteParticleRenderer.cxx +++ b/panda/src/particlesystem/spriteParticleRenderer.cxx @@ -17,11 +17,16 @@ //////////////////////////////////////////////////////////////////// #include "spriteParticleRenderer.h" - #include "boundingSphere.h" -#include "geom.h" +#include "geomNode.h" #include "nodePath.h" #include "dcast.h" +#include "geomSprite.h" +#include "qpgeom.h" +#include "qpgeomVertexWriter.h" +#include "renderModeAttrib.h" +#include "texMatrixAttrib.h" +#include "textureAttrib.h" //////////////////////////////////////////////////////////////////// // Function : SpriteParticleRenderer::SpriteParticleRenderer @@ -32,19 +37,21 @@ SpriteParticleRenderer:: SpriteParticleRenderer(Texture *tex) : BaseParticleRenderer(PR_ALPHA_NONE), _color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)), - _initial_x_texel_ratio(0.02f), - _final_x_texel_ratio(0.02f), - _initial_y_texel_ratio(0.02f), - _final_y_texel_ratio(0.02f), + _ll_uv(0.0f, 0.0f), + _ur_uv(1.0f, 1.0f), + _initial_x_scale(0.02f), + _final_x_scale(0.02f), + _initial_y_scale(0.02f), + _final_y_scale(0.02f), _theta(0.0f), _animate_x_ratio(false), _animate_y_ratio(false), _animate_theta(false), + _alpha_disable(false), _blend_method(PP_BLEND_LINEAR), _pool_size(0), _source_type(ST_texture) { - _sprite_primitive = new GeomSprite(tex); init_geoms(); } @@ -56,17 +63,20 @@ SpriteParticleRenderer(Texture *tex) : SpriteParticleRenderer:: SpriteParticleRenderer(const SpriteParticleRenderer& copy) : BaseParticleRenderer(copy), _pool_size(0) { + _texture = copy._texture; _animate_x_ratio = copy._animate_x_ratio; _animate_y_ratio = copy._animate_y_ratio; _animate_theta = copy._animate_theta; + _alpha_disable = copy._alpha_disable; _blend_method = copy._blend_method; - _initial_x_texel_ratio = copy._initial_x_texel_ratio; - _final_x_texel_ratio = copy._final_x_texel_ratio; - _initial_y_texel_ratio = copy._initial_y_texel_ratio; - _final_y_texel_ratio = copy._final_y_texel_ratio; + _ll_uv = copy._ll_uv; + _ur_uv = copy._ur_uv; + _initial_x_scale = copy._initial_x_scale; + _final_x_scale = copy._final_x_scale; + _initial_y_scale = copy._initial_y_scale; + _final_y_scale = copy._final_y_scale; _theta = copy._theta; _color = copy._color; - _sprite_primitive = new GeomSprite(copy.get_texture()); init_geoms(); } @@ -76,7 +86,7 @@ SpriteParticleRenderer(const SpriteParticleRenderer& copy) : // Description : destructor //////////////////////////////////////////////////////////////////// SpriteParticleRenderer:: -~SpriteParticleRenderer(void) { +~SpriteParticleRenderer() { } //////////////////////////////////////////////////////////////////// @@ -85,7 +95,7 @@ SpriteParticleRenderer:: // Description : child dynamic copy //////////////////////////////////////////////////////////////////// BaseParticleRenderer *SpriteParticleRenderer:: -make_copy(void) { +make_copy() { return new SpriteParticleRenderer(*this); } @@ -166,6 +176,8 @@ set_from_node(const NodePath &node_path) { set_ll_uv(min_uv); set_ur_uv(max_uv); _source_type = ST_from_node; + + init_geoms(); } //////////////////////////////////////////////////////////////////// @@ -180,34 +192,29 @@ resize_pool(int new_size) { _pool_size = new_size; - GeomBindType _x_bind, _y_bind, _theta_bind; - // handle the x texel ratio - if (_animate_x_ratio == true) { + if (_animate_x_ratio) { _x_texel_array = PTA_float::empty_array(new_size); _x_bind = G_PER_PRIM; - } - else { + } else { _x_texel_array = PTA_float::empty_array(1); _x_bind = G_OVERALL; } // handle the y texel ratio - if (_animate_y_ratio == true) { + if (_animate_y_ratio) { _y_texel_array = PTA_float::empty_array(new_size); _y_bind = G_PER_PRIM; - } - else { + } else { _y_texel_array = PTA_float::empty_array(1); _y_bind = G_OVERALL; } // handle the theta vector - if (_animate_theta == true) { + if (_animate_theta) { _theta_array = PTA_float::empty_array(new_size); _theta_bind = G_PER_PRIM; - } - else { + } else { _theta_array = PTA_float::empty_array(1); _theta_bind = G_OVERALL; } @@ -215,12 +222,6 @@ resize_pool(int new_size) { _vertex_array = PTA_Vertexf::empty_array(new_size); _color_array = PTA_Colorf::empty_array(new_size); - _sprite_primitive->set_coords(_vertex_array); - _sprite_primitive->set_colors(_color_array, G_PER_PRIM); - _sprite_primitive->set_x_texel_ratio(_x_texel_array, _x_bind); - _sprite_primitive->set_y_texel_ratio(_y_texel_array, _y_bind); - _sprite_primitive->set_thetas(_theta_array, _theta_bind); - init_geoms(); } @@ -232,12 +233,97 @@ resize_pool(int new_size) { // modifications //////////////////////////////////////////////////////////////////// void SpriteParticleRenderer:: -init_geoms(void) { - _sprite_primitive->set_num_prims(0); +init_geoms() { + CPT(RenderState) state = _render_state; + + if (use_qpgeom) { + PT(qpGeom) qpgeom = new qpGeom; + _sprite_primitive = qpgeom; + + PT(qpGeomVertexArrayFormat) array_format = new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexColumn::NT_float32, + qpGeomVertexColumn::C_point, + InternalName::get_color(), 1, qpGeomVertexColumn::NT_packed_dabc, + qpGeomVertexColumn::C_color); + + if (_animate_theta || _theta != 0.0f) { + array_format->add_column + (InternalName::get_rotate(), 1, qpGeomVertexColumn::NT_float32, + qpGeomVertexColumn::C_other); + } + + _base_x_scale = _initial_x_scale; + _base_y_scale = _base_x_scale; + + // We also scale the particle size by the number of texels used, + // by established convention. + float texel_scale = 1.0f; + if (_texture != (Texture *)NULL) { + float x_texels = _texture->get_x_size() * fabs(_ur_uv[0] - _ll_uv[0]); + float y_texels = _texture->get_y_size() * fabs(_ur_uv[1] - _ll_uv[1]); + texel_scale = x_texels; + _base_y_scale = _base_x_scale / y_texels * x_texels; + } + + if (_animate_x_ratio) { + _base_x_scale = max(_initial_x_scale, _final_x_scale); + array_format->add_column + (InternalName::get_scale_x(), 1, qpGeomVertexColumn::NT_float32, + qpGeomVertexColumn::C_other); + } + + if (_animate_y_ratio || _initial_y_scale != _base_y_scale) { + array_format->add_column + (InternalName::get_scale_y(), 1, qpGeomVertexColumn::NT_float32, + qpGeomVertexColumn::C_other); + } + + CPT(qpGeomVertexFormat) format = qpGeomVertexFormat::register_format + (new qpGeomVertexFormat(array_format)); + + _vdata = new qpGeomVertexData + ("particles", format, qpGeomUsageHint::UH_dynamic); + qpgeom->set_vertex_data(_vdata); + _sprites = new qpGeomSprites(qpGeomUsageHint::UH_dynamic); + qpgeom->add_primitive(_sprites); + + state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _base_x_scale * texel_scale, true)); + + if (_texture != (Texture *)NULL) { + state = state->add_attrib(TextureAttrib::make(_texture)); + } + + // Build a matrix to convert the texture coordinates to the ll, ur + // space. + LPoint2f ul(_ll_uv[0], _ur_uv[1]); + LPoint2f lr(_ur_uv[0], _ll_uv[1]); + LVector2f sc = lr - ul; + + LMatrix4f mat + (sc[0], 0.0f, 0.0f, 0.0f, + 0.0f, sc[1], 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + ul[0], ul[1], 0.0f, 1.0f); + state = state->add_attrib(TexMatrixAttrib::make(mat)); + + } else { + PT(GeomSprite) sprite = new GeomSprite(get_texture()); + _sprite_primitive = sprite; + _sprite_primitive->set_num_prims(0); + + _sprite_primitive->set_coords(_vertex_array); + _sprite_primitive->set_colors(_color_array, G_PER_PRIM); + sprite->set_x_texel_ratio(_x_texel_array, _x_bind); + sprite->set_y_texel_ratio(_y_texel_array, _y_bind); + sprite->set_thetas(_theta_array, _theta_bind); + sprite->set_ll_uv(_ll_uv); + sprite->set_ur_uv(_ur_uv); + sprite->set_alpha_disable(_alpha_disable); + } GeomNode *render_node = get_render_node(); render_node->remove_all_geoms(); - render_node->add_geom(_sprite_primitive, _render_state); + render_node->add_geom(_sprite_primitive, state); } //////////////////////////////////////////////////////////////////// @@ -277,15 +363,22 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { float *cur_x_texel = &_x_texel_array[0]; float *cur_y_texel = &_y_texel_array[0]; float *cur_theta = &_theta_array[0]; + qpGeomVertexWriter vertex(_vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(_vdata, InternalName::get_color()); + qpGeomVertexWriter rotate(_vdata, InternalName::get_rotate()); + qpGeomVertexWriter scale_x(_vdata, InternalName::get_scale_x()); + qpGeomVertexWriter scale_y(_vdata, InternalName::get_scale_y()); - if (_animate_x_ratio == false) - *cur_x_texel = _initial_x_texel_ratio; - - if (_animate_y_ratio == false) - *cur_y_texel = _initial_y_texel_ratio; - - if (_animate_theta == false) - *cur_theta = _theta; + if (!use_qpgeom) { + if (!_animate_x_ratio) + *cur_x_texel = _initial_x_scale; + + if (!_animate_y_ratio) + *cur_y_texel = _initial_y_scale; + + if (!_animate_theta) + *cur_theta = _theta; + } // init the aabb _aabb_min.set(99999.0f, 99999.0f, 99999.0f); @@ -295,31 +388,30 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { for (i = 0; i < (int)po_vector.size(); i++) { cur_particle = (BaseParticle *) po_vector[i].p(); - if (cur_particle->get_alive() == false) + if (!cur_particle->get_alive()) continue; + LPoint3f position = cur_particle->get_position(); + // x aabb adjust - if (cur_particle->get_position().get_x() > _aabb_max.get_x()) - _aabb_max[0] = cur_particle->get_position().get_x(); - else if (cur_particle->get_position().get_x() < _aabb_min.get_x()) - _aabb_min[0] = cur_particle->get_position().get_x(); + if (position[0] > _aabb_max[0]) + _aabb_max[0] = position[0]; + else if (position[0] < _aabb_min[0]) + _aabb_min[0] = position[0]; // y aabb adjust - if (cur_particle->get_position().get_y() > _aabb_max.get_y()) - _aabb_max[1] = cur_particle->get_position().get_y(); - else if (cur_particle->get_position().get_y() < _aabb_min.get_y()) - _aabb_min[1] = cur_particle->get_position().get_y(); + if (position[1] > _aabb_max[1]) + _aabb_max[1] = position[1]; + else if (position[1] < _aabb_min[1]) + _aabb_min[1] = position[1]; // z aabb adjust - if (cur_particle->get_position().get_z() > _aabb_max.get_z()) - _aabb_max[2] = cur_particle->get_position().get_z(); - else if (cur_particle->get_position().get_z() < _aabb_min.get_z()) - _aabb_min[2] = cur_particle->get_position().get_z(); + if (position[2] > _aabb_max[2]) + _aabb_max[2] = position[2]; + else if (position[2] < _aabb_min[2]) + _aabb_min[2] = position[2]; - // put the current vertex into the array - *cur_vert++ = cur_particle->get_position(); - - // put the current color into the array + // Calculate the color Colorf c = _color; int alphamode=get_alpha_mode(); @@ -339,41 +431,88 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { } } - *cur_color++ = c; + if (use_qpgeom) { + vertex.add_data3f(position); + color.add_data4f(c); - // handle x scaling - if (_animate_x_ratio == true) { - float t = cur_particle->get_parameterized_age(); + if (_animate_x_ratio) { + float t = cur_particle->get_parameterized_age(); + + if (_blend_method == PP_BLEND_CUBIC) + t = CUBIC_T(t); + + float scale = (_initial_x_scale + + (t * (_final_x_scale - _initial_x_scale))); + scale_x.add_data1f(scale / _base_x_scale); - if (_blend_method == PP_BLEND_CUBIC) - t = CUBIC_T(t); + } else if (scale_x.has_column()) { + scale_x.add_data1f(_initial_x_scale / _base_x_scale); + } - *cur_x_texel++ = (_initial_x_texel_ratio + - (t * (_final_x_texel_ratio - _initial_x_texel_ratio))); + if (_animate_y_ratio) { + float t = cur_particle->get_parameterized_age(); + + if (_blend_method == PP_BLEND_CUBIC) + t = CUBIC_T(t); + + float scale = (_initial_y_scale + + (t * (_final_y_scale - _initial_y_scale))); + scale_y.add_data1f(scale / _base_y_scale); + + } else if (scale_y.has_column()) { + scale_y.add_data1f(_initial_y_scale / _base_y_scale); + } + + if (_animate_theta) { + rotate.add_data1f(cur_particle->get_theta()); + } else if (rotate.has_column()) { + rotate.add_data1f(_theta); + } + + } else { + // put the current vertex into the array + *cur_vert++ = position; + *cur_color++ = c; + + // handle x scaling + if (_animate_x_ratio) { + float t = cur_particle->get_parameterized_age(); + + if (_blend_method == PP_BLEND_CUBIC) + t = CUBIC_T(t); + + *cur_x_texel++ = (_initial_x_scale + + (t * (_final_x_scale - _initial_x_scale))); + } + + // handle y scaling + if (_animate_y_ratio) { + float t = cur_particle->get_parameterized_age(); + + if (_blend_method == PP_BLEND_CUBIC) + t = CUBIC_T(t); + + *cur_y_texel++ = (_initial_y_scale + + (t * (_final_y_scale - _initial_y_scale))); + } + + // handle theta + if (_animate_theta) + *cur_theta++ = cur_particle->get_theta(); } - // handle y scaling - if (_animate_y_ratio == true) { - float t = cur_particle->get_parameterized_age(); - - if (_blend_method == PP_BLEND_CUBIC) - t = CUBIC_T(t); - - *cur_y_texel++ = (_initial_y_texel_ratio + - (t * (_final_y_texel_ratio - _initial_y_texel_ratio))); - } - - // handle theta - if (_animate_theta == true) - *cur_theta++ = cur_particle->get_theta(); - // maybe jump out early? remaining_particles--; if (remaining_particles == 0) break; } - _sprite_primitive->set_num_prims(ttl_particles); + if (use_qpgeom) { + _sprites->clear_vertices(); + _sprites->add_next_vertices(ttl_particles); + } else { + _sprite_primitive->set_num_prims(ttl_particles); + } // done filling geompoint node, now do the bb stuff LPoint3f aabb_center = _aabb_min + ((_aabb_max - _aabb_min) * 0.5f); @@ -413,10 +552,10 @@ write(ostream &out, int indent) const { out.width(indent+2); out<<""; out<<"_y_texel_array "<<_y_texel_array<<"\n"; out.width(indent+2); out<<""; out<<"_theta_array "<<_theta_array<<"\n"; out.width(indent+2); out<<""; out<<"_color "<<_color<<"\n"; - out.width(indent+2); out<<""; out<<"_initial_x_texel_ratio "<<_initial_x_texel_ratio<<"\n"; - out.width(indent+2); out<<""; out<<"_final_x_texel_ratio "<<_final_x_texel_ratio<<"\n"; - out.width(indent+2); out<<""; out<<"_initial_y_texel_ratio "<<_initial_y_texel_ratio<<"\n"; - out.width(indent+2); out<<""; out<<"_final_y_texel_ratio "<<_final_y_texel_ratio<<"\n"; + out.width(indent+2); out<<""; out<<"_initial_x_scale "<<_initial_x_scale<<"\n"; + out.width(indent+2); out<<""; out<<"_final_x_scale "<<_final_x_scale<<"\n"; + out.width(indent+2); out<<""; out<<"_initial_y_scale "<<_initial_y_scale<<"\n"; + out.width(indent+2); out<<""; out<<"_final_y_scale "<<_final_y_scale<<"\n"; out.width(indent+2); out<<""; out<<"_theta "<<_theta<<"\n"; out.width(indent+2); out<<""; out<<"_animate_x_ratio "<<_animate_x_ratio<<"\n"; out.width(indent+2); out<<""; out<<"_animate_y_ratio "<<_animate_y_ratio<<"\n"; diff --git a/panda/src/particlesystem/spriteParticleRenderer.h b/panda/src/particlesystem/spriteParticleRenderer.h index 6103c0f437..fe07391e50 100644 --- a/panda/src/particlesystem/spriteParticleRenderer.h +++ b/panda/src/particlesystem/spriteParticleRenderer.h @@ -20,15 +20,16 @@ #define SPRITEPARTICLERENDERER_H #include "pandabase.h" +#include "baseParticleRenderer.h" +#include "baseParticle.h" #include "texture.h" #include "pointerTo.h" #include "pointerToArray.h" #include "pta_float.h" #include "geom.h" #include "geomSprite.h" - -#include "baseParticleRenderer.h" -#include "baseParticle.h" +#include "qpgeomVertexData.h" +#include "qpgeomSprites.h" class NodePath; @@ -91,24 +92,34 @@ PUBLISHED: virtual void write(ostream &out, int indent=0) const; private: - PT(GeomSprite) _sprite_primitive; + PT(Geom) _sprite_primitive; + PT(qpGeomSprites) _sprites; + PT(Texture) _texture; + PTA_Vertexf _vertex_array; PTA_Colorf _color_array; PTA_float _x_texel_array; PTA_float _y_texel_array; PTA_float _theta_array; + GeomBindType _x_bind, _y_bind, _theta_bind; + PT(qpGeomVertexData) _vdata; Colorf _color; - float _initial_x_texel_ratio; - float _final_x_texel_ratio; - float _initial_y_texel_ratio; - float _final_y_texel_ratio; + TexCoordf _ll_uv, _ur_uv; + float _initial_x_scale; + float _final_x_scale; + float _initial_y_scale; + float _final_y_scale; float _theta; + float _base_x_scale; + float _base_y_scale; + float _aspect_ratio; bool _animate_x_ratio; bool _animate_y_ratio; bool _animate_theta; + bool _alpha_disable; ParticleRendererBlendMethod _blend_method; diff --git a/panda/src/pgraph/renderModeAttrib.I b/panda/src/pgraph/renderModeAttrib.I index 94817184a6..9523a9a17e 100644 --- a/panda/src/pgraph/renderModeAttrib.I +++ b/panda/src/pgraph/renderModeAttrib.I @@ -24,9 +24,11 @@ // RenderModeAttrib object. //////////////////////////////////////////////////////////////////// INLINE RenderModeAttrib:: -RenderModeAttrib(RenderModeAttrib::Mode mode, float thickness) : +RenderModeAttrib(RenderModeAttrib::Mode mode, float thickness, + bool perspective) : _mode(mode), - _thickness(thickness) + _thickness(thickness), + _perspective(perspective) { } @@ -43,10 +45,29 @@ get_mode() const { //////////////////////////////////////////////////////////////////// // Function: RenderModeAttrib::get_thickness // Access: Published -// Description: Returns the line width. This is only relevant when -// the mode is M_wireframe. +// Description: Returns the line width or point thickness. This is +// only relevant when rendering points or lines, such as +// when the mode is M_wireframe or M_point (or when +// rendering actual points or lines primitives in +// M_polygon mode). //////////////////////////////////////////////////////////////////// INLINE float RenderModeAttrib:: get_thickness() const { return _thickness; } + +//////////////////////////////////////////////////////////////////// +// Function: RenderModeAttrib::get_perspective +// Access: Published +// Description: Returns the perspective flag. When this is true, the +// point thickness represented by get_thickness() is +// actually a width in 3-d units, and the points should +// scale according to perspective. When it is false, +// the default, the point thickness is actually a width +// in pixels, and points are a uniform size regardless +// of distance from the camera. +//////////////////////////////////////////////////////////////////// +INLINE bool RenderModeAttrib:: +get_perspective() const { + return _perspective; +} diff --git a/panda/src/pgraph/renderModeAttrib.cxx b/panda/src/pgraph/renderModeAttrib.cxx index 3953157bc2..197e488bcf 100644 --- a/panda/src/pgraph/renderModeAttrib.cxx +++ b/panda/src/pgraph/renderModeAttrib.cxx @@ -39,10 +39,18 @@ TypeHandle RenderModeAttrib::_type_handle; // linestrip lines; it also specifies the diameter of // points. It is not supported in DirectX, which only // supports pixel-based lines and points. +// +// If perspective is true, the point thickness +// represented is actually a width in 3-d units, and the +// points should scale according to perspective. When +// it is false, the point thickness is actually a width +// in pixels, and points are a uniform size regardless +// of distance from the camera. This feature is not +// supported by all graphics drivers. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) RenderModeAttrib:: -make(RenderModeAttrib::Mode mode, float thickness) { - RenderModeAttrib *attrib = new RenderModeAttrib(mode, thickness); +make(RenderModeAttrib::Mode mode, float thickness, bool perspective) { + RenderModeAttrib *attrib = new RenderModeAttrib(mode, thickness, perspective); return return_new(attrib); } @@ -85,6 +93,10 @@ output(ostream &out) const { out << "point(" << get_thickness() << ")"; break; } + + if (get_perspective()) { + out << ", perspective"; + } } //////////////////////////////////////////////////////////////////// @@ -112,6 +124,9 @@ compare_to_impl(const RenderAttrib *other) const { if (_thickness != ta->_thickness) { return _thickness < ta->_thickness ? -1 : 1; } + if (_perspective != ta->_perspective) { + return (int)_perspective - (int)ta->_perspective; + } return 0; } @@ -143,7 +158,7 @@ compose_impl(const RenderAttrib *other) const { mode = get_mode(); } - return make(mode, get_thickness()); + return make(mode, ta->get_thickness(), ta->get_perspective()); } //////////////////////////////////////////////////////////////////// @@ -159,7 +174,7 @@ compose_impl(const RenderAttrib *other) const { //////////////////////////////////////////////////////////////////// RenderAttrib *RenderModeAttrib:: make_default_impl() const { - return new RenderModeAttrib(M_filled, 1.0f); + return new RenderModeAttrib(M_filled, 1.0f, false); } //////////////////////////////////////////////////////////////////// @@ -185,6 +200,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_int8(_mode); dg.add_float32(_thickness); + dg.add_bool(_perspective); } //////////////////////////////////////////////////////////////////// @@ -197,7 +213,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { //////////////////////////////////////////////////////////////////// TypedWritable *RenderModeAttrib:: make_from_bam(const FactoryParams ¶ms) { - RenderModeAttrib *attrib = new RenderModeAttrib(M_filled, 0.0f); + RenderModeAttrib *attrib = new RenderModeAttrib(M_filled, 1.0f, false); DatagramIterator scan; BamReader *manager; @@ -220,4 +236,8 @@ fillin(DatagramIterator &scan, BamReader *manager) { _mode = (Mode)scan.get_int8(); _thickness = scan.get_float32(); + _perspective = false; + if (manager->get_file_minor_ver() >= 18) { + _perspective = scan.get_bool(); + } } diff --git a/panda/src/pgraph/renderModeAttrib.h b/panda/src/pgraph/renderModeAttrib.h index 11f15a0742..f2f5c32471 100644 --- a/panda/src/pgraph/renderModeAttrib.h +++ b/panda/src/pgraph/renderModeAttrib.h @@ -39,13 +39,15 @@ PUBLISHED: }; private: - INLINE RenderModeAttrib(Mode mode, float thickness); + INLINE RenderModeAttrib(Mode mode, float thickness, bool perspective); PUBLISHED: - static CPT(RenderAttrib) make(Mode mode, float thickness = 1.0f); + static CPT(RenderAttrib) make(Mode mode, float thickness = 1.0f, + bool perspective = false); INLINE Mode get_mode() const; INLINE float get_thickness() const; + INLINE bool get_perspective() const; public: virtual void issue(GraphicsStateGuardianBase *gsg) const; @@ -59,6 +61,7 @@ protected: private: Mode _mode; float _thickness; + bool _perspective; public: static void register_with_read_factory(); diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 685d5b0697..dbd9c7657d 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -34,7 +34,7 @@ static const unsigned short _bam_major_ver = 4; // Bumped to major version 3 on 12/8/00 to change float64's to float32's. // Bumped to major version 4 on 4/10/02 to store new scene graph. -static const unsigned short _bam_minor_ver = 17; +static const unsigned short _bam_minor_ver = 18; // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse. // Bumped to minor version 2 on 4/12/03 to add num_components to texture. // Bumped to minor version 3 on 4/15/03 to add ImageBuffer::_alpha_file_channel @@ -52,6 +52,7 @@ static const unsigned short _bam_minor_ver = 17; // Bumped to minor version 15 on 1/16/05 to remove width from GeomLine, etc. // Bumped to minor version 16 on 2/24/05 to add TextureStage::rgb_scale, etc. // Bumped to minor version 17 on 3/03/05 to add 3-d textures, etc. +// Bumped to minor version 18 on 4/05/05 to add RenderModeAttrib::perspective. #endif