gl display lists with new geom

This commit is contained in:
David Rose 2005-03-19 01:34:05 +00:00
parent 70a94646f7
commit 3f7956f4e9
18 changed files with 370 additions and 133 deletions

View File

@ -670,7 +670,7 @@ finish_decal() {
// are ok, false to abort this group of primitives.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
begin_draw_primitives(const qpGeomVertexData *data) {
begin_draw_primitives(const qpGeom *, const qpGeomVertexData *data) {
_vertex_data = data;
return true;
}
@ -719,6 +719,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
end_draw_primitives() {
_vertex_data = NULL;
}
////////////////////////////////////////////////////////////////////

View File

@ -148,7 +148,7 @@ public:
virtual CPT(RenderState) begin_decal_base_second();
virtual void finish_decal();
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data);
virtual void draw_triangles(const qpGeomTriangles *primitive);
virtual void draw_tristrips(const qpGeomTristrips *primitive);
virtual void draw_trifans(const qpGeomTrifans *primitive);

View File

@ -2606,10 +2606,10 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
// are ok, false to abort this group of primitives.
////////////////////////////////////////////////////////////////////
bool DXGraphicsStateGuardian8::
begin_draw_primitives(const qpGeomVertexData *vertex_data) {
begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) {
DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
if (!GraphicsStateGuardian::begin_draw_primitives(vertex_data)) {
if (!GraphicsStateGuardian::begin_draw_primitives(geom, vertex_data)) {
return false;
}
nassertr(_vertex_data != (qpGeomVertexData *)NULL, false);
@ -2694,6 +2694,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
end_draw_primitives() {
GraphicsStateGuardian::end_draw_primitives();
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
}

View File

@ -90,7 +90,7 @@ public:
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc);
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc);
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data);
virtual void draw_triangles(const qpGeomTriangles *primitive);
virtual void draw_tristrips(const qpGeomTristrips *primitive);
virtual void end_draw_primitives();

View File

@ -30,6 +30,8 @@ public:
// This is the GL display list index.
GLuint _index;
UpdateSeq _modified;
// The number of vertices encoded in the display list, for stats
// reporting.
#ifdef DO_PSTATS

View File

@ -2030,14 +2030,53 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
// are ok, false to abort this group of primitives.
////////////////////////////////////////////////////////////////////
bool CLP(GraphicsStateGuardian)::
begin_draw_primitives(const qpGeomVertexData *vertex_data) {
begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) {
DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
if (!GraphicsStateGuardian::begin_draw_primitives(vertex_data)) {
if (!GraphicsStateGuardian::begin_draw_primitives(geom, vertex_data)) {
return false;
}
nassertr(_vertex_data != (qpGeomVertexData *)NULL, false);
_geom_display_list = NULL;
if (geom->get_usage_hint() == qpGeomUsageHint::UH_static &&
_vertex_data->get_usage_hint() == qpGeomUsageHint::UH_static &&
display_lists) {
// If the geom appears to be totally static, try to build it into
// a display list.
GeomContext *gc = ((qpGeom *)geom)->prepare_now(get_prepared_objects(), this);
nassertr(gc != (GeomContext *)NULL, false);
CLP(GeomContext) *ggc = DCAST(CLP(GeomContext), gc);
if (ggc->_modified == geom->get_modified()) {
// If it hasn't been modified, just play the display list again.
GLP(CallList)(ggc->_index);
#ifdef DO_PSTATS
_vertices_display_list_pcollector.add_level(ggc->_num_verts);
#endif
// And now we don't need to do anything else for this geom.
return false;
}
// If it has been modified, or this is the first time, then we
// need to build the display list up.
GLP(NewList)(ggc->_index, GL_COMPILE_AND_EXECUTE);
ggc->_modified = geom->get_modified();
_geom_display_list = ggc;
#ifdef DO_PSTATS
// Count up the number of vertices we're about to render, by
// checking the PStats vertex counters now, and at the end. This is
// kind of hacky, but this is debug code.
_num_display_list_verts_before =
_vertices_tristrip_pcollector.get_level() +
_vertices_trifan_pcollector.get_level() +
_vertices_tri_pcollector.get_level() +
_vertices_other_pcollector.get_level();
#endif
}
const qpGeomVertexArrayData *array_data;
int num_components;
qpGeomVertexDataType::NumericType numeric_type;
@ -2051,9 +2090,6 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
GLP(VertexPointer)(num_components, get_numeric_type(numeric_type),
stride, client_pointer + start);
GLP(EnableClientState)(GL_VERTEX_ARRAY);
} else {
// No vertex data? No primitives!
return false;
}
if (wants_normals() &&
@ -2073,14 +2109,8 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
array_data, num_components, numeric_type,
start, stride)) {
const unsigned char *client_pointer = setup_array_data(array_data);
if (numeric_type == qpGeomVertexDataType::NT_packed_argb) {
// Temporary hack--this will probably reverse r and b.
GLP(ColorPointer)(4, GL_UNSIGNED_BYTE, stride, client_pointer + start);
} else {
GLP(ColorPointer)(num_components, get_numeric_type(numeric_type),
stride, client_pointer + start);
}
GLP(EnableClientState)(GL_COLOR_ARRAY);
} else {
@ -2105,8 +2135,6 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
}
issue_scene_graph_color();
return true;
}
@ -2168,7 +2196,23 @@ draw_tristrips(const qpGeomTristrips *primitive) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
end_draw_primitives() {
GLP(DisableClientState)(GL_VERTEX_ARRAY);
if (_geom_display_list != NULL) {
// If we were building a display list, close it now.
GLP(EndList)();
#ifdef DO_PSTATS
float num_verts_after =
_vertices_tristrip_pcollector.get_level() +
_vertices_trifan_pcollector.get_level() +
_vertices_tri_pcollector.get_level() +
_vertices_other_pcollector.get_level();
float num_verts = num_verts_after - _num_display_list_verts_before;
_geom_display_list->_num_verts = (int)(num_verts + 0.5);
#endif
}
_geom_display_list = NULL;
GraphicsStateGuardian::end_draw_primitives();
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
}
@ -2262,6 +2306,30 @@ release_texture(TextureContext *tc) {
////////////////////////////////////////////////////////////////////
GeomContext *CLP(GraphicsStateGuardian)::
prepare_geom(Geom *geom) {
// Temporary test until the experimental Geom rewrite becomes the
// actual Geom implementation.
if (geom->is_exact_type(qpGeom::get_class_type())) {
CLP(GeomContext) *ggc = new CLP(GeomContext)(geom);
ggc->_index = GLP(GenLists)(1);
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "preparing " << *geom << ", index " << ggc->_index << "\n";
}
if (ggc->_index == 0) {
GLCAT.error()
<< "Ran out of display list indices.\n";
delete ggc;
return NULL;
}
report_my_gl_errors();
return ggc;
} else {
// Original Geom display list implementation. Slightly broken,
// since it doesn't work well with scene graph color
// manipulations.
if (!_vertex_colors_enabled) {
// We can't build a display list (or play back a display list) if
// its color is overridden with a scene graph color. Maybe if we
@ -2325,6 +2393,7 @@ prepare_geom(Geom *geom) {
report_my_gl_errors();
return ggc;
}
}
////////////////////////////////////////////////////////////////////
@ -2464,7 +2533,7 @@ setup_array_data(const qpGeomVertexArrayData *data) {
// No support for buffer objects; always render from client.
return data->get_data();
}
if (!vertex_buffers ||
if (!vertex_buffers || _geom_display_list != NULL ||
data->get_usage_hint() == qpGeomUsageHint::UH_client) {
// The array specifies client rendering only, or buffer objects
// are configured off.
@ -2534,12 +2603,12 @@ apply_index_buffer(IndexBufferContext *ibc) {
}
if (gibc->changed_size()) {
_glBufferData(GL_ELEMENT_ARRAY_BUFFER, gibc->get_data()->get_data_size_bytes(),
gibc->get_data()->get_vertices(),
gibc->get_data()->get_flat_last_vertices(),
get_usage(gibc->get_data()->get_usage_hint()));
} else {
_glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, gibc->get_data_size_bytes(),
gibc->get_data()->get_vertices());
gibc->get_data()->get_flat_last_vertices());
}
gibc->mark_loaded();
@ -2593,19 +2662,19 @@ const unsigned short *CLP(GraphicsStateGuardian)::
setup_primitive(const qpGeomPrimitive *data) {
if (!_supports_buffers) {
// No support for buffer objects; always render from client.
return data->get_vertices();
return data->get_flat_last_vertices();
}
if (!vertex_buffers ||
if (!vertex_buffers || _geom_display_list != NULL ||
data->get_usage_hint() == qpGeomUsageHint::UH_client) {
// The array specifies client rendering only, or buffer objects
// are configured off.
_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return data->get_vertices();
return data->get_flat_last_vertices();
}
// Prepare the buffer object and bind it.
IndexBufferContext *ibc = ((qpGeomPrimitive *)data)->prepare_now(get_prepared_objects(), this);
nassertr(ibc != (IndexBufferContext *)NULL, data->get_vertices());
nassertr(ibc != (IndexBufferContext *)NULL, data->get_flat_last_vertices());
apply_index_buffer(ibc);
// NULL is the OpenGL convention for the first byte of the buffer.

View File

@ -58,6 +58,8 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
class CLP(GeomContext);
////////////////////////////////////////////////////////////////////
// Class : GLGraphicsStateGuardian
// Description : A GraphicsStateGuardian specialized for rendering
@ -90,7 +92,7 @@ public:
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc);
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc);
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data);
virtual void draw_triangles(const qpGeomTriangles *primitive);
virtual void draw_tristrips(const qpGeomTristrips *primitive);
virtual void end_draw_primitives();
@ -315,6 +317,8 @@ protected:
int _pass_number;
bool _auto_rescale_normal;
CLP(GeomContext) *_geom_display_list;
float _num_display_list_verts_before;
int _error_count;

View File

@ -84,7 +84,9 @@ ConfigVariableBool retained_mode
"creates specific cache information (like display lists or vertex "
"buffers) with the GSG for static geometry, when supported by the "
"GSG. Set it false to use only immediate mode, which sends the "
"vertices to the GSG every frame."));
"vertices to the GSG every frame. This is used only in the "
"original Geom implementation; it is replaced by display-lists "
"in the experimental Geom rewrite."));
ConfigVariableBool vertex_buffers
("vertex-buffers", false,
@ -95,6 +97,16 @@ ConfigVariableBool vertex_buffers
"graphics memory (which might otherwise be used for textures "
"or offscreen buffers)."));
ConfigVariableBool display_lists
("display-lists", false,
PRC_DESC("Set this true to allow the use of OpenGL display lists for "
"rendering static geometry. On some systems, this can result "
"in a performance improvement over vertex buffers alone; on "
"other systems (particularly low-end systems) it makes little to "
"no difference. This has no effect on DirectX rendering. If "
"vertex-buffers is also enabled, then OpenGL buffer objects "
"will also be created for dynamic geometry."));
ConfigVariableBool use_qpgeom
("use-qpgeom", false,
PRC_DESC("A temporary variable while the experimental Geom rewrite is "

View File

@ -52,6 +52,7 @@ extern EXPCL_PANDA ConfigVariableBool keep_texture_ram;
extern EXPCL_PANDA ConfigVariableBool keep_geom_ram;
extern EXPCL_PANDA ConfigVariableBool retained_mode;
extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
extern EXPCL_PANDA ConfigVariableBool display_lists;
extern EXPCL_PANDA ConfigVariableBool use_qpgeom;

View File

@ -17,6 +17,23 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_usage_hint
// Access: Published
// Description: Returns the minimum (i.e. most dynamic) usage_hint
// among all of the individual GeomPrimitives that have
// been added to the geom.
////////////////////////////////////////////////////////////////////
INLINE qpGeomUsageHint::UsageHint qpGeom::
get_usage_hint() const {
CDReader cdata(_cycler);
if (!cdata->_got_usage_hint) {
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
((qpGeom *)this)->reset_usage_hint(cdataw);
}
return cdata->_usage_hint;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_vertex_data
// Access: Published
@ -71,6 +88,7 @@ modify_primitive(int i) {
clear_cache();
CDWriter cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
cdata->_got_usage_hint = false;
return cdata->_primitives[i];
}
@ -85,6 +103,19 @@ set_primitive(int i, const qpGeomPrimitive *primitive) {
clear_cache();
CDWriter cdata(_cycler);
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
if (cdata->_got_usage_hint &&
cdata->_primitives[i]->get_usage_hint() != primitive->get_usage_hint()) {
if (cdata->_primitives[i]->get_usage_hint() < primitive->get_usage_hint()) {
// If we're reducing the usage hint, we might also be reducing
// the minimum usage hit.
cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
} else { // (cdata->_primitives[i]->get_usage_hint() > primitive->get_usage_hint())
// If we're increasing it, we might have to rederive the minimum.
if (cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) {
cdata->_got_usage_hint = false;
}
}
}
cdata->_primitives[i] = (qpGeomPrimitive *)primitive;
}
@ -94,7 +125,10 @@ set_primitive(int i, const qpGeomPrimitive *primitive) {
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeom::CData::
CData() {
CData() :
_usage_hint(qpGeomUsageHint::UH_static),
_got_usage_hint(false)
{
}
////////////////////////////////////////////////////////////////////
@ -105,7 +139,9 @@ CData() {
INLINE qpGeom::CData::
CData(const qpGeom::CData &copy) :
_data(copy._data),
_primitives(copy._primitives)
_primitives(copy._primitives),
_usage_hint(copy._usage_hint),
_got_usage_hint(copy._got_usage_hint)
{
}

View File

@ -22,6 +22,7 @@
#include "bamReader.h"
#include "bamWriter.h"
UpdateSeq qpGeom::_next_modified;
TypeHandle qpGeom::_type_handle;
////////////////////////////////////////////////////////////////////
@ -152,6 +153,10 @@ add_primitive(const qpGeomPrimitive *primitive) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_primitives.push_back((qpGeomPrimitive *)primitive);
if (cdata->_got_usage_hint) {
cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
}
}
////////////////////////////////////////////////////////////////////
@ -164,6 +169,12 @@ remove_primitive(int i) {
clear_cache();
CDWriter cdata(_cycler);
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
if (cdata->_got_usage_hint &&
cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) {
// Maybe we're raising the minimum usage_hint; we have to rederive
// the usage_hint later.
cdata->_got_usage_hint = false;
}
cdata->_primitives.erase(cdata->_primitives.begin() + i);
}
@ -203,6 +214,34 @@ get_num_bytes() const {
return num_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_modified
// Access: Published
// Description: Returns the maximum UpdateSeq of all the Geom's
// individual primitives and vertex arrays. This,
// therefore, will change only when any part of the Geom
// changes.
////////////////////////////////////////////////////////////////////
UpdateSeq qpGeom::
get_modified() const {
CDReader cdata(_cycler);
UpdateSeq seq;
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
seq = max(seq, (*pi)->get_modified());
}
int num_arrays = cdata->_data->get_num_arrays();
for (int i = 0; i < num_arrays; ++i) {
seq = max(seq, cdata->_data->get_array(i)->get_modified());
}
return seq;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::munge_geom
// Access: Published
@ -342,9 +381,25 @@ clear_cache() {
////////////////////////////////////////////////////////////////////
void qpGeom::
draw(GraphicsStateGuardianBase *gsg, const qpGeomVertexData *vertex_data) const {
#ifdef DO_PIPELINING
// Make sure the usage_hint is already updated before we start to
// draw, so we don't end up with a circular lock if the GSG asks us
// to update this while we're holding the read lock.
{
CDReader cdata(_cycler);
if (!cdata->_got_usage_hint) {
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
((qpGeom *)this)->reset_usage_hint(cdataw);
}
}
// TODO: fix up the race condition between this line and the next.
// Maybe CDWriter's elevate-to-write should return the read lock to
// its original locked state when it's done.
#endif // DO_PIPELINING
CDReader cdata(_cycler);
if (gsg->begin_draw_primitives(vertex_data)) {
if (gsg->begin_draw_primitives(this, vertex_data)) {
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
@ -355,6 +410,25 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomVertexData *vertex_data) const
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_next_modified
// Access: Public
// Description: Returns a monotonically increasing sequence. Each
// time this is called, a new sequence number is
// returned, higher than the previous value.
//
// This is used to ensure that
// GeomVertexArrayData::get_modified() and
// GeomPrimitive::get_modified() update from the same
// space, so that Geom::get_modified() returns a
// meaningful value.
////////////////////////////////////////////////////////////////////
UpdateSeq qpGeom::
get_next_modified() {
++_next_modified;
return _next_modified;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::recompute_bound
// Access: Protected, Virtual
@ -445,6 +519,23 @@ remove_cache_entry(const qpGeomMunger *modifier) const {
((qpGeom *)this)->_cycler.release_write_stage(0, cdata);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::reset_usage_hint
// Access: Private
// Description: Recomputes the minimum usage_hint.
////////////////////////////////////////////////////////////////////
void qpGeom::
reset_usage_hint(qpGeom::CDWriter &cdata) {
cdata->_usage_hint = qpGeomUsageHint::UH_static;
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
cdata->_usage_hint = min(cdata->_usage_hint, (*pi)->get_usage_hint());
}
cdata->_got_usage_hint = true;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::register_with_read_factory
// Access: Public, Static

View File

@ -29,6 +29,8 @@
#include "qpgeomVertexData.h"
#include "qpgeomPrimitive.h"
#include "qpgeomMunger.h"
#include "qpgeomUsageHint.h"
#include "updateSeq.h"
#include "pointerTo.h"
#include "geom.h"
@ -61,6 +63,8 @@ PUBLISHED:
// Temporary.
virtual Geom *make_copy() const;
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
INLINE CPT(qpGeomVertexData) get_vertex_data() const;
PT(qpGeomVertexData) modify_vertex_data();
void set_vertex_data(const qpGeomVertexData *data);
@ -74,6 +78,7 @@ PUBLISHED:
void clear_primitives();
int get_num_bytes() const;
UpdateSeq get_modified() const;
void munge_geom(const qpGeomMunger *munger,
CPT(qpGeom) &result, CPT(qpGeomVertexData) &data) const;
@ -87,6 +92,8 @@ public:
void draw(GraphicsStateGuardianBase *gsg,
const qpGeomVertexData *vertex_data) const;
static UpdateSeq get_next_modified();
protected:
virtual BoundingVolume *recompute_bound();
@ -120,6 +127,8 @@ private:
PT(qpGeomVertexData) _data;
Primitives _primitives;
qpGeomUsageHint::UsageHint _usage_hint;
bool _got_usage_hint;
MungedCache _munged_cache;
};
@ -127,6 +136,10 @@ private:
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
void reset_usage_hint(CDWriter &cdata);
static UpdateSeq _next_modified;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "qpgeomPrimitive.h"
#include "qpgeom.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexDataType.h"
@ -536,7 +537,7 @@ clear_cache() {
// This, on the other hand, should be applied to the current
// pipeline stage.
++(cdata->_modified);
cdata->_modified = qpGeom::get_next_modified();
}

View File

@ -50,26 +50,30 @@
class EXPCL_PANDA qpGeomUsageHint {
PUBLISHED:
enum UsageHint {
// The following are intentionally ordered from most dynamic to
// most static. In general, if usage_a < usage_b, then usage_a is
// more dynamic than usage_b.
// UH_client: don't attempt to upload the data; always keep it on
// the client.
UH_client,
// UH_stream: the data will be created once, used to render a few
// times, and then discarded. This should be used for short-lived
// temporary arrays.
// temporary objects.
UH_stream,
// UH_dynamic: the data will be repeatedly modified and
// re-rendered. This is for data that will be modified at
// runtime, such as animated or soft-skinned vertices.
UH_dynamic,
// UH_static: the data will be created once, and used to render
// many times, without modification. This is the most common
// case, since typically vertex data is not directly animated
// (this is not related to scene graph animation, e.g. from
// adjusting transforms on a node).
UH_static,
// UH_dynamic: the data will be repeatedly modified and
// re-rendered. This is for data that will be modified at
// runtime, such as animated or soft-skinned vertices.
UH_dynamic,
};
};

View File

@ -52,43 +52,6 @@ get_data() const {
return cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::modify_data
// Access: Published
// Description: Returns a modifiable pointer to the actual vertex
// array, so that application code may directly
// manipulate the vertices.
////////////////////////////////////////////////////////////////////
INLINE PTA_uchar qpGeomVertexArrayData::
modify_data() {
// Perform copy-on-write: if the reference count on the vertex data
// is greater than 1, assume some other GeomVertexData has the same
// pointer, so make a copy of it first.
CDWriter cdata(_cycler);
if (cdata->_data.get_ref_count() > 1) {
PTA_uchar orig_data = cdata->_data;
cdata->_data = PTA_uchar();
cdata->_data.v() = orig_data.v();
}
++(cdata->_modified);
return cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::set_data
// Access: Published
// Description: Replaces the vertex data array with a completely new
// array.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexArrayData::
set_data(CPTA_uchar array) {
CDWriter cdata(_cycler);
cdata->_data = (PTA_uchar &)array;
++(cdata->_modified);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::get_num_vertices
// Access: Published

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexArrayData.h"
#include "qpgeom.h"
#include "preparedGraphicsObjects.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -82,6 +83,43 @@ qpGeomVertexArrayData::
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::modify_data
// Access: Published
// Description: Returns a modifiable pointer to the actual vertex
// array, so that application code may directly
// manipulate the vertices.
////////////////////////////////////////////////////////////////////
PTA_uchar qpGeomVertexArrayData::
modify_data() {
// Perform copy-on-write: if the reference count on the vertex data
// is greater than 1, assume some other GeomVertexData has the same
// pointer, so make a copy of it first.
CDWriter cdata(_cycler);
if (cdata->_data.get_ref_count() > 1) {
PTA_uchar orig_data = cdata->_data;
cdata->_data = PTA_uchar();
cdata->_data.v() = orig_data.v();
}
cdata->_modified = qpGeom::get_next_modified();
return cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::set_data
// Access: Published
// Description: Replaces the vertex data array with a completely new
// array.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayData::
set_data(CPTA_uchar array) {
CDWriter cdata(_cycler);
cdata->_data = (PTA_uchar &)array;
cdata->_modified = qpGeom::get_next_modified();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayData::set_num_vertices
// Access: Published
@ -125,7 +163,7 @@ set_num_vertices(int n) {
}
}
++(cdata->_modified);
cdata->_modified = qpGeom::get_next_modified();
return true;
}

View File

@ -66,8 +66,8 @@ PUBLISHED:
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
INLINE CPTA_uchar get_data() const;
INLINE PTA_uchar modify_data();
INLINE void set_data(CPTA_uchar data);
PTA_uchar modify_data();
void set_data(CPTA_uchar data);
INLINE int get_num_vertices() const;
bool set_num_vertices(int n);

View File

@ -45,6 +45,7 @@ class GeomTri;
class GeomTristrip;
class GeomTrifan;
class GeomSphere;
class qpGeom;
class qpGeomVertexData;
class qpGeomVertexArrayData;
class qpGeomPrimitive;
@ -183,7 +184,7 @@ public:
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0;
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0;
virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data)=0;
virtual bool begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data)=0;
virtual void draw_triangles(const qpGeomTriangles *primitive)=0;
virtual void draw_tristrips(const qpGeomTristrips *primitive)=0;
virtual void draw_trifans(const qpGeomTrifans *primitive)=0;