diff --git a/dtool/src/dtoolutil/textEncoder.I b/dtool/src/dtoolutil/textEncoder.I index 766319d6da..c9eeb0ec66 100644 --- a/dtool/src/dtoolutil/textEncoder.I +++ b/dtool/src/dtoolutil/textEncoder.I @@ -220,7 +220,7 @@ get_unicode_char(size_t index) const { * according to set_encoding(). */ INLINE void TextEncoder:: -set_unicode_char(size_t index, int character) { +set_unicode_char(size_t index, char32_t character) { get_wtext(); if (index < _wtext.length()) { _wtext[index] = character; @@ -283,7 +283,7 @@ reencode_text(const std::string &text, TextEncoder::Encoding from, * otherwise. This is akin to ctype's isalpha(), extended to Unicode. */ INLINE bool TextEncoder:: -unicode_isalpha(int character) { +unicode_isalpha(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { return false; @@ -297,7 +297,7 @@ unicode_isalpha(int character) { * otherwise. This is akin to ctype's isdigit(), extended to Unicode. */ INLINE bool TextEncoder:: -unicode_isdigit(int character) { +unicode_isdigit(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { // The digits aren't actually listed in the map. @@ -312,7 +312,7 @@ unicode_isdigit(int character) { * otherwise. This is akin to ctype's ispunct(), extended to Unicode. */ INLINE bool TextEncoder:: -unicode_ispunct(int character) { +unicode_ispunct(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { // Some punctuation marks aren't listed in the map. @@ -326,7 +326,7 @@ unicode_ispunct(int character) { * otherwise. This is akin to ctype's isupper(), extended to Unicode. */ INLINE bool TextEncoder:: -unicode_isupper(int character) { +unicode_isupper(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { return false; @@ -339,7 +339,7 @@ unicode_isupper(int character) { * otherwise. This is akin to ctype's isspace(), extended to Unicode. */ INLINE bool TextEncoder:: -unicode_isspace(int character) { +unicode_isspace(char32_t character) { switch (character) { case ' ': case '\t': @@ -356,7 +356,7 @@ unicode_isspace(int character) { * otherwise. This is akin to ctype's islower(), extended to Unicode. */ INLINE bool TextEncoder:: -unicode_islower(int character) { +unicode_islower(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { return false; @@ -369,7 +369,7 @@ unicode_islower(int character) { * akin to ctype's toupper(), extended to Unicode. */ INLINE int TextEncoder:: -unicode_toupper(int character) { +unicode_toupper(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { return character; @@ -382,7 +382,7 @@ unicode_toupper(int character) { * akin to ctype's tolower(), extended to Unicode. */ INLINE int TextEncoder:: -unicode_tolower(int character) { +unicode_tolower(char32_t character) { const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character); if (entry == nullptr) { return character; diff --git a/dtool/src/dtoolutil/textEncoder.h b/dtool/src/dtoolutil/textEncoder.h index 30004ef5d3..1e1d9eeda4 100644 --- a/dtool/src/dtoolutil/textEncoder.h +++ b/dtool/src/dtoolutil/textEncoder.h @@ -23,7 +23,7 @@ class StringDecoder; /** * This class can be used to convert text between multiple representations, - * e.g. utf-8 to Unicode. You may use it as a static class object, passing + * e.g. UTF-8 to UTF-16. You may use it as a static class object, passing * the encoding each time, or you may create an instance and use that object, * which will record the current encoding and retain the current string. * @@ -78,21 +78,21 @@ PUBLISHED: INLINE void append_unicode_char(char32_t character); INLINE size_t get_num_chars() const; INLINE int get_unicode_char(size_t index) const; - INLINE void set_unicode_char(size_t index, int character); + INLINE void set_unicode_char(size_t index, char32_t character); INLINE std::string get_encoded_char(size_t index) const; INLINE std::string get_encoded_char(size_t index, Encoding encoding) const; INLINE std::string get_text_as_ascii() const; INLINE static std::string reencode_text(const std::string &text, Encoding from, Encoding to); - INLINE static bool unicode_isalpha(int character); - INLINE static bool unicode_isdigit(int character); - INLINE static bool unicode_ispunct(int character); - INLINE static bool unicode_islower(int character); - INLINE static bool unicode_isupper(int character); - INLINE static bool unicode_isspace(int character); - INLINE static int unicode_toupper(int character); - INLINE static int unicode_tolower(int character); + INLINE static bool unicode_isalpha(char32_t character); + INLINE static bool unicode_isdigit(char32_t character); + INLINE static bool unicode_ispunct(char32_t character); + INLINE static bool unicode_islower(char32_t character); + INLINE static bool unicode_isupper(char32_t character); + INLINE static bool unicode_isspace(char32_t character); + INLINE static int unicode_toupper(char32_t character); + INLINE static int unicode_tolower(char32_t character); INLINE static std::string upper(const std::string &source); INLINE static std::string upper(const std::string &source, Encoding encoding); diff --git a/dtool/src/dtoolutil/unicodeLatinMap.cxx b/dtool/src/dtoolutil/unicodeLatinMap.cxx index 87c9cb5a7d..288b85a4ce 100644 --- a/dtool/src/dtoolutil/unicodeLatinMap.cxx +++ b/dtool/src/dtoolutil/unicodeLatinMap.cxx @@ -1378,7 +1378,7 @@ static const wchar_t combining_accent_map[] = { * Returns the Entry associated with the indicated character, if there is one. */ const UnicodeLatinMap::Entry *UnicodeLatinMap:: -look_up(wchar_t character) { +look_up(char32_t character) { if (!_initialized) { init(); } diff --git a/dtool/src/dtoolutil/unicodeLatinMap.h b/dtool/src/dtoolutil/unicodeLatinMap.h index fb94154f7f..6ed3c5f17c 100644 --- a/dtool/src/dtoolutil/unicodeLatinMap.h +++ b/dtool/src/dtoolutil/unicodeLatinMap.h @@ -112,17 +112,17 @@ public: class Entry { public: - wchar_t _character; + char32_t _character; CharType _char_type; char _ascii_equiv; char _ascii_additional; - wchar_t _tolower_character; - wchar_t _toupper_character; + char32_t _tolower_character; + char32_t _toupper_character; AccentType _accent_type; int _additional_flags; }; - static const Entry *look_up(wchar_t character); + static const Entry *look_up(char32_t character); static wchar_t get_combining_accent(AccentType accent); @@ -130,7 +130,7 @@ private: static void init(); static bool _initialized; - typedef phash_map > ByCharacter; + typedef phash_map > ByCharacter; static ByCharacter *_by_character; enum { max_direct_chars = 256 }; static const Entry *_direct_chars[max_direct_chars]; diff --git a/dtool/src/prc/notifyCategory.I b/dtool/src/prc/notifyCategory.I index 5793917d91..20678fbace 100644 --- a/dtool/src/prc/notifyCategory.I +++ b/dtool/src/prc/notifyCategory.I @@ -82,26 +82,6 @@ is_debug() const { // Instruct the compiler to optimize for the usual case. return UNLIKELY(is_on(NS_debug)); } -#else -/** - * When NOTIFY_DEBUG is not defined, the categories are never set to "spam" or - * "debug" severities, and these methods are redefined to be static to make it - * more obvious to the compiler. - */ -constexpr bool NotifyCategory:: -is_spam() { - return false; -} - -/** - * When NOTIFY_DEBUG is not defined, the categories are never set to "spam" or - * "debug" severities, and these methods are redefined to be static to make it - * more obvious to the compiler. - */ -constexpr bool NotifyCategory:: -is_debug() { - return false; -} #endif /** diff --git a/dtool/src/prc/notifyCategory.h b/dtool/src/prc/notifyCategory.h index f3e99b09ba..9a2a9fa4e2 100644 --- a/dtool/src/prc/notifyCategory.h +++ b/dtool/src/prc/notifyCategory.h @@ -55,8 +55,8 @@ PUBLISHED: INLINE bool is_spam() const; INLINE bool is_debug() const; #else - constexpr static bool is_spam(); - constexpr static bool is_debug(); + constexpr static bool is_spam() { return false; } + constexpr static bool is_debug() { return false; } #endif INLINE bool is_info() const; INLINE bool is_warning() const; diff --git a/dtool/src/prc/notifyCategoryProxy.I b/dtool/src/prc/notifyCategoryProxy.I index eaca9b6e33..fbdac1f0ca 100644 --- a/dtool/src/prc/notifyCategoryProxy.I +++ b/dtool/src/prc/notifyCategoryProxy.I @@ -72,12 +72,6 @@ is_spam() { // Instruct the compiler to optimize for the usual case. return UNLIKELY(get_unsafe_ptr()->is_spam()); } -#else -template -constexpr bool NotifyCategoryProxy:: -is_spam() { - return false; -} #endif /** @@ -90,12 +84,6 @@ is_debug() { // Instruct the compiler to optimize for the usual case. return UNLIKELY(get_unsafe_ptr()->is_debug()); } -#else -template -constexpr bool NotifyCategoryProxy:: -is_debug() { - return false; -} #endif /** diff --git a/dtool/src/prc/notifyCategoryProxy.h b/dtool/src/prc/notifyCategoryProxy.h index 06f38ec804..5465529583 100644 --- a/dtool/src/prc/notifyCategoryProxy.h +++ b/dtool/src/prc/notifyCategoryProxy.h @@ -75,8 +75,8 @@ public: INLINE bool is_spam(); INLINE bool is_debug(); #else - constexpr static bool is_spam(); - constexpr static bool is_debug(); + constexpr static bool is_spam() { return false; } + constexpr static bool is_debug() { return false; } #endif INLINE bool is_info(); INLINE bool is_warning(); diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 6e8a01d68f..35f7966a3f 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -1254,7 +1254,7 @@ compare_collider_to_geom(CollisionEntry &entry, const Geom *geom, if (geom->get_primitive_type() == Geom::PT_polygons) { Thread *current_thread = Thread::get_current_thread(); - CPT(GeomVertexData) data = geom->get_vertex_data()->animate_vertices(true, current_thread); + CPT(GeomVertexData) data = geom->get_animated_vertex_data(true, current_thread); GeomVertexReader vertex(data, InternalName::get_vertex()); int num_primitives = geom->get_num_primitives(); diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx index e3bed91e27..74314bce06 100644 --- a/panda/src/distort/projectionScreen.cxx +++ b/panda/src/distort/projectionScreen.cxx @@ -484,8 +484,7 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) { const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv; // Iterate through all the vertices in the Geom. - CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread); - vdata = vdata->animate_vertices(true, current_thread); + CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(true, current_thread); CPT(GeomVertexFormat) vformat = vdata->get_format(); if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) { @@ -507,7 +506,7 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) { PT(GeomVertexData) modify_vdata = geom->modify_vertex_data(); // Maybe the vdata has animation that we should consider. - CPT(GeomVertexData) animated_vdata = geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread); + CPT(GeomVertexData) animated_vdata = geom->get_animated_vertex_data(true, current_thread); GeomVertexWriter texcoord(modify_vdata, _texcoord_name, current_thread); GeomVertexWriter color(modify_vdata, current_thread); @@ -674,9 +673,8 @@ make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) { Thread *current_thread = Thread::get_current_thread(); PT(Geom) new_geom = geom->make_copy(); + new_geom->set_vertex_data(new_geom->get_animated_vertex_data(false, current_thread)); PT(GeomVertexData) vdata = new_geom->modify_vertex_data(); - new_geom->set_vertex_data(vdata->animate_vertices(false, current_thread)); - vdata = new_geom->modify_vertex_data(); GeomVertexRewriter vertex(vdata, InternalName::get_vertex()); while (!vertex.is_at_end()) { LVertex vert = vertex.get_data3(); diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 565f8c47b4..bafe523e0f 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -286,6 +286,28 @@ make_nonindexed(bool composite_only) { return num_changed; } +/** + * Returns a GeomVertexData that represents the results of computing the + * vertex animation on the CPU for this Geom's vertex data. + * + * If there is no CPU-defined vertex animation on this object, this just + * returns the original object. + * + * If there is vertex animation, but the VertexTransform values have not + * changed since last time, this may return the same pointer it returned + * previously. Even if the VertexTransform values have changed, it may still + * return the same pointer, but with its contents modified (this is preferred, + * since it allows the graphics backend to update vertex buffers optimally). + * + * If force is false, this method may return immediately with stale data, if + * the vertex data is not completely resident. If force is true, this method + * will never return stale data, but may block until the data is available. + */ +CPT(GeomVertexData) Geom:: +get_animated_vertex_data(bool force, Thread *current_thread) const { + return get_vertex_data()->animate_vertices(force, current_thread); +} + /** * Replaces the ith GeomPrimitive object stored within the Geom with the new * object. @@ -1311,8 +1333,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const { int num_vertices = 0; // Get the vertex data, after animation. - CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer(current_thread); - vertex_data = vertex_data->animate_vertices(true, current_thread); + CPT(GeomVertexData) vertex_data = get_animated_vertex_data(true, current_thread); // Now actually compute the bounding volume. We do this by using // calc_tight_bounds to determine our box first. diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 833ac3cd83..82aac75cfa 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -85,6 +85,8 @@ PUBLISHED: void offset_vertices(const GeomVertexData *data, int offset); int make_nonindexed(bool composite_only); + CPT(GeomVertexData) get_animated_vertex_data(bool force, Thread *current_thread) const; + INLINE bool is_empty() const; INLINE size_t get_num_primitives() const; diff --git a/panda/src/gobj/geomVertexArrayData.I b/panda/src/gobj/geomVertexArrayData.I index cfe12f9013..30e5c590e8 100644 --- a/panda/src/gobj/geomVertexArrayData.I +++ b/panda/src/gobj/geomVertexArrayData.I @@ -45,7 +45,9 @@ has_column(const InternalName *name) const { */ INLINE int GeomVertexArrayData:: get_num_rows() const { - return get_handle()->get_num_rows(); + CDReader cdata(_cycler); + nassertr(_array_format->get_stride() != 0, 0); + return cdata->_buffer.get_size() / _array_format->get_stride(); } /** diff --git a/panda/src/gobj/geomVertexData.I b/panda/src/gobj/geomVertexData.I index bfea5a10ef..bd68fc4cf4 100644 --- a/panda/src/gobj/geomVertexData.I +++ b/panda/src/gobj/geomVertexData.I @@ -60,9 +60,20 @@ has_column(const InternalName *name) const { */ INLINE int GeomVertexData:: get_num_rows() const { - GeomVertexDataPipelineReader reader(this, Thread::get_current_thread()); - reader.check_array_readers(); - return reader.get_num_rows(); + CPT(GeomVertexArrayData) array; + { + CDReader cdata(_cycler); + nassertr(cdata->_format->get_num_arrays() == cdata->_arrays.size(), 0); + + if (cdata->_arrays.size() == 0) { + // No arrays means no rows. Weird but legal. + return 0; + } + + array = cdata->_arrays[0].get_read_pointer(); + } + + return array->get_num_rows(); } /** diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 5e5fa7a1d4..d97197e25c 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -621,13 +621,26 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, const TransformBlend &blend = blend_table->get_blend(from.get_data1i()); LVecBase4 weights = LVecBase4::zero(); LVecBase4i indices(0, 0, 0, 0); - nassertv(blend.get_num_transforms() <= 4); - for (size_t i = 0; i < blend.get_num_transforms(); i++) { - weights[i] = blend.get_weight(i); - indices[i] = add_transform(transform_table, blend.get_transform(i), - already_added); + if (blend.get_num_transforms() <= 4) { + for (size_t i = 0; i < blend.get_num_transforms(); i++) { + weights[i] = blend.get_weight(i); + indices[i] = add_transform(transform_table, blend.get_transform(i), + already_added); + } + } else { + // Limit the number of blends to the four with highest weights. + TransformBlend blend2(blend); + blend2.limit_transforms(4); + blend2.normalize_weights(); + + for (size_t i = 0; i < 4; i++) { + weights[i] = blend2.get_weight(i); + indices[i] = add_transform(transform_table, blend2.get_transform(i), + already_added); + } } + if (weight.has_column()) { weight.set_data4(weights); } diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index fdad25bb48..2fff484de3 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -866,7 +866,7 @@ transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name, PT(Geom) geom = orig_geom->make_copy(); // Ensure that any vertex animation has been applied. - geom->set_vertex_data(geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread)); + geom->set_vertex_data(geom->get_animated_vertex_data(true, current_thread)); // Now get a modifiable pointer to the vertex data in the new Geom. This // will actually perform a deep copy of the vertex data. diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 16e95442c2..17d5555e5d 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -376,8 +376,7 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, geom = transformer.premunge_geom(geom, munger); // Prepare each of the vertex arrays in the munged Geom. - CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread); - vdata = vdata->animate_vertices(false, current_thread); + CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(false, current_thread); GeomVertexDataPipelineReader vdata_reader(vdata, current_thread); int num_arrays = vdata_reader.get_num_arrays(); for (int i = 0; i < num_arrays; ++i) { @@ -474,7 +473,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any, for (gi = geoms->begin(); gi != geoms->end(); ++gi) { CPT(Geom) geom = (*gi)._geom.get_read_pointer(); geom->calc_tight_bounds(min_point, max_point, found_any, - geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread), + geom->get_animated_vertex_data(true, current_thread), !next_transform->is_identity(), mat, current_thread); }