move rotate and decompose operations into cull

This commit is contained in:
David Rose 2005-04-15 01:41:07 +00:00
parent 541bbe4403
commit 2434300804
44 changed files with 725 additions and 1837 deletions

View File

@ -122,7 +122,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_supports_generate_mipmap = false;
_supports_render_texture = false;
_supported_point_rendering = 0;
_supported_geom_rendering = 0;
}
////////////////////////////////////////////////////////////////////
@ -153,20 +153,20 @@ get_supports_multisample() const {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supported_point_rendering
// Function: GraphicsStateGuardian::get_supported_geom_rendering
// Access: Published, Virtual
// Description: Returns the union of Geom::PointRendering values that
// this particular GSG can support directly. If a point
// Description: Returns the union of Geom::GeomRendering values that
// this particular GSG can support directly. If a Geom
// needs to be rendered that requires some additional
// properties, the StandardMunger will convert it into
// quads instead.
// properties, the StandardMunger and/or the
// CullableObject will convert it as needed.
//
// This method is declared virtual solely so that it can
// be queried from cullableObject.cxx.
////////////////////////////////////////////////////////////////////
int GraphicsStateGuardian::
get_supported_point_rendering() const {
return _supported_point_rendering;
get_supported_geom_rendering() const {
return _supported_geom_rendering;
}
////////////////////////////////////////////////////////////////////
@ -723,10 +723,6 @@ draw_triangles(const qpGeomTriangles *) {
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
draw_tristrips(const qpGeomTristrips *primitive) {
CPT(qpGeomPrimitive) new_prim = primitive->decompose();
if (!new_prim->is_of_type(qpGeomTristrips::get_class_type())) {
new_prim->draw(this);
}
}
////////////////////////////////////////////////////////////////////
@ -736,10 +732,6 @@ draw_tristrips(const qpGeomTristrips *primitive) {
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
draw_trifans(const qpGeomTrifans *primitive) {
CPT(qpGeomPrimitive) new_prim = primitive->decompose();
if (!new_prim->is_of_type(qpGeomTrifans::get_class_type())) {
new_prim->draw(this);
}
}
////////////////////////////////////////////////////////////////////
@ -758,10 +750,6 @@ draw_lines(const qpGeomLines *) {
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
draw_linestrips(const qpGeomLinestrips *primitive) {
CPT(qpGeomPrimitive) new_prim = primitive->decompose();
if (!new_prim->is_of_type(qpGeomLinestrips::get_class_type())) {
new_prim->draw(this);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -96,7 +96,7 @@ PUBLISHED:
INLINE bool get_supports_generate_mipmap() const;
INLINE bool get_supports_render_texture() const;
virtual int get_supported_point_rendering() const;
virtual int get_supported_geom_rendering() const;
public:
INLINE bool set_scene(SceneSetup *scene_setup);
@ -326,7 +326,7 @@ protected:
bool _supports_multisample;
bool _supports_generate_mipmap;
bool _supports_render_texture;
int _supported_point_rendering;
int _supported_geom_rendering;
public:
// Statistics

View File

@ -133,6 +133,41 @@ munge_data_impl(const qpGeomVertexData *data) {
return new_data->convert_to(new_format);
}
////////////////////////////////////////////////////////////////////
// Function: StandardMunger::munge_geom_impl
// Access: Protected, Virtual
// Description: Converts a Geom and/or its data as necessary.
////////////////////////////////////////////////////////////////////
bool StandardMunger::
munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &vertex_data) {
int geom_rendering = geom->get_geom_rendering();
int supported_geom_rendering = _gsg->get_supported_geom_rendering();
int unsupported_bits = geom_rendering & ~supported_geom_rendering;
if (unsupported_bits != 0) {
// Even beyond munging the vertex format, we have to convert the
// Geom itself into a new primitive type the GSG can render
// directly.
if ((unsupported_bits & qpGeom::GR_composite_bits) != 0) {
// This decomposes everything in the primitive, so that if (for
// instance) the primitive contained both strips and fans, but
// the GSG didn't support fans, it would decompose the strips
// too. To handle this correctly, we'd need a separate
// decompose_fans() and decompose_strips() call; but for now,
// we'll just say it's good enough. In practice, we don't have
// any GSG's that can support strips without also supporting
// fans.
geom = geom->decompose();
}
if ((unsupported_bits & qpGeom::GR_shade_model_bits) != 0) {
geom = geom->rotate();
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: StandardMunger::compare_to_impl
// Access: Protected, Virtual

View File

@ -46,6 +46,7 @@ public:
protected:
virtual CPT(qpGeomVertexData) munge_data_impl(const qpGeomVertexData *data);
virtual int compare_to_impl(const qpGeomMunger *other) const;
virtual bool munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data);
virtual int geom_compare_to_impl(const qpGeomMunger *other) const;
private:

View File

@ -35,12 +35,6 @@ NotifyCategoryDef(wdxdisplay7, "windisplay");
ConfigVariableBool dx_full_screen
("dx-full-screen", false);
// Configure this true to force the rendering to sync to the video
// refresh, or false to let your frame rate go as high as it can,
// irrespective of the video refresh.
ConfigVariableBool dx_sync_video
("sync-video", true);
// enable this to turn on full-screen anti-aliasing, if the HW supports it
// this var is also used in wdxGraphicsWindows.cxx
ConfigVariableBool dx_full_screen_antialiasing

View File

@ -29,7 +29,6 @@ NotifyCategoryDecl(dxgsg7, EXPCL_PANDADX, EXPTP_PANDADX);
NotifyCategoryDecl(wdxdisplay7, EXPCL_PANDADX, EXPTP_PANDADX);
extern ConfigVariableBool dx_full_screen;
extern ConfigVariableBool dx_sync_video;
extern ConfigVariableBool dx_no_vertex_fog;
extern ConfigVariableBool dx_full_screen_antialiasing;
extern ConfigVariableBool dx_use_rangebased_fog;

View File

@ -4968,7 +4968,7 @@ void DXGraphicsStateGuardian7::show_full_screen_frame(void) {
// Normally, we can just do the fast flip operation.
DWORD dwFlipFlags = DDFLIP_WAIT;
if (!dx_sync_video) {
if (!sync_video) {
// If the user indicated via Config that we shouldn't wait for
// video sync, then don't wait (if the hardware supports this).
// This will introduce visible artifacts like tearing, and may
@ -5008,7 +5008,7 @@ void DXGraphicsStateGuardian7::show_windowed_frame(void) {
DX_DECLARE_CLEAN(DDBLTFX, bltfx);
if (dx_sync_video) {
if (sync_video) {
// Wait for the video refresh *before* we blt the rendered image
// onto the window. This will (a) prevent the "tearing" of the
// image that would occur if only part of the image happened to be
@ -5029,7 +5029,7 @@ void DXGraphicsStateGuardian7::show_windowed_frame(void) {
hr = _pScrn->pddsPrimary->Blt( &_pScrn->view_rect, _pScrn->pddsBack, NULL, DDBLT_DDFX | DDBLT_WAIT, &bltfx );
if (dx_sync_video) {
if (sync_video) {
HRESULT hr = _pScrn->pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
if(hr != DD_OK) {
dxgsg7_cat.error() << "WaitForVerticalBlank() failed : " << ConvD3DErrorToString(hr) << endl;

View File

@ -40,12 +40,6 @@ NotifyCategoryDef(wdxdisplay8, "windisplay");
ConfigVariableBool dx_show_transforms
("dx-show-transforms", false);
// Configure this true to force the rendering to sync to the video
// refresh, or false to let your frame rate go as high as it can,
// irrespective of the video refresh.
ConfigVariableBool dx_sync_video
("sync-video", true);
// Set Level of MultiSampling to be used, if HW supports it. Valid values are 2-16.
ConfigVariableInt dx_multisample_antialiasing_level
("dx-multisample-antialiasing-level", 0);

View File

@ -29,7 +29,6 @@
NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
NotifyCategoryDecl(wdxdisplay8, EXPCL_PANDADX, EXPTP_PANDADX);
extern ConfigVariableBool dx_sync_video;
extern ConfigVariableBool dx_no_vertex_fog;
extern ConfigVariableBool dx_show_cursor_watermark;
extern ConfigVariableBool dx_full_screen_antialiasing;

View File

@ -190,7 +190,6 @@ DXGraphicsStateGuardian8::
DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
GraphicsStateGuardian(properties, CS_yup_left)
{
reset_panda_gsg();
_pScrn = NULL;
@ -222,6 +221,10 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
// DirectX drivers seem to consistently invert the texture when
// they copy framebuffer-to-texture. Ok.
_copy_texture_inverted = true;
_supported_geom_rendering =
qpGeom::GR_triangle_strip | qpGeom::GR_triangle_fan |
qpGeom::GR_flat_first_vertex;
}
////////////////////////////////////////////////////////////////////
@ -2749,7 +2752,7 @@ draw_triangles(const qpGeomTriangles *primitive) {
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_flat_first_vertices(),
primitive->get_vertices(),
D3DFMT_INDEX16,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
@ -2765,8 +2768,6 @@ void DXGraphicsStateGuardian8::
draw_tristrips(const qpGeomTristrips *primitive) {
int min_vertex = primitive->get_min_vertex();
int max_vertex = primitive->get_max_vertex();
// CPTA_ushort vertices = primitive->get_flat_first_vertices();
CPTA_ushort vertices = primitive->get_vertices();
if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
// One long triangle strip, connected by the degenerate vertices
@ -2779,17 +2780,15 @@ draw_tristrips(const qpGeomTristrips *primitive) {
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLESTRIP,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
min_vertex, max_vertex - min_vertex + 1,
0, primitive->get_num_vertices() - 2);
} else {
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLESTRIP,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
min_vertex, max_vertex - min_vertex + 1,
primitive->get_num_vertices() - 2,
vertices, D3DFMT_INDEX16,
primitive->get_vertices(), D3DFMT_INDEX16,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());
}
@ -2821,6 +2820,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
} else {
CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
int stride = _vertex_data->get_format()->get_array(0)->get_stride();
CPTA_ushort vertices = primitive->get_vertices();
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
@ -2838,6 +2838,59 @@ draw_tristrips(const qpGeomTristrips *primitive) {
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::draw_trifans
// Access: Public, Virtual
// Description: Draws a series of triangle fans.
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
draw_trifans(const qpGeomTrifans *primitive) {
int min_vertex = primitive->get_min_vertex();
int max_vertex = primitive->get_max_vertex();
// Send the individual triangle fans. There's no connecting fans
// with degenerate vertices, so no worries about that.
CPTA_int ends = primitive->get_ends();
CPTA_ushort mins = primitive->get_mins();
CPTA_ushort maxs = primitive->get_maxs();
nassertv(mins.size() == ends.size() && maxs.size() == ends.size());
if (_vbuffer_active) {
IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
nassertv(ibc != (IndexBufferContext *)NULL);
apply_index_buffer(ibc);
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_trifan_pcollector.add_level(ends[i] - start);
_pD3DDevice->DrawIndexedPrimitive
(D3DPT_TRIANGLEFAN,
mins[i], maxs[i] - mins[i] + 1,
start, ends[i] - start - 2);
start = ends[i] + 2;
}
} else {
CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
int stride = _vertex_data->get_format()->get_array(0)->get_stride();
CPTA_ushort vertices = primitive->get_vertices();
unsigned int start = 0;
for (size_t i = 0; i < ends.size(); i++) {
_vertices_trifan_pcollector.add_level(ends[i] - start);
_pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLEFAN,
mins[i], maxs[i] - mins[i] + 1,
ends[i] - start - 2,
vertices + start, D3DFMT_INDEX16,
array_data, stride);
start = ends[i] + 2;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::draw_lines
// Access: Public, Virtual
@ -2863,7 +2916,7 @@ draw_lines(const qpGeomLines *primitive) {
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_flat_first_vertices(),
primitive->get_vertices(),
D3DFMT_INDEX16,
_vertex_data->get_array(0)->get_data(),
_vertex_data->get_format()->get_array(0)->get_stride());

View File

@ -95,6 +95,7 @@ public:
const qpGeomVertexData *vertex_data);
virtual void draw_triangles(const qpGeomTriangles *primitive);
virtual void draw_tristrips(const qpGeomTristrips *primitive);
virtual void draw_trifans(const qpGeomTrifans *primitive);
virtual void draw_lines(const qpGeomLines *primitive);
virtual void end_draw_primitives();

View File

@ -104,7 +104,7 @@ upload_data() {
return;
}
memcpy(local_pointer, get_data()->get_flat_first_vertices(), data_size);
memcpy(local_pointer, get_data()->get_vertices(), data_size);
_ibuffer->Unlock();
}

View File

@ -683,9 +683,12 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
pPresParams->BackBufferFormat = Display.DisplayMode.Format; // dont need dest alpha, so just use adapter format
if (dx_sync_video && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
wdxdisplay8_cat.info() << "HW doesnt support syncing to vertical refresh, ignoring dx_sync_video\n";
dx_sync_video=false;
bool do_sync = sync_video;
if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
wdxdisplay8_cat.info()
<< "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
do_sync = false;
}
// verify the rendertarget fmt one last time
@ -779,7 +782,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
if (is_fullscreen()) {
pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD; // we dont care about preserving contents of old frame
pPresParams->FullScreen_PresentationInterval = (dx_sync_video ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
pPresParams->FullScreen_PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
pPresParams->FullScreen_RefreshRateInHz = Display.DisplayMode.RefreshRate;
#ifdef _DEBUG
@ -831,7 +834,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
pPresParams->FullScreen_PresentationInterval = 0;
if (dx_multisample_antialiasing_level<2) {
if (dx_sync_video) {
if (do_sync) {
pPresParams->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
} else {
pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD; //D3DSWAPEFFECT_COPY; does this make any difference?

View File

@ -37,12 +37,6 @@ NotifyCategoryDef(wdxdisplay9, "windisplay");
ConfigVariableBool dx_show_transforms
("dx-show-transforms", false);
// Configure this true to force the rendering to sync to the video
// refresh, or false to let your frame rate go as high as it can,
// irrespective of the video refresh.
ConfigVariableBool dx_sync_video
("sync-video", true);
// Set Level of MultiSampling to be used, if HW supports it. Valid values are 2-16.
ConfigVariableInt dx_multisample_antialiasing_level
("dx-multisample-antialiasing-level", 0);

View File

@ -29,7 +29,6 @@
NotifyCategoryDecl(dxgsg9, EXPCL_PANDADX, EXPTP_PANDADX);
NotifyCategoryDecl(wdxdisplay9, EXPCL_PANDADX, EXPTP_PANDADX);
extern ConfigVariableBool dx_sync_video;
extern ConfigVariableBool dx_no_vertex_fog;
extern ConfigVariableBool dx_show_cursor_watermark;
extern ConfigVariableBool dx_full_screen_antialiasing;

View File

@ -670,9 +670,12 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
pPresParams->BackBufferFormat = Display.DisplayMode.Format; // dont need dest alpha, so just use adapter format
if (dx_sync_video && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
wdxdisplay9_cat.info() << "HW doesnt support syncing to vertical refresh, ignoring dx_sync_video\n";
dx_sync_video=false;
bool do_sync = sync_video;
if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
wdxdisplay9_cat.info()
<< "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
do_sync = false;
}
// verify the rendertarget fmt one last time
@ -766,7 +769,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
if (is_fullscreen()) {
pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD; // we dont care about preserving contents of old frame
pPresParams->PresentationInterval = (dx_sync_video ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
pPresParams->PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
pPresParams->FullScreen_RefreshRateInHz = Display.DisplayMode.RefreshRate;
#ifdef _DEBUG
@ -818,7 +821,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
pPresParams->PresentationInterval = 0;
if (dx_multisample_antialiasing_level<2) {
if (dx_sync_video) {
if (do_sync) {
pPresParams->SwapEffect = D3DSWAPEFFECT_COPY;
} else {
pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD; //D3DSWAPEFFECT_COPY; does this make any difference?

File diff suppressed because it is too large Load Diff

View File

@ -100,6 +100,7 @@ public:
virtual void draw_triangles(const qpGeomTriangles *primitive);
virtual void draw_tristrips(const qpGeomTristrips *primitive);
virtual void draw_lines(const qpGeomLines *primitive);
virtual void draw_linestrips(const qpGeomLinestrips *primitive);
virtual void draw_points(const qpGeomPoints *primitive);
virtual void end_draw_primitives();
@ -390,16 +391,24 @@ public:
typedef pvector<GLuint> DeletedDisplayLists;
DeletedDisplayLists _deleted_display_lists;
public:
static GraphicsStateGuardian *
make_GlGraphicsStateGuardian(const FactoryParams &params);
static PStatCollector _vertices_display_list_pcollector;
static TypeHandle get_class_type(void);
static void init_type(void);
virtual TypeHandle get_type(void) const;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static PStatCollector _vertices_display_list_pcollector;
static TypeHandle get_class_type() {
return _type_handle;
}
public:
static void init_type() {
GraphicsStateGuardian::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "GraphicsStateGuardian",
GraphicsStateGuardian::get_class_type());
}
private:
static TypeHandle _type_handle;

View File

@ -31,6 +31,32 @@ get_primitive_type() const {
return cdata->_primitive_type;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_shade_model
// Access: Published
// Description: Returns the shade model common to all of the
// individual GeomPrimitives that have been added to the
// geom.
////////////////////////////////////////////////////////////////////
INLINE qpGeom::ShadeModel qpGeom::
get_shade_model() const {
CDReader cdata(_cycler);
return cdata->_shade_model;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_geom_rendering
// Access: Published
// Description: Returns the set of GeomRendering bits that represent
// the rendering properties required to properly render
// this Geom.
////////////////////////////////////////////////////////////////////
INLINE int qpGeom::
get_geom_rendering() const {
CDReader cdata(_cycler);
return cdata->_geom_rendering;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_usage_hint
// Access: Published
@ -48,19 +74,6 @@ get_usage_hint() const {
return cdata->_usage_hint;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_point_rendering
// Access: Published
// Description: Returns the set of PointRendering bits that represent
// the rendering properties required to properly render
// the points (if any) represented within this Geom.
////////////////////////////////////////////////////////////////////
INLINE int qpGeom::
get_point_rendering() const {
CDReader cdata(_cycler);
return cdata->_point_rendering;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_vertex_data
// Access: Published
@ -123,6 +136,34 @@ modify_primitive(int i) {
return cdata->_primitives[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::decompose
// Access: Published
// Description: Decomposes all of the primitives within this Geom,
// returning the result. See
// GeomPrimitive::decompose().
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeom) qpGeom::
decompose() const {
PT(qpGeom) new_geom = new qpGeom(*this);
new_geom->decompose_in_place();
return new_geom;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::rotate
// Access: Published
// Description: Rotates all of the primitives within this Geom,
// returning the result. See
// GeomPrimitive::rotate().
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeom) qpGeom::
rotate() const {
PT(qpGeom) new_geom = new qpGeom(*this);
new_geom->rotate_in_place();
return new_geom;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_modified
// Access: Published
@ -179,7 +220,8 @@ operator < (const CacheEntry &other) const {
INLINE qpGeom::CData::
CData() :
_primitive_type(PT_none),
_point_rendering(0),
_shade_model(SM_uniform),
_geom_rendering(0),
_usage_hint(UH_unspecified),
_got_usage_hint(false)
{
@ -195,7 +237,8 @@ CData(const qpGeom::CData &copy) :
_data(copy._data),
_primitives(copy._primitives),
_primitive_type(copy._primitive_type),
_point_rendering(copy._point_rendering),
_shade_model(copy._shade_model),
_geom_rendering(copy._geom_rendering),
_usage_hint(copy._usage_hint),
_got_usage_hint(copy._got_usage_hint),
_modified(copy._modified)

View File

@ -162,7 +162,7 @@ set_vertex_data(const qpGeomVertexData *data) {
CDWriter cdata(_cycler);
cdata->_data = (qpGeomVertexData *)data;
mark_bound_stale();
reset_point_rendering(cdata);
reset_geom_rendering(cdata);
}
////////////////////////////////////////////////////////////////////
@ -199,10 +199,9 @@ offset_vertices(const qpGeomVertexData *data, int offset) {
#endif
}
cdata->_got_usage_hint = false;
cdata->_modified = qpGeom::get_next_modified();
mark_bound_stale();
reset_point_rendering(cdata);
reset_geom_rendering(cdata);
nassertv(all_is_valid);
}
@ -225,25 +224,25 @@ set_primitive(int i, const qpGeomPrimitive *primitive) {
nassertv(cdata->_primitive_type == PT_none ||
cdata->_primitive_type == primitive->get_primitive_type());
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;
}
}
}
// They also should have the same fundamental shade model, but
// SM_uniform is compatible with anything.
nassertv(cdata->_shade_model == SM_uniform ||
primitive->get_shade_model() == SM_uniform ||
cdata->_shade_model == primitive->get_shade_model());
cdata->_primitives[i] = (qpGeomPrimitive *)primitive;
PrimitiveType new_primitive_type = primitive->get_primitive_type();
if (new_primitive_type != cdata->_primitive_type) {
cdata->_primitive_type = new_primitive_type;
reset_point_rendering(cdata);
}
ShadeModel new_shade_model = primitive->get_shade_model();
if (new_shade_model != cdata->_shade_model &&
new_shade_model != SM_uniform) {
cdata->_shade_model = new_shade_model;
}
reset_geom_rendering(cdata);
cdata->_got_usage_hint = false;
cdata->_modified = qpGeom::get_next_modified();
}
@ -267,16 +266,25 @@ add_primitive(const qpGeomPrimitive *primitive) {
nassertv(cdata->_primitive_type == PT_none ||
cdata->_primitive_type == primitive->get_primitive_type());
// They also should have the same fundamental shade model, but
// SM_uniform is compatible with anything.
nassertv(cdata->_shade_model == SM_uniform ||
primitive->get_shade_model() == SM_uniform ||
cdata->_shade_model == primitive->get_shade_model());
cdata->_primitives.push_back((qpGeomPrimitive *)primitive);
PrimitiveType new_primitive_type = primitive->get_primitive_type();
if (new_primitive_type != cdata->_primitive_type) {
cdata->_primitive_type = new_primitive_type;
reset_point_rendering(cdata);
}
ShadeModel new_shade_model = primitive->get_shade_model();
if (new_shade_model != cdata->_shade_model &&
new_shade_model != SM_uniform) {
cdata->_shade_model = new_shade_model;
}
if (cdata->_got_usage_hint) {
cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
}
reset_geom_rendering(cdata);
cdata->_got_usage_hint = false;
cdata->_modified = qpGeom::get_next_modified();
}
@ -290,17 +298,13 @@ 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);
if (cdata->_primitives.empty()) {
cdata->_primitive_type = PT_none;
reset_point_rendering(cdata);
cdata->_shade_model = SM_uniform;
}
reset_geom_rendering(cdata);
cdata->_got_usage_hint = false;
cdata->_modified = qpGeom::get_next_modified();
}
@ -318,7 +322,73 @@ clear_primitives() {
CDWriter cdata(_cycler);
cdata->_primitives.clear();
cdata->_primitive_type = PT_none;
reset_point_rendering(cdata);
cdata->_shade_model = SM_uniform;
reset_geom_rendering(cdata);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::decompose_in_place
// Access: Published
// Description: Decomposes all of the primitives within this Geom,
// leaving the results in place. See
// GeomPrimitive::decompose().
////////////////////////////////////////////////////////////////////
void qpGeom::
decompose_in_place() {
clear_cache();
CDWriter cdata(_cycler);
#ifndef NDEBUG
bool all_is_valid = true;
#endif
Primitives::iterator pi;
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
CPT(qpGeomPrimitive) new_prim = (*pi)->decompose();
(*pi) = (qpGeomPrimitive *)new_prim.p();
#ifndef NDEBUG
if (!(*pi)->check_valid(cdata->_data)) {
all_is_valid = false;
}
#endif
}
cdata->_modified = qpGeom::get_next_modified();
reset_geom_rendering(cdata);
nassertv(all_is_valid);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::rotate_in_place
// Access: Published
// Description: Rotates all of the primitives within this Geom,
// leaving the results in place. See
// GeomPrimitive::rotate().
////////////////////////////////////////////////////////////////////
void qpGeom::
rotate_in_place() {
clear_cache();
CDWriter cdata(_cycler);
#ifndef NDEBUG
bool all_is_valid = true;
#endif
Primitives::iterator pi;
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
CPT(qpGeomPrimitive) new_prim = (*pi)->rotate();
(*pi) = (qpGeomPrimitive *)new_prim.p();
#ifndef NDEBUG
if (!(*pi)->check_valid(cdata->_data)) {
all_is_valid = false;
}
#endif
}
cdata->_modified = qpGeom::get_next_modified();
nassertv(all_is_valid);
}
////////////////////////////////////////////////////////////////////
@ -712,26 +782,44 @@ reset_usage_hint(qpGeom::CDWriter &cdata) {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::reset_point_rendering
// Function: qpGeom::reset_geom_rendering
// Access: Private
// Description: Rederives the _point_rendering member.
// Description: Rederives the _geom_rendering member.
////////////////////////////////////////////////////////////////////
void qpGeom::
reset_point_rendering(qpGeom::CDWriter &cdata) {
cdata->_point_rendering = 0;
if (cdata->_primitive_type == PT_points) {
cdata->_point_rendering |= PR_point;
reset_geom_rendering(qpGeom::CDWriter &cdata) {
cdata->_geom_rendering = 0;
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
cdata->_geom_rendering |= (*pi)->get_geom_rendering();
}
if ((cdata->_geom_rendering & GR_point) != 0) {
if (cdata->_data->has_column(InternalName::get_size())) {
cdata->_point_rendering |= PR_per_point_size;
cdata->_geom_rendering |= GR_per_point_size;
}
if (cdata->_data->has_column(InternalName::get_aspect_ratio())) {
cdata->_point_rendering |= PR_aspect_ratio;
cdata->_geom_rendering |= GR_point_aspect_ratio;
}
if (cdata->_data->has_column(InternalName::get_rotate())) {
cdata->_point_rendering |= PR_rotate;
cdata->_geom_rendering |= GR_point_rotate;
}
}
switch (get_shade_model()) {
case SM_flat_first_vertex:
cdata->_geom_rendering |= GR_flat_first_vertex;
break;
case SM_flat_last_vertex:
cdata->_geom_rendering |= GR_flat_last_vertex;
break;
default:
break;
}
}
////////////////////////////////////////////////////////////////////
@ -862,7 +950,8 @@ write_datagram(BamWriter *manager, Datagram &dg) const {
}
dg.add_uint8(_primitive_type);
dg.add_uint16(_point_rendering);
dg.add_uint8(_shade_model);
dg.add_uint16(_geom_rendering);
}
////////////////////////////////////////////////////////////////////
@ -905,7 +994,8 @@ fillin(DatagramIterator &scan, BamReader *manager) {
}
_primitive_type = (PrimitiveType)scan.get_uint8();
_point_rendering = scan.get_uint16();
_shade_model = (ShadeModel)scan.get_uint16();
_geom_rendering = scan.get_uint16();
_got_usage_hint = false;
_modified = qpGeom::get_next_modified();
}

View File

@ -68,11 +68,12 @@ PUBLISHED:
virtual Geom *make_copy() const;
INLINE PrimitiveType get_primitive_type() const;
INLINE ShadeModel get_shade_model() const;
INLINE int get_geom_rendering() const;
INLINE UsageHint get_usage_hint() const;
void set_usage_hint(UsageHint usage_hint);
INLINE int get_point_rendering() const;
INLINE CPT(qpGeomVertexData) get_vertex_data() const;
PT(qpGeomVertexData) modify_vertex_data();
void set_vertex_data(const qpGeomVertexData *data);
@ -86,6 +87,12 @@ PUBLISHED:
void remove_primitive(int i);
void clear_primitives();
INLINE CPT(qpGeom) decompose() const;
INLINE CPT(qpGeom) rotate() const;
void decompose_in_place();
void rotate_in_place();
int get_num_bytes() const;
INLINE UpdateSeq get_modified() const;
@ -160,7 +167,8 @@ private:
PT(qpGeomVertexData) _data;
Primitives _primitives;
PrimitiveType _primitive_type;
int _point_rendering;
ShadeModel _shade_model;
int _geom_rendering;
UsageHint _usage_hint;
bool _got_usage_hint;
UpdateSeq _modified;
@ -172,7 +180,7 @@ private:
typedef CycleDataWriter<CData> CDWriter;
void reset_usage_hint(CDWriter &cdata);
void reset_point_rendering(CDWriter &cdata);
void reset_geom_rendering(CDWriter &cdata);
static UpdateSeq _next_modified;

View File

@ -82,48 +82,68 @@ PUBLISHED:
UH_unspecified,
};
// This type specifies a number of bits that are used to
// representing the rendering capabilities and/or requirements for
// fancy points.
enum PointRendering {
// This type specifies a number of bits that are used to represent
// the rendering requirements of a particular Geom, as well as the
// rendering capabilities of the GSG. The difference between the
// two indicates whether the Geom needs to be munged for the GSG.
enum GeomRendering {
// If there are any points at all.
PR_point = 0x0001,
GR_point = 0x0001,
// If the points are all the same size, other than 1 pixel.
PR_uniform_size = 0x0002,
GR_point_uniform_size = 0x0002,
// If the points have a per-vertex size designation.
PR_per_point_size = 0x0004,
GR_per_point_size = 0x0004,
// If the points' size is specified in camera units rather than
// screen pixels.
PR_perspective = 0x0008,
GR_point_perspective = 0x0008,
// If the points have a non-square aspect ratio.
PR_aspect_ratio = 0x0010,
GR_point_aspect_ratio = 0x0010,
// If the points are rotated off the orthonormal axis.
PR_rotate = 0x0020,
GR_point_rotate = 0x0020,
// If the points require texture coordinates interpolated across
// their face, to render textures as sprites.
PR_sprite = 0x0040,
GR_point_sprite = 0x0040,
// The union of all the above point attributes.
GR_point_bits = 0x007f,
// If there are any of these composite types.
GR_triangle_strip = 0x0080,
GR_triangle_fan = 0x0100,
GR_line_strip = 0x0200,
// The union of all of the above composite types.
GR_composite_bits = 0x0380,
// If the shade model requires a particular vertex for flat shading.
GR_flat_first_vertex = 0x0400,
GR_flat_last_vertex = 0x0800,
// The union of the above shade model types.
GR_shade_model_bits = 0x0c00,
};
// The shade model controls whether colors and/or lighting effects
// are smoothly interpolated across the face of a triangle, or
// uniform for the entire triangle.
// The shade model specifies whether the per-vertex colors and
// normals indexed by a given primitive truly represent per-vertex
// colors and normals, or whether they actually represent
// per-triangle flat-shaded colors and normals.
enum ShadeModel {
// SM_smooth: vertices within a single face have different
// colors/normals that should be smoothed across the face. This
// primitive should be rendered with SmoothModelAttrib::M_smooth.
SM_smooth,
// SM_uniform: all vertices across all faces have the same colors
// and normals. It doesn't really matter which ShadeModelAttrib
// mode is used to render this primitive.
SM_uniform,
// SM_smooth: vertices within a single face have different
// colors/normals that should be smoothed across the face. This
// primitive should be rendered with SmoothModelAttrib::M_smooth.
SM_smooth,
// SM_flat_(first,last)_vertex: each face within the primitive
// might have a different color/normal than the other faces, but
// across a particular face there is only one color/normal. Each

View File

@ -134,7 +134,7 @@ rotate_impl() const {
new_vertices.push_back(vertices[begin]);
}
nassertr(new_vertices.size() == vertices.size(), vertices);
nassertr(new_vertices.size() == vertices.size(), CPTA_ushort());
return new_vertices;
}

View File

@ -79,6 +79,18 @@ get_primitive_type() const {
return PT_lines;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomLinestrips::get_geom_rendering
// Access: Published, Virtual
// Description: Returns the set of GeomRendering bits that represent
// the rendering properties required to properly render
// this primitive.
////////////////////////////////////////////////////////////////////
int qpGeomLinestrips::
get_geom_rendering() const {
return GR_line_strip;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomLinestrips::get_min_num_vertices_per_primitive
// Access: Public, Virtual
@ -167,7 +179,7 @@ rotate_impl() const {
}
begin = end;
}
nassertr(new_vertices.size() == vertices.size(), vertices);
nassertr(new_vertices.size() == vertices.size(), CPTA_ushort());
return new_vertices;
}

View File

@ -37,7 +37,7 @@ PUBLISHED:
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;
virtual int get_geom_rendering() const;
virtual int get_min_num_vertices_per_primitive() const;
public:

View File

@ -78,6 +78,21 @@ get_primitive_type() const {
return PT_points;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPoints::get_geom_rendering
// Access: Published, Virtual
// Description: Returns the set of GeomRendering bits that represent
// the rendering properties required to properly render
// this primitive.
////////////////////////////////////////////////////////////////////
int qpGeomPoints::
get_geom_rendering() const {
// Fancy point attributes, if any, are based on whether the
// appropriate columns are defined in the associated GeomVertexData;
// these bits will be added by Geom::get_geom_rendering().
return GR_point;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPoints::get_num_vertices_per_primitive
// Access: Public, Virtual

View File

@ -37,6 +37,7 @@ PUBLISHED:
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;
virtual int get_geom_rendering() const;
virtual int get_num_vertices_per_primitive() const;
virtual int get_min_num_vertices_per_primitive() const;

View File

@ -17,6 +17,36 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_shade_model
// Access: Published
// Description: Returns the ShadeModel hint for this primitive.
// This is intended as a hint to the renderer to tell it
// how the per-vertex colors and normals are applied.
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::ShadeModel qpGeomPrimitive::
get_shade_model() const {
CDReader cdata(_cycler);
return cdata->_shade_model;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_shade_model
// Access: Published
// Description: Changes the ShadeModel hint for this primitive.
// This is different from the ShadeModelAttrib that
// might also be applied from the scene graph. This
// does not affect the shade model that is in effect
// when rendering, but rather serves as a hint to the
// renderer to tell it how the per-vertex colors and
// normals on this primitive are applied.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomPrimitive::
set_shade_model(qpGeomPrimitive::ShadeModel shade_model) {
CDWriter cdata(_cycler);
cdata->_shade_model = shade_model;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_usage_hint
// Access: Published
@ -47,42 +77,10 @@ get_usage_hint() const {
////////////////////////////////////////////////////////////////////
INLINE void qpGeomPrimitive::
set_usage_hint(qpGeomPrimitive::UsageHint usage_hint) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_usage_hint = usage_hint;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_shade_model
// Access: Published
// Description: Returns the ShadeModel hint for this primitive.
// This is intended as a hint to the renderer to tell it
// how the per-vertex colors and normals are applied.
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::ShadeModel qpGeomPrimitive::
get_shade_model() const {
CDReader cdata(_cycler);
return cdata->_shade_model;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_shade_model
// Access: Published
// Description: Changes the ShadeModel hint for this primitive.
// This is different from the ShadeModelAttrib that
// might also be applied from the scene graph. This
// does not affect the shade model that is in effect
// when rendering, but rather serves as a hint to the
// renderer to tell it how the per-vertex colors and
// normals on this primitive are applied.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomPrimitive::
set_shade_model(qpGeomPrimitive::ShadeModel shade_model) {
CDWriter cdata(_cycler);
cdata->_shade_model = shade_model;
cdata->_rotated_vertices.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_vertices
// Access: Published
@ -246,64 +244,6 @@ get_vertices() const {
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_flat_first_vertices
// Access: Public
// Description: Returns a const pointer to the vertex index array,
// suitable for traversing for a renderer that expects
// the key vertex of each triangle in a flat-shaded
// model to be the triangle's first vertex (as DirectX
// does).
//
// The result of this is dependent on the value
// specified to set_shade_model(). If the shade model
// indicates flat_last_vertex, this will return the
// vertices rotated to bring them into first_vertex
// compliance; otherwise, it will be the unmodified
// result from get_vertices().
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_flat_first_vertices() const {
CDReader cdata(_cycler);
if (cdata->_shade_model == SM_flat_last_vertex) {
if (cdata->_rotated_vertices == (const ushort *)NULL) {
return ((qpGeomPrimitive *)this)->do_rotate(cdata);
}
return cdata->_rotated_vertices;
} else {
return cdata->_vertices;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_flat_last_vertices
// Access: Public
// Description: Returns a const pointer to the vertex index array,
// suitable for traversing for a renderer that expects
// the key vertex of each triangle in a flat-shaded
// model to be the triangle's last vertex (as OpenGL
// does).
//
// The result of this is dependent on the value
// specified to set_shade_model(). If the shade model
// indicates flat_first_vertex, this will return the
// vertices rotated to bring them into last_vertex
// compliance; otherwise, it will be the unmodified
// result from get_vertices().
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_flat_last_vertices() const {
CDReader cdata(_cycler);
if (cdata->_shade_model == SM_flat_first_vertex) {
if (cdata->_rotated_vertices == (const ushort *)NULL) {
return ((qpGeomPrimitive *)this)->do_rotate(cdata);
}
return cdata->_rotated_vertices;
} else {
return cdata->_vertices;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_ends
// Access: Public
@ -391,7 +331,6 @@ CData(const qpGeomPrimitive::CData &copy) :
_usage_hint(copy._usage_hint),
_shade_model(copy._shade_model),
_vertices(copy._vertices),
_rotated_vertices(copy._rotated_vertices),
_ends(copy._ends),
_mins(copy._mins),
_maxs(copy._maxs),

View File

@ -30,7 +30,8 @@
TypeHandle qpGeomPrimitive::_type_handle;
PStatCollector qpGeomPrimitive::_rotate_pcollector("Draw:Rotate");
PStatCollector qpGeomPrimitive::_decompose_pcollector("Cull:Munge:Decompose");
PStatCollector qpGeomPrimitive::_rotate_pcollector("Cull:Munge:Rotate");
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::Constructor
@ -61,22 +62,20 @@ qpGeomPrimitive(const qpGeomPrimitive &copy) :
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
~qpGeomPrimitive() {
// When we destruct, we should ensure that all of our cached
// entries, across all pipeline stages, are properly removed from
// the cache manager.
int num_stages = _cycler.get_num_stages();
for (int i = 0; i < num_stages; i++) {
if (_cycler.is_stage_unique(i)) {
CData *cdata = _cycler.write_stage(i);
if (cdata->_cache != (CacheEntry *)NULL) {
cdata->_cache->erase();
cdata->_cache = NULL;
}
_cycler.release_write_stage(i, cdata);
}
release_all();
}
release_all();
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_geom_rendering
// Access: Published, Virtual
// Description: Returns the set of GeomRendering bits that represent
// the rendering properties required to properly render
// this primitive.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_geom_rendering() const {
// The default is nothing fancy.
return 0;
}
////////////////////////////////////////////////////////////////////
@ -94,7 +93,6 @@ add_vertex(int vertex) {
unsigned short short_vertex = vertex;
nassertv((int)short_vertex == vertex);
clear_cache();
CDWriter cdata(_cycler);
int num_primitives = get_num_primitives();
@ -106,7 +104,6 @@ add_vertex(int vertex) {
}
cdata->_vertices.push_back(short_vertex);
cdata->_rotated_vertices.clear();
if (cdata->_got_minmax) {
cdata->_min_vertex = min(cdata->_min_vertex, short_vertex);
@ -139,7 +136,6 @@ 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;
unsigned short short_end = end;
@ -158,7 +154,6 @@ add_consecutive_vertices(int start, int num_vertices) {
for (unsigned short v = short_start; v <= short_end; ++v) {
cdata->_vertices.push_back(v);
}
cdata->_rotated_vertices.clear();
if (cdata->_got_minmax) {
cdata->_min_vertex = min(cdata->_min_vertex, short_start);
@ -210,7 +205,6 @@ add_next_vertices(int num_vertices) {
////////////////////////////////////////////////////////////////////
bool qpGeomPrimitive::
close_primitive() {
clear_cache();
int num_vertices_per_primitive = get_num_vertices_per_primitive();
CDWriter cdata(_cycler);
@ -262,10 +256,8 @@ close_primitive() {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
clear_vertices() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_vertices.clear();
cdata->_rotated_vertices.clear();
cdata->_ends.clear();
cdata->_mins.clear();
cdata->_maxs.clear();
@ -280,10 +272,8 @@ clear_vertices() {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
offset_vertices(int offset) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_mins.clear();
cdata->_maxs.clear();
cdata->_got_minmax = false;
@ -427,49 +417,44 @@ get_primitive_num_vertices(int n) const {
////////////////////////////////////////////////////////////////////
CPT(qpGeomPrimitive) qpGeomPrimitive::
decompose() const {
CPT(qpGeomPrimitive) result;
{
// Use read() and release_read() instead of CDReader, because the
// call to record_primitive() might recursively call back into
// this object, and require a write.
const CData *cdata = _cycler.read();
if (cdata->_cache != (CacheEntry *)NULL) {
result = cdata->_cache->_decomposed;
_cycler.release_read(cdata);
// Record a cache hit, so this element will stay in the cache a
// while longer.
cdata->_cache->refresh();
return result;
}
_cycler.release_read(cdata);
}
result = decompose_impl();
if (result.p() == this || result.p() == NULL) {
// decomposing this primitive has no effect or cannot be done.
return this;
}
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Decomposing " << get_type() << ": " << (void *)this << "\n";
}
// Record the result for the future.
CacheEntry *entry;
{
CDWriter cdata(((qpGeomPrimitive *)this)->_cycler);
entry = new CacheEntry;
entry->_source = (qpGeomPrimitive *)this;
entry->_decomposed = result;
cdata->_cache = entry;
PStatTimer timer(_decompose_pcollector);
return decompose_impl();
}
// And add *this* object to the cache manager.
entry->record();
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::rotate
// Access: Published
// Description: Returns a new primitive with the shade_model reversed
// (if it is flat shaded).
//
// If the current shade_model indicates
// flat_vertex_last, this should bring the last vertex
// to the first position; if it indicates
// flat_vertex_first, this should bring the first vertex
// to the last position.
////////////////////////////////////////////////////////////////////
CPT(qpGeomPrimitive) qpGeomPrimitive::
rotate() const {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Rotating " << get_type() << ": " << (void *)this << "\n";
}
return result;
PStatTimer timer(_rotate_pcollector);
CPTA_ushort rotated_vertices = rotate_impl();
if (rotated_vertices.is_null()) {
return this;
}
PT(qpGeomPrimitive) new_prim = make_copy();
new_prim->set_vertices(rotated_vertices);
return new_prim;
}
////////////////////////////////////////////////////////////////////
@ -554,9 +539,7 @@ write(ostream &out, int indent_level) const {
////////////////////////////////////////////////////////////////////
PTA_ushort qpGeomPrimitive::
modify_vertices() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
return cdata->_vertices;
}
@ -570,10 +553,8 @@ modify_vertices() {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_vertices(CPTA_ushort vertices) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_vertices = (PTA_ushort &)vertices;
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
}
@ -591,9 +572,7 @@ set_vertices(CPTA_ushort vertices) {
////////////////////////////////////////////////////////////////////
PTA_int qpGeomPrimitive::
modify_ends() {
clear_cache();
CDWriter cdata(_cycler);
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
return cdata->_ends;
}
@ -612,10 +591,8 @@ modify_ends() {
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_ends(CPTA_int ends) {
clear_cache();
CDWriter cdata(_cycler);
cdata->_ends = (PTA_int &)ends;
cdata->_rotated_vertices.clear();
cdata->_got_minmax = false;
}
@ -660,28 +637,6 @@ get_num_unused_vertices_per_primitive() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::clear_cache
// Access: Public
// Description: Removes all of the previously-cached results of
// decompose().
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
clear_cache() {
// Probably we shouldn't do anything at all here unless we are
// running in pipeline stage 0.
CData *cdata = CDWriter(_cycler);
if (cdata->_cache != (CacheEntry *)NULL) {
cdata->_cache->erase();
cdata->_cache = NULL;
}
// This, on the other hand, should be applied to the current
// pipeline stage.
cdata->_modified = qpGeom::get_next_modified();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::prepare
// Access: Public
@ -892,13 +847,13 @@ decompose_impl() const {
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::rotate_impl
// Access: Protected, Virtual
// Description: The virtual implementation of do_rotate().
// Description: The virtual implementation of rotate().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomPrimitive::
rotate_impl() const {
// The default implementation doesn't even try to do anything.
nassertr(false, get_vertices());
return get_vertices();
nassertr(false, CPTA_ushort());
return CPTA_ushort();
}
////////////////////////////////////////////////////////////////////
@ -914,34 +869,6 @@ void qpGeomPrimitive::
append_unused_vertices(PTA_ushort &, int) {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::do_rotate
// Access: Private
// Description: Fills _rotated_vertices by rotating the individual
// primitives to bring each flat-colored vertex to the
// opposite position. If the current shade_model
// indicates flat_vertex_last, this should bring the
// last vertex to the first position; if it indicates
// flat_vertex_first, this should bring the first vertex
// to the last position. This is used internally to
// implement get_flat_first_vertices() and
// get_flat_last_vertices().
////////////////////////////////////////////////////////////////////
CPTA_ushort qpGeomPrimitive::
do_rotate(qpGeomPrimitive::CDReader &cdata) {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Rotating " << get_type() << ": " << (void *)this << "\n";
}
PStatTimer timer(_rotate_pcollector);
CPTA_ushort rotated_vertices = rotate_impl();
CDWriter cdataw(_cycler, cdata);
cdataw->_rotated_vertices = rotated_vertices;
return rotated_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::recompute_minmax
// Access: Private
@ -1041,46 +968,6 @@ fillin(DatagramIterator &scan, BamReader *manager) {
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CacheEntry::evict_callback
// Access: Public, Virtual
// Description: Called when the entry is evicted from the cache, this
// should clean up the owning object appropriately.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::CacheEntry::
evict_callback() {
// We have to operate on stage 0 of the pipeline, since that's where
// the cache really counts. Because of the multistage pipeline, we
// might not actually have a cache entry there (it might have been
// added to stage 1 instead). No big deal if we don't.
CData *cdata = _source->_cycler.write_stage(0);
if (cdata->_cache.p() == this) {
cdata->_cache = NULL;
}
_source->_cycler.release_write_stage(0, cdata);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CacheEntry::get_result_size
// Access: Public, Virtual
// Description: Returns the approximate number of bytes represented
// by the computed result.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::CacheEntry::
get_result_size() const {
return _decomposed->get_num_bytes();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CacheEntry::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::CacheEntry::
output(ostream &out) const {
out << "primitive " << (void *)_source;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::make_copy
// Access: Public, Virtual

View File

@ -21,7 +21,6 @@
#include "pandabase.h"
#include "qpgeomEnums.h"
#include "qpgeomCacheEntry.h"
#include "typedWritableReferenceCount.h"
#include "luse.h"
#include "updateSeq.h"
@ -72,13 +71,14 @@ PUBLISHED:
virtual PT(qpGeomPrimitive) make_copy() const=0;
virtual PrimitiveType get_primitive_type() const=0;
INLINE UsageHint get_usage_hint() const;
INLINE void set_usage_hint(UsageHint usage_hint);
virtual int get_geom_rendering() const;
INLINE ShadeModel get_shade_model() const;
INLINE void set_shade_model(ShadeModel shade_model);
INLINE UsageHint get_usage_hint() const;
INLINE void set_usage_hint(UsageHint usage_hint);
// The following published methods are provided for safe, high-level
// iteration through the vertices and sub-primitives within the
// GeomPrimitive class. These work correctly regardless of the
@ -109,6 +109,7 @@ PUBLISHED:
INLINE int get_primitive_max_vertex(int n) const;
CPT(qpGeomPrimitive) decompose() const;
CPT(qpGeomPrimitive) rotate() const;
int get_num_bytes() const;
INLINE int get_data_size_bytes() const;
@ -131,8 +132,6 @@ public:
// instead.
INLINE CPTA_ushort get_vertices() const;
INLINE CPTA_ushort get_flat_first_vertices() const;
INLINE CPTA_ushort get_flat_last_vertices() const;
PTA_ushort modify_vertices();
void set_vertices(CPTA_ushort vertices);
@ -147,7 +146,6 @@ public:
virtual int get_min_num_vertices_per_primitive() const;
virtual int get_num_unused_vertices_per_primitive() const;
void clear_cache();
void prepare(PreparedGraphicsObjects *prepared_objects);
public:
@ -172,9 +170,6 @@ protected:
virtual CPTA_ushort rotate_impl() const;
virtual void append_unused_vertices(PTA_ushort &vertices, int vertex);
protected:
static PStatCollector _rotate_pcollector;
private:
// A GeomPrimitive keeps a list (actually, a map) of all the
// PreparedGraphicsObjects tables that it has been prepared into.
@ -184,16 +179,6 @@ private:
typedef pmap<PreparedGraphicsObjects *, IndexBufferContext *> Contexts;
Contexts _contexts;
class CacheEntry : public qpGeomCacheEntry {
public:
virtual void evict_callback();
virtual int get_result_size() const;
virtual void output(ostream &out) const;
qpGeomPrimitive *_source;
CPT(qpGeomPrimitive) _decomposed;
};
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
@ -206,7 +191,6 @@ private:
UsageHint _usage_hint;
ShadeModel _shade_model;
PTA_ushort _vertices;
CPTA_ushort _rotated_vertices;
PTA_int _ends;
PTA_ushort _mins;
PTA_ushort _maxs;
@ -215,17 +199,17 @@ private:
bool _got_minmax;
unsigned short _min_vertex;
unsigned short _max_vertex;
PT(CacheEntry) _cache;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
CPTA_ushort do_rotate(CDReader &cdata);
void recompute_minmax(CDWriter &cdata);
static PStatCollector _decompose_pcollector;
static PStatCollector _rotate_pcollector;
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);

View File

@ -78,6 +78,18 @@ get_primitive_type() const {
return PT_polygons;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::get_geom_rendering
// Access: Published, Virtual
// Description: Returns the set of GeomRendering bits that represent
// the rendering properties required to properly render
// this primitive.
////////////////////////////////////////////////////////////////////
int qpGeomTrifans::
get_geom_rendering() const {
return GR_triangle_fan;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::draw
// Access: Public, Virtual
@ -147,8 +159,8 @@ CPTA_ushort qpGeomTrifans::
rotate_impl() const {
// Actually, we can't rotate fans without chaging the winding order.
// It's an error to define a flat shade model for a GeomTrifan.
nassertr(false, get_vertices());
return get_vertices();
nassertr(false, CPTA_ushort());
return CPTA_ushort();
}
////////////////////////////////////////////////////////////////////

View File

@ -37,6 +37,7 @@ PUBLISHED:
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;
virtual int get_geom_rendering() const;
public:
virtual void draw(GraphicsStateGuardianBase *gsg) const;

View File

@ -79,6 +79,18 @@ get_primitive_type() const {
return PT_polygons;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::get_geom_rendering
// Access: Published, Virtual
// Description: Returns the set of GeomRendering bits that represent
// the rendering properties required to properly render
// this primitive.
////////////////////////////////////////////////////////////////////
int qpGeomTristrips::
get_geom_rendering() const {
return GR_triangle_strip;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::get_num_unused_vertices_per_primitive
// Access: Public, Virtual
@ -256,7 +268,7 @@ rotate_impl() const {
// If this assertion is triggered, there was a triangle strip with
// an odd number of vertices and either SM_flat_first_vertex or
// SM_flat_last_vertex specified--which is not allowed.
nassertr(!any_odd, new_vertices);
nassertr(!any_odd, CPTA_ushort());
return new_vertices;
}

View File

@ -37,6 +37,7 @@ PUBLISHED:
public:
virtual PT(qpGeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;
virtual int get_geom_rendering() const;
virtual int get_num_unused_vertices_per_primitive() const;
public:

View File

@ -230,7 +230,6 @@ void qpGeomVertexData::
set_array(int i, const qpGeomVertexArrayData *array) {
CDWriter cdata(_cycler);
nassertv(i >= 0 && i < (int)cdata->_arrays.size());
nassertv(array->get_array_format() == cdata->_arrays[i]->get_array_format());
cdata->_arrays[i] = (qpGeomVertexArrayData *)array;
cdata->_modified = qpGeom::get_next_modified();
cdata->_animated_vertices_modified = UpdateSeq();

View File

@ -120,7 +120,7 @@ class Lens;
class EXPCL_PANDA GraphicsStateGuardianBase : public TypedWritableReferenceCount {
public:
virtual bool get_supports_multisample() const=0;
virtual int get_supported_point_rendering() const=0;
virtual int get_supported_geom_rendering() const=0;
// These functions will be queried by the GeomIssuer to determine if
// it should issue normals, texcoords, and/or colors, based on the

View File

@ -51,10 +51,10 @@ munge_geom(GraphicsStateGuardianBase *gsg,
CPT(qpGeom) qpgeom = DCAST(qpGeom, _geom);
_munged_data = qpgeom->get_vertex_data();
int point_rendering = _state->get_point_rendering(qpgeom->get_point_rendering());
int geom_rendering = _state->get_geom_rendering(qpgeom->get_geom_rendering());
GraphicsStateGuardianBase *gsg = traverser->get_gsg();
if ((point_rendering & ~gsg->get_supported_point_rendering()) != 0) {
if ((geom_rendering & ~gsg->get_supported_geom_rendering() & qpGeom::GR_point_bits) != 0) {
// The GSG doesn't support rendering these fancy points
// directly; we have to render them in software instead.
// Munge them into quads. This will replace the _geom and

View File

@ -73,25 +73,25 @@ get_perspective() const {
}
////////////////////////////////////////////////////////////////////
// Function: RenderModeAttrib::get_point_rendering
// Function: RenderModeAttrib::get_geom_rendering
// Access: Published
// Description: Returns the union of the Geom::PointRendering bits
// Description: Returns the union of the Geom::GeomRendering bits
// that will be required once this RenderModeAttrib is
// applied to a geom which includes the indicated
// geom_point_rendering bits.
// geom_rendering bits.
////////////////////////////////////////////////////////////////////
INLINE int RenderModeAttrib::
get_point_rendering(int geom_point_rendering) const {
get_geom_rendering(int geom_rendering) const {
if (_mode == M_point) {
geom_point_rendering |= qpGeom::PR_point;
geom_rendering |= qpGeom::GR_point;
}
if ((geom_point_rendering & qpGeom::PR_point) != 0) {
if ((geom_rendering & qpGeom::GR_point) != 0) {
if (_perspective) {
geom_point_rendering |= (qpGeom::PR_perspective | qpGeom::PR_uniform_size);
geom_rendering |= (qpGeom::GR_point_perspective | qpGeom::GR_point_uniform_size);
} else if (_thickness != 1.0f) {
geom_point_rendering |= qpGeom::PR_uniform_size;
geom_rendering |= qpGeom::GR_point_uniform_size;
}
}
return geom_point_rendering;
return geom_rendering;
}

View File

@ -50,7 +50,7 @@ PUBLISHED:
INLINE float get_thickness() const;
INLINE bool get_perspective() const;
INLINE int get_point_rendering(int geom_point_rendering) const;
INLINE int get_geom_rendering(int geom_rendering) const;
public:
virtual void issue(GraphicsStateGuardianBase *gsg) const;

View File

@ -250,23 +250,23 @@ get_render_mode() const {
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_point_rendering
// Function: RenderState::get_geom_rendering
// Access: Published
// Description: Returns the union of the Geom::PointRendering bits
// Description: Returns the union of the Geom::GeomRendering bits
// that will be required once this RenderState is
// applied to a geom which includes the indicated
// geom_point_rendering bits.
// geom_rendering bits.
////////////////////////////////////////////////////////////////////
INLINE int RenderState::
get_point_rendering(int geom_point_rendering) const {
get_geom_rendering(int geom_rendering) const {
if (get_render_mode() != (const RenderModeAttrib *)NULL) {
geom_point_rendering = _render_mode->get_point_rendering(geom_point_rendering);
geom_rendering = _render_mode->get_geom_rendering(geom_rendering);
}
if (get_tex_gen() != (const TexGenAttrib *)NULL) {
geom_point_rendering = _tex_gen->get_point_rendering(geom_point_rendering);
geom_rendering = _tex_gen->get_geom_rendering(geom_rendering);
}
return geom_point_rendering;
return geom_rendering;
}
////////////////////////////////////////////////////////////////////

View File

@ -127,7 +127,7 @@ PUBLISHED:
INLINE const TexGenAttrib *get_tex_gen() const;
INLINE const RenderModeAttrib *get_render_mode() const;
INLINE int get_point_rendering(int geom_point_rendering) const;
INLINE int get_geom_rendering(int geom_rendering) const;
public:
CPT(RenderState) issue_delta_modify(const RenderState *other,

View File

@ -44,22 +44,22 @@ TexGenAttrib(const TexGenAttrib &copy) :
}
////////////////////////////////////////////////////////////////////
// Function: TexGenAttrib::get_point_rendering
// Function: TexGenAttrib::get_geom_rendering
// Access: Published
// Description: Returns the union of the Geom::PointRendering bits
// Description: Returns the union of the Geom::GeomRendering bits
// that will be required once this TexGenAttrib is
// applied to a geom which includes the indicated
// geom_point_rendering bits.
// geom_rendering bits.
////////////////////////////////////////////////////////////////////
INLINE int TexGenAttrib::
get_point_rendering(int geom_point_rendering) const {
if ((geom_point_rendering & qpGeom::PR_point) != 0) {
get_geom_rendering(int geom_rendering) const {
if ((geom_rendering & qpGeom::GR_point) != 0) {
if (_num_point_sprites > 0) {
return geom_point_rendering |= qpGeom::PR_sprite;
return geom_rendering |= qpGeom::GR_point_sprite;
}
}
return geom_point_rendering;
return geom_rendering;
}
////////////////////////////////////////////////////////////////////

View File

@ -104,7 +104,7 @@ PUBLISHED:
bool has_stage(TextureStage *stage) const;
Mode get_mode(TextureStage *stage) const;
INLINE int get_point_rendering(int geom_point_rendering) const;
INLINE int get_geom_rendering(int geom_rendering) const;
public:
INLINE const Geom::NoTexCoordStages &get_no_texcoords() const;

View File

@ -129,6 +129,8 @@ static TimeCollectorProperties time_properties[] = {
{ 1, "Cull:Munge", { 0.3, 0.3, 0.9 } },
{ 1, "Cull:Munge:Points", { 0.2, 0.8, 0.4 } },
{ 1, "Cull:Munge:Data", { 0.7, 0.5, 0.2 } },
{ 1, "Cull:Munge:Rotate", { 0.9, 0.8, 0.5 } },
{ 1, "Cull:Munge:Decompose", { 0.1, 0.3, 0.1 } },
{ 1, "Draw", { 1.0, 0.0, 0.0 }, 1.0 / 30.0 },
{ 1, "Draw:Make current", { 0.4, 0.2, 0.6 } },
{ 1, "Draw:Copy texture", { 0.2, 0.6, 0.4 } },
@ -140,7 +142,6 @@ static TimeCollectorProperties time_properties[] = {
{ 1, "Draw:Flip:End", { 0.9, 0.3, 0.6 } },
{ 1, "Draw:Bins", { 0.3, 0.6, 0.0 } },
{ 0, "Draw:Primitive", { 0.0, 0.0, 0.5 } },
{ 1, "Draw:Rotate", { 0.9, 0.8, 0.5 } },
{ 0, NULL }
};