From 720fddb73b7b2580f79e5cc46a7b411cb2e993e0 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sun, 20 Mar 2005 18:47:52 +0000 Subject: [PATCH] egg loader optimizations; directx vbuffer support --- panda/src/builder/builderFuncs.I | 1 - panda/src/builder/builderPrimTempl.I | 10 ++ panda/src/dxgsg8/Sources.pp | 2 + panda/src/dxgsg8/config_dxgsg8.cxx | 2 + panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 135 ++++++++++++++++-- panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 4 + panda/src/dxgsg8/dxIndexBufferContext8.I | 18 +++ panda/src/dxgsg8/dxIndexBufferContext8.cxx | 100 +++++++++++++ panda/src/dxgsg8/dxIndexBufferContext8.h | 63 ++++++++ panda/src/dxgsg8/dxgsg8_composite1.cxx | 1 + panda/src/egg/eggPrimitive.cxx | 6 +- panda/src/egg2pg/eggLoader.I | 13 -- panda/src/egg2pg/eggLoader.cxx | 134 ++++++++++++++--- panda/src/egg2pg/eggLoader.h | 7 +- panda/src/egg2pg/eggRenderState.cxx | 4 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 36 ++--- 16 files changed, 454 insertions(+), 82 deletions(-) create mode 100644 panda/src/dxgsg8/dxIndexBufferContext8.I create mode 100644 panda/src/dxgsg8/dxIndexBufferContext8.cxx create mode 100644 panda/src/dxgsg8/dxIndexBufferContext8.h diff --git a/panda/src/builder/builderFuncs.I b/panda/src/builder/builderFuncs.I index fec85820cd..d773c9af1d 100644 --- a/panda/src/builder/builderFuncs.I +++ b/panda/src/builder/builderFuncs.I @@ -570,7 +570,6 @@ build_geoms(InputIterator first, InputIterator last, InputIterator i; for (i = first; i != last; ++i) { - // Normals. // Test rule 1. diff --git a/panda/src/builder/builderPrimTempl.I b/panda/src/builder/builderPrimTempl.I index 0c8d1a4d2a..05ad78d86d 100644 --- a/panda/src/builder/builderPrimTempl.I +++ b/panda/src/builder/builderPrimTempl.I @@ -55,6 +55,7 @@ operator = (const BuilderPrimTempl ©) { DAttrib::operator = (copy); _verts = copy._verts; _components = copy._components; + _texcoord_names = copy._texcoord_names; _type = copy._type; _overall = copy._overall; @@ -334,6 +335,9 @@ has_any_pixel_size() const { template INLINE TYPENAME BuilderPrimTempl::tcn_const_iterator BuilderPrimTempl:: tcn_begin() const { + if ((_overall & BAF_overall_updated) == 0) { + ((BuilderPrimTempl *)this)->update_overall_attrib(); + } return _texcoord_names.begin(); } @@ -347,6 +351,9 @@ tcn_begin() const { template INLINE TYPENAME BuilderPrimTempl::tcn_const_iterator BuilderPrimTempl:: tcn_end() const { + if ((_overall & BAF_overall_updated) == 0) { + ((BuilderPrimTempl *)this)->update_overall_attrib(); + } return _texcoord_names.end(); } @@ -359,6 +366,9 @@ tcn_end() const { template INLINE TYPENAME BuilderPrimTempl::tcn_size_type BuilderPrimTempl:: tcn_size() const { + if ((_overall & BAF_overall_updated) == 0) { + ((BuilderPrimTempl *)this)->update_overall_attrib(); + } return _texcoord_names.size(); } diff --git a/panda/src/dxgsg8/Sources.pp b/panda/src/dxgsg8/Sources.pp index 9ea74d6dfe..cfbccbe74a 100644 --- a/panda/src/dxgsg8/Sources.pp +++ b/panda/src/dxgsg8/Sources.pp @@ -21,6 +21,7 @@ #define INSTALL_HEADERS \ dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \ dxVertexBufferContext8.h \ + dxIndexBufferContext8.h \ dxTextureContext8.h \ dxGeomMunger8.h \ d3dfont8.h \ @@ -38,6 +39,7 @@ #define INCLUDED_SOURCES \ config_dxgsg8.cxx \ dxVertexBufferContext8.cxx \ + dxIndexBufferContext8.cxx \ dxTextureContext8.cxx \ dxGeomMunger8.cxx \ d3dfont8.cxx \ diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index da27198918..9c60ebc26c 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -20,6 +20,7 @@ #include "dxGraphicsStateGuardian8.h" #include "dxTextureContext8.h" #include "dxVertexBufferContext8.h" +#include "dxIndexBufferContext8.h" #include "dxGeomMunger8.h" #include "graphicsPipeSelection.h" #include "wdxGraphicsWindow8.h" @@ -146,6 +147,7 @@ init_libdxgsg8() { DXGraphicsStateGuardian8::init_type(); DXTextureContext8::init_type(); DXVertexBufferContext8::init_type(); + DXIndexBufferContext8::init_type(); DXGeomMunger8::init_type(); wdxGraphicsPipe8::init_type(); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 53a26dec14..38c1d92b0e 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -57,6 +57,7 @@ #include "dxGeomMunger8.h" #include "config_gobj.h" #include "dxVertexBufferContext8.h" +#include "dxIndexBufferContext8.h" #ifdef DO_PSTATS #include "pStatTimer.h" @@ -2634,7 +2635,11 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: draw_triangles(const qpGeomTriangles *primitive) { - if (_vbuffer_active && _ibuffer_active) { + if (_vbuffer_active) { + IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this); + nassertv(ibc != (IndexBufferContext *)NULL); + apply_index_buffer(ibc); + _pD3DDevice->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, primitive->get_min_vertex(), @@ -2669,19 +2674,36 @@ draw_tristrips(const qpGeomTristrips *primitive) { CPTA_ushort maxs = primitive->get_maxs(); nassertv(mins.size() == ends.size() && maxs.size() == ends.size()); - CPTA_uchar array_data = _vertex_data->get_array(0)->get_data(); - int stride = _vertex_data->get_format()->get_array(0)->get_stride(); + 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++) { - _pD3DDevice->DrawIndexedPrimitiveUP - (D3DPT_TRIANGLESTRIP, - mins[i], maxs[i] - mins[i] + 1, - ends[i] - start - 2, - vertices + start, D3DFMT_INDEX16, - array_data, stride); + unsigned int start = 0; + for (size_t i = 0; i < ends.size(); i++) { + _pD3DDevice->DrawIndexedPrimitive + (D3DPT_TRIANGLESTRIP, + mins[i], maxs[i] - mins[i] + 1, + start, ends[i] - start - 2); - start = ends[i]; + start = ends[i]; + } + + } else { + CPTA_uchar array_data = _vertex_data->get_array(0)->get_data(); + int stride = _vertex_data->get_format()->get_array(0)->get_stride(); + + unsigned int start = 0; + for (size_t i = 0; i < ends.size(); i++) { + _pD3DDevice->DrawIndexedPrimitiveUP + (D3DPT_TRIANGLESTRIP, + mins[i], maxs[i] - mins[i] + 1, + ends[i] - start - 2, + vertices + start, D3DFMT_INDEX16, + array_data, stride); + + start = ends[i]; + } } } @@ -2914,7 +2936,7 @@ release_texture(TextureContext *tc) { // will also delete the pointer). // // This function should not be called directly to -// prepare a data. Instead, call Data::prepare(). +// prepare a buffer. Instead, call Geom::prepare(). //////////////////////////////////////////////////////////////////// VertexBufferContext *DXGraphicsStateGuardian8:: prepare_vertex_buffer(qpGeomVertexArrayData *data) { @@ -2994,6 +3016,93 @@ release_vertex_buffer(VertexBufferContext *vbc) { delete dvbc; } +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::prepare_index_buffer +// Access: Public, Virtual +// Description: Creates a new retained-mode representation of the +// given data, and returns a newly-allocated +// IndexBufferContext pointer to reference it. It is the +// responsibility of the calling function to later call +// release_index_buffer() with this same pointer (which +// will also delete the pointer). +// +// This function should not be called directly to +// prepare a buffer. Instead, call Geom::prepare(). +//////////////////////////////////////////////////////////////////// +IndexBufferContext *DXGraphicsStateGuardian8:: +prepare_index_buffer(qpGeomPrimitive *data) { + if (dxgsg8_cat.is_debug()) { + dxgsg8_cat.debug() + << "prepare_index_buffer(" << (void *)data << ")\n"; + } + + DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data); + + dibc->create_ibuffer(*_pScrn); + dibc->mark_loaded(); + + return dibc; +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::apply_index_buffer +// Access: Public +// Description: Makes the data the currently available data for +// rendering. +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian8:: +apply_index_buffer(IndexBufferContext *ibc) { + DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc); + + if (dibc->_ibuffer != NULL) { + add_to_index_buffer_record(dibc); + + if (dibc->was_modified()) { + if (dxgsg8_cat.is_debug()) { + dxgsg8_cat.debug() + << "apply_index_buffer(" << (void *)ibc->get_data() << ")\n"; + } + if (dibc->changed_size()) { + // Here we have to destroy the old index buffer and create a + // new one. + dibc->create_ibuffer(*_pScrn); + + } else { + // Here we just copy the new data to the index buffer. + dibc->upload_data(); + } + + dibc->mark_loaded(); + } + + _pD3DDevice->SetIndices(dibc->_ibuffer, 0); + _ibuffer_active = true; + + } else { + _pD3DDevice->SetIndices(NULL, 0); + _ibuffer_active = false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::release_index_buffer +// Access: Public, Virtual +// Description: Frees the GL resources previously allocated for the +// data. This function should never be called +// directly; instead, call Data::release() (or simply +// let the Data destruct). +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian8:: +release_index_buffer(IndexBufferContext *ibc) { + if (dxgsg8_cat.is_debug()) { + dxgsg8_cat.debug() + << "release_index_buffer(" << (void *)ibc->get_data() << ")\n"; + } + + DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc); + delete dibc; +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::get_geom_munger // Access: Public, Virtual diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 4bd1c815e7..b98f8d5ea1 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -103,6 +103,10 @@ public: void apply_vertex_buffer(VertexBufferContext *vbc); virtual void release_vertex_buffer(VertexBufferContext *vbc); + virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data); + void apply_index_buffer(IndexBufferContext *ibc); + virtual void release_index_buffer(IndexBufferContext *ibc); + virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state); virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.I b/panda/src/dxgsg8/dxIndexBufferContext8.I new file mode 100644 index 0000000000..e9204d0033 --- /dev/null +++ b/panda/src/dxgsg8/dxIndexBufferContext8.I @@ -0,0 +1,18 @@ +// Filename: dxIndexBufferContext8.I +// Created by: drose (18Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.cxx b/panda/src/dxgsg8/dxIndexBufferContext8.cxx new file mode 100644 index 0000000000..f3d896fa7f --- /dev/null +++ b/panda/src/dxgsg8/dxIndexBufferContext8.cxx @@ -0,0 +1,100 @@ +// Filename: dxIndexBufferContext8.cxx +// Created by: drose (18Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "dxIndexBufferContext8.h" +#include "qpgeomPrimitive.h" +#include "config_dxgsg8.h" +#include + +TypeHandle DXIndexBufferContext8::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: DXIndexBufferContext8::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +DXIndexBufferContext8:: +DXIndexBufferContext8(qpGeomPrimitive *data) : + IndexBufferContext(data), + _ibuffer(NULL) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: DXIndexBufferContext8::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +DXIndexBufferContext8:: +~DXIndexBufferContext8() { + if (_ibuffer != NULL) { + RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE); + _ibuffer = NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DXIndexBufferContext8::create_ibuffer +// Access: Public +// Description: Creates a new index buffer and uploads data to it. +//////////////////////////////////////////////////////////////////// +void DXIndexBufferContext8:: +create_ibuffer(DXScreenData &scrn) { + if (_ibuffer != NULL) { + RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE); + _ibuffer = NULL; + } + + HRESULT hr = scrn.pD3DDevice->CreateIndexBuffer + (get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY, + D3DFMT_INDEX16, D3DPOOL_MANAGED, &_ibuffer); + if (FAILED(hr)) { + dxgsg8_cat.warning() + << "CreateIndexBuffer failed" << D3DERRORSTRING(hr); + _ibuffer = NULL; + + } else { + upload_data(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DXIndexBufferContext8::upload_data +// Access: Public +// Description: Copies the latest data from the client store to +// DirectX. +//////////////////////////////////////////////////////////////////// +void DXIndexBufferContext8:: +upload_data() { + nassertv(_ibuffer != NULL); + + int data_size = get_data()->get_data_size_bytes(); + + BYTE *local_pointer; + HRESULT hr = _ibuffer->Lock(0, data_size, &local_pointer, 0); + if (FAILED(hr)) { + dxgsg8_cat.error() + << "IndexBuffer::Lock failed" << D3DERRORSTRING(hr); + return; + } + + memcpy(local_pointer, get_data()->get_flat_first_vertices(), data_size); + + _ibuffer->Unlock(); +} + diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.h b/panda/src/dxgsg8/dxIndexBufferContext8.h new file mode 100644 index 0000000000..20d6745e5b --- /dev/null +++ b/panda/src/dxgsg8/dxIndexBufferContext8.h @@ -0,0 +1,63 @@ +// Filename: dxIndexBufferContext8.h +// Created by: drose (18Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef DXINDEXBUFFERCONTEXT8_H +#define DXINDEXBUFFERCONTEXT8_H + +#include "pandabase.h" +#include "dxgsg8base.h" +#include "indexBufferContext.h" + +//////////////////////////////////////////////////////////////////// +// Class : DXIndexBufferContext8 +// Description : Caches a GeomPrimitive in the DirectX device as +// an index buffer. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDADX DXIndexBufferContext8 : public IndexBufferContext { +public: + DXIndexBufferContext8(qpGeomPrimitive *data); + virtual ~DXIndexBufferContext8(); + + void create_ibuffer(DXScreenData &scrn); + void upload_data(); + + IDirect3DIndexBuffer8 *_ibuffer; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + IndexBufferContext::init_type(); + register_type(_type_handle, "DXIndexBufferContext8", + IndexBufferContext::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "dxIndexBufferContext8.I" + +#endif + + diff --git a/panda/src/dxgsg8/dxgsg8_composite1.cxx b/panda/src/dxgsg8/dxgsg8_composite1.cxx index 93f83e8aec..ff1ba1eeee 100644 --- a/panda/src/dxgsg8/dxgsg8_composite1.cxx +++ b/panda/src/dxgsg8/dxgsg8_composite1.cxx @@ -2,6 +2,7 @@ #include "config_dxgsg8.cxx" #include "dxTextureContext8.cxx" #include "dxVertexBufferContext8.cxx" +#include "dxIndexBufferContext8.cxx" #include "dxGeomMunger8.cxx" #include "d3dfont8.cxx" #include "wdxGraphicsPipe8.cxx" diff --git a/panda/src/egg/eggPrimitive.cxx b/panda/src/egg/eggPrimitive.cxx index 35deea3ffd..7b985c421f 100644 --- a/panda/src/egg/eggPrimitive.cxx +++ b/panda/src/egg/eggPrimitive.cxx @@ -31,7 +31,7 @@ TypeHandle EggPrimitive::_type_handle; //////////////////////////////////////////////////////////////////// // Function: EggPrimitive::determine_alpha_mode // Access: Published, Virtual -// Description: Walks back up the hierarchy, looking for an EggPrimitive +// Description: Walks back up the hierarchy, looking for an EggGroup // or EggPrimitive or some such object at this level or // above this primitive that has an alpha_mode other than // AM_unspecified. Returns a valid EggRenderMode pointer @@ -139,7 +139,7 @@ determine_visibility_mode() { //////////////////////////////////////////////////////////////////// // Function: EggPrimitive::determine_draw_order // Access: Published, Virtual -// Description: Walks back up the hierarchy, looking for an EggPrimitive +// Description: Walks back up the hierarchy, looking for an EggGroup // or EggPrimitive or some such object at this level or // above this primitive that has a draw_order specified. // Returns a valid EggRenderMode pointer if one is found, @@ -166,7 +166,7 @@ determine_draw_order() { //////////////////////////////////////////////////////////////////// // Function: EggPrimitive::determine_bin // Access: Published, Virtual -// Description: Walks back up the hierarchy, looking for an EggPrimitive +// Description: Walks back up the hierarchy, looking for an EggGroup // or EggPrimitive or some such object at this level or // above this primitive that has a bin specified. Returns a // valid EggRenderMode pointer if one is found, or NULL diff --git a/panda/src/egg2pg/eggLoader.I b/panda/src/egg2pg/eggLoader.I index 04c4bf2a7b..9aba9f22dd 100644 --- a/panda/src/egg2pg/eggLoader.I +++ b/panda/src/egg2pg/eggLoader.I @@ -42,16 +42,3 @@ operator < (const PrimitiveUnifier &other) const { } return _shade_model < other._shade_model; } - -//////////////////////////////////////////////////////////////////// -// Function: EggLoader::VertexPoolTransform::operator < -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool EggLoader::VertexPoolTransform:: -operator < (const EggLoader::VertexPoolTransform &other) const { - if (_vertex_pool != other._vertex_pool) { - return _vertex_pool < other._vertex_pool; - } - return _transform.compare_to(other._transform, 0.001) < 0; -} diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index b89abb9cf5..c0f3d46359 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -154,7 +154,13 @@ void EggLoader:: build_graph() { _deferred_nodes.clear(); - // First, load up all of the textures. + // Expand all of the ObjectType flags before we do anything else; + // that might prune out large portions of the scene. + if (!expand_all_object_types(_data)) { + return; + } + + // Now, load up all of the textures. load_textures(); // Clean up the vertices. @@ -1483,7 +1489,8 @@ make_polyset(EggBin *egg_bin, PandaNode *parent) { // Now convert the vertex pool to a GeomVertexData. nassertr(vertex_pool != (EggVertexPool *)NULL, NULL); PT(qpGeomVertexData) vertex_data = - make_vertex_data(vertex_pool, egg_bin->get_vertex_to_node()); + make_vertex_data(render_state, vertex_pool, + egg_bin->get_vertex_to_node()); nassertr(vertex_data != (qpGeomVertexData *)NULL, NULL); // And create a Geom to hold the primitives. @@ -1565,7 +1572,6 @@ make_lod(EggBin *egg_bin, PandaNode *parent) { return create_group_arc(egg_bin, parent, lod_node); } - //////////////////////////////////////////////////////////////////// // Function: EggLoader::make_node (EggGroup) // Access: Private @@ -1575,14 +1581,6 @@ PandaNode *EggLoader:: make_node(EggGroup *egg_group, PandaNode *parent) { PT(PandaNode) node = NULL; - if (egg_group->get_num_object_types() != 0) { - pset expanded; - pvector expanded_history; - if (!expand_object_types(egg_group, expanded, expanded_history)) { - return NULL; - } - } - if (egg_group->get_dart_type() != EggGroup::DT_none) { // A group with the flag set means to create a character. CharacterMaker char_maker(egg_group, *this); @@ -1865,7 +1863,10 @@ check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden) { all_polysets = false; return; } - } else { + } else if ((*ci)->is_of_type(EggGroup::get_class_type())) { + // Other kinds of children, like vertex pools, comments, + // textures, etc., are ignored; but groups indicate more nodes, + // so if we find a nested group it means we're not all polysets. all_polysets = false; return; } @@ -1881,9 +1882,11 @@ check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden) { // transform, just returns it. //////////////////////////////////////////////////////////////////// PT(qpGeomVertexData) EggLoader:: -make_vertex_data(EggVertexPool *vertex_pool, const LMatrix4d &transform) { +make_vertex_data(const EggRenderState *render_state, + EggVertexPool *vertex_pool, const LMatrix4d &transform) { VertexPoolTransform vpt; vpt._vertex_pool = vertex_pool; + vpt._bake_in_uvs = render_state->_bake_in_uvs; vpt._transform = transform; VertexPoolData::iterator di; @@ -1916,9 +1919,8 @@ make_vertex_data(EggVertexPool *vertex_pool, const LMatrix4d &transform) { if (name == "default") { name = string(); } - array_format->add_data_type - (InternalName::get_texcoord_name(name), 2, - qpGeomVertexDataType::NT_float); + PT(InternalName) iname = InternalName::get_texcoord_name(name); + array_format->add_data_type(iname, 2, qpGeomVertexDataType::NT_float); } CPT(qpGeomVertexFormat) format = @@ -1950,13 +1952,23 @@ make_vertex_data(EggVertexPool *vertex_pool, const LMatrix4d &transform) { EggVertex::const_uv_iterator uvi; for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) { - EggVertexUV *uv = (*uvi); - string name = uv->get_name(); + EggVertexUV *egg_uv = (*uvi); + TexCoordd uv = egg_uv->get_uv(); + + string name = egg_uv->get_name(); if (name == "default") { name = string(); } - gvi.set_data_type(InternalName::get_texcoord_name(name)); - gvi.set_data2(LCAST(float, uv->get_uv())); + PT(InternalName) iname = InternalName::get_texcoord_name(name); + gvi.set_data_type(iname); + + BakeInUVs::const_iterator buv = render_state->_bake_in_uvs.find(iname); + if (buv != render_state->_bake_in_uvs.end()) { + // If we are to bake in a texture matrix, do so now. + uv = uv * (*buv).second->get_transform(); + } + + gvi.set_data2(LCAST(float, uv)); } } @@ -2736,6 +2748,52 @@ apply_deferred_nodes(PandaNode *node, const DeferredNodeProperty &prop) { } } +//////////////////////////////////////////////////////////////////// +// Function: EggLoader::expand_all_object_types +// Access: Private +// Description: Walks the hierarchy and calls expand_object_types() +// on each node, to expand all of the ObjectType +// definitions in the file at once. Also prunes any +// nodes that are flagged "backstage". +// +// The return value is true if this node should be kept, +// false if it should be pruned. +//////////////////////////////////////////////////////////////////// +bool EggLoader:: +expand_all_object_types(EggNode *egg_node) { + if (egg_node->is_of_type(EggGroup::get_class_type())) { + EggGroup *egg_group = DCAST(EggGroup, egg_node); + + if (egg_group->get_num_object_types() != 0) { + pset expanded; + pvector expanded_history; + if (!expand_object_types(egg_group, expanded, expanded_history)) { + return false; + } + } + } + + // Now recurse on children, and we might prune children from this + // list as we go. + if (egg_node->is_of_type(EggGroupNode::get_class_type())) { + EggGroupNode *egg_group_node = DCAST(EggGroupNode, egg_node); + EggGroupNode::const_iterator ci; + ci = egg_group_node->begin(); + while (ci != egg_group_node->end()) { + EggGroupNode::const_iterator cnext = ci; + ++cnext; + + if (!expand_all_object_types(*ci)) { + // Prune this child. + egg_group_node->erase(ci); + } + ci = cnext; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: EggLoader::expand_object_types // Access: Private @@ -2797,7 +2855,7 @@ expand_object_types(EggGroup *egg_group, const pset &expanded, } //////////////////////////////////////////////////////////////////// -// Function: EggLoader::expand_object_type +// Function: EggLoader::do_expand_object_types // Access: Private // Description: Further implementation of expand_object_types(). //////////////////////////////////////////////////////////////////// @@ -3093,5 +3151,37 @@ get_combine_operand(const EggTexture *egg_tex, return TextureStage::CO_undefined; } - +//////////////////////////////////////////////////////////////////// +// Function: EggLoader::VertexPoolTransform::operator < +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool EggLoader::VertexPoolTransform:: +operator < (const EggLoader::VertexPoolTransform &other) const { + if (_vertex_pool != other._vertex_pool) { + return _vertex_pool < other._vertex_pool; + } + int compare = _transform.compare_to(other._transform, 0.001); + if (compare != 0) { + return compare < 0; + } + if (_bake_in_uvs.size() != other._bake_in_uvs.size()) { + return _bake_in_uvs.size() < other._bake_in_uvs.size(); + } + + BakeInUVs::const_iterator ai, bi; + ai = _bake_in_uvs.begin(); + bi = other._bake_in_uvs.begin(); + while (ai != _bake_in_uvs.end()) { + nassertr(bi != other._bake_in_uvs.end(), false); + if ((*ai) != (*bi)) { + return (*ai) < (*bi); + } + ++ai; + ++bi; + } + nassertr(bi == other._bake_in_uvs.end(), false); + + return false; +} diff --git a/panda/src/egg2pg/eggLoader.h b/panda/src/egg2pg/eggLoader.h index 31edb8c8a7..f0ac164858 100644 --- a/panda/src/egg2pg/eggLoader.h +++ b/panda/src/egg2pg/eggLoader.h @@ -137,7 +137,8 @@ private: void check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden); - PT(qpGeomVertexData) make_vertex_data(EggVertexPool *vertex_pool, + PT(qpGeomVertexData) make_vertex_data(const EggRenderState *render_state, + EggVertexPool *vertex_pool, const LMatrix4d &transform); void make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim, Primitives &primitives); @@ -173,6 +174,7 @@ private: EggGroup::CollideFlags flags); void apply_deferred_nodes(PandaNode *node, const DeferredNodeProperty &prop); + bool expand_all_object_types(EggNode *egg_node); bool expand_object_types(EggGroup *egg_group, const pset &expanded, const pvector &expanded_history); bool do_expand_object_type(EggGroup *egg_group, const pset &expanded, @@ -207,8 +209,9 @@ private: class VertexPoolTransform { public: - INLINE bool operator < (const VertexPoolTransform &other) const; + bool operator < (const VertexPoolTransform &other) const; PT(EggVertexPool) _vertex_pool; + BakeInUVs _bake_in_uvs; LMatrix4d _transform; }; typedef pmap VertexPoolData; diff --git a/panda/src/egg2pg/eggRenderState.cxx b/panda/src/egg2pg/eggRenderState.cxx index 641bfae82b..3ffca9e55e 100644 --- a/panda/src/egg2pg/eggRenderState.cxx +++ b/panda/src/egg2pg/eggRenderState.cxx @@ -188,7 +188,7 @@ fill_state(EggPrimitive *egg_prim) { const InternalName *uv_name = (*tmi).first; const TexMatTransforms &tmt = (*tmi).second; - if (tmt.size() == 1 && !needs_tex_mat && !use_qpgeom) { + if (tmt.size() == 1 && !needs_tex_mat) { // Only one unique transform sharing this set of UV's. We can // bake in the transform! const TexMatTextures &tmtex = (*tmt.begin()).second; @@ -346,8 +346,6 @@ fill_state(EggPrimitive *egg_prim) { if (use_qpgeom) { if (_flat_shaded) { add_attrib(ShadeModelAttrib::make(ShadeModelAttrib::M_flat)); - } else { - add_attrib(ShadeModelAttrib::make(ShadeModelAttrib::M_smooth)); } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index f360d709f8..6b19842ef2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2031,8 +2031,6 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) { - DO_PSTATS_STUFF(_draw_primitive_pcollector.start()); - if (!GraphicsStateGuardian::begin_draw_primitives(geom, vertex_data)) { return false; } @@ -2095,8 +2093,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) { GLP(EnableClientState)(GL_VERTEX_ARRAY); } - if (wants_normals() && - _vertex_data->get_array_info(InternalName::get_normal(), + if (_vertex_data->get_array_info(InternalName::get_normal(), array_data, num_components, numeric_type, start, stride)) { const unsigned char *client_pointer = setup_array_data(array_data); @@ -2107,27 +2104,18 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomVertexData *vertex_data) { GLP(DisableClientState)(GL_NORMAL_ARRAY); } - if (wants_colors()) { - if (_vertex_data->get_array_info(InternalName::get_color(), - array_data, num_components, numeric_type, - start, stride)) { - const unsigned char *client_pointer = setup_array_data(array_data); - GLP(ColorPointer)(num_components, get_numeric_type(numeric_type), - stride, client_pointer + start); - GLP(EnableClientState)(GL_COLOR_ARRAY); - - } else { - // We wanted colors, but the geom didn't have any; just issue - // white. - GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); - GLP(DisableClientState)(GL_COLOR_ARRAY); - } + if (_vertex_data->get_array_info(InternalName::get_color(), + array_data, num_components, numeric_type, + start, stride)) { + const unsigned char *client_pointer = setup_array_data(array_data); + GLP(ColorPointer)(num_components, get_numeric_type(numeric_type), + stride, client_pointer + start); + GLP(EnableClientState)(GL_COLOR_ARRAY); } else { GLP(DisableClientState)(GL_COLOR_ARRAY); } - if (wants_texcoords() && - _vertex_data->get_array_info(InternalName::get_texcoord(), + if (_vertex_data->get_array_info(InternalName::get_texcoord(), array_data, num_components, numeric_type, start, stride)) { const unsigned char *client_pointer = setup_array_data(array_data); @@ -2209,8 +2197,6 @@ end_draw_primitives() { _geom_display_list = NULL; GraphicsStateGuardian::end_draw_primitives(); - - DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } //////////////////////////////////////////////////////////////////// @@ -2426,7 +2412,7 @@ release_geom(GeomContext *gc) { // will also delete the pointer). // // This function should not be called directly to -// prepare a data. Instead, call Data::prepare(). +// prepare a buffer. Instead, call Geom::prepare(). //////////////////////////////////////////////////////////////////// VertexBufferContext *CLP(GraphicsStateGuardian):: prepare_vertex_buffer(qpGeomVertexArrayData *data) { @@ -2557,7 +2543,7 @@ setup_array_data(const qpGeomVertexArrayData *data) { // will also delete the pointer). // // This function should not be called directly to -// prepare a data. Instead, call Data::prepare(). +// prepare a buffer. Instead, call Geom::prepare(). //////////////////////////////////////////////////////////////////// IndexBufferContext *CLP(GraphicsStateGuardian):: prepare_index_buffer(qpGeomPrimitive *data) {