qpgeom particles

This commit is contained in:
David Rose 2005-04-06 04:06:28 +00:00
parent 5195da67ab
commit 8dd9c1419c
31 changed files with 1207 additions and 283 deletions

View File

@ -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

View File

@ -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);

View File

@ -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];
}

View File

@ -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<SpriteData>());
// 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

View File

@ -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<string> _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<GLuint> 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 &params);

View File

@ -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 \

View File

@ -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();

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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 &copy) :
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 &params) {
qpGeomSprites *object = new qpGeomSprites(qpGeomUsageHint::UH_client);
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}

View File

@ -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 &copy);
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 &params);
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

View File

@ -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));
}
////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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";

View File

@ -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;

View File

@ -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;
}

View File

@ -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 &params) {
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();
}
}

View File

@ -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();

View File

@ -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