Selaa lähdekoodia

faster text generation

David Rose 23 vuotta sitten
vanhempi
sitoutus
7421fe3e05

+ 3 - 3
panda/src/text/dynamicTextGlyph.cxx

@@ -53,7 +53,7 @@ get_geom() const {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextGlyph::get_row
-//       Access: Publiic
+//       Access: Public
 //  Description: Returns a pointer to the first byte in the pixel
 //               buffer associated with the leftmost pixel in the
 //               indicated row, where 0 is the topmost row and _y_size
@@ -79,7 +79,7 @@ get_row(int y) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextGlyph::erase
-//       Access: Publiic
+//       Access: Public
 //  Description: Erases the glyph from the texture map.
 ////////////////////////////////////////////////////////////////////
 void DynamicTextGlyph::
@@ -99,7 +99,7 @@ erase() {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextGlyph::make_geom
-//       Access: Publiic
+//       Access: Public
 //  Description: Creates the actual geometry for the glyph.  The
 //               parameters bitmap_top and bitmap_left are from
 //               FreeType, and indicate the position of the top left

+ 9 - 1
panda/src/text/textGlyph.cxx

@@ -34,5 +34,13 @@ TextGlyph::
 ////////////////////////////////////////////////////////////////////
 PT(Geom) TextGlyph::
 get_geom() const {
-  return _geom;
+  if (_geom == (Geom *)NULL) {
+    return _geom;
+  }
+
+  // We always return a copy of the geom.  That will allow the caller
+  // to modify its vertices without fear of stomping on other copies;
+  // it is also critical for the DynamicTextGlyph, which depends on
+  // this behavior to properly count references to this glyph.
+  return _geom->make_copy();
 }

+ 21 - 1
panda/src/text/textNode.I

@@ -194,7 +194,12 @@ get_expand_amp() const {
 ////////////////////////////////////////////////////////////////////
 INLINE float TextNode::
 get_line_height() const {
-  return (_font == (TextFont *)NULL) ? 0.0 : _font->get_line_height();
+  if (_font != (TextFont *)NULL) {
+    return _font->get_line_height();
+  } else if (get_default_font() != (TextFont *)NULL) {
+    return _default_font->get_line_height();
+  }
+  return 0.0f;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1305,6 +1310,21 @@ update() {
   check_rebuild();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::force_update
+//       Access: Published
+//  Description: Forces the TextNode to recompute itself now, even if
+//               it believes nothing has changed.  Normally, this
+//               should not need to be called, but it may be useful if
+//               some properties change outside of the TextNode's
+//               knowledge (for instance, within the font).
+////////////////////////////////////////////////////////////////////
+INLINE void TextNode::
+force_update() {
+  invalidate_with_measure();
+  check_rebuild();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::set_wtext
 //       Access: Public

+ 40 - 28
panda/src/text/textNode.cxx

@@ -294,7 +294,8 @@ generate() {
     assemble_text(wtext.begin(), wtext.end(), font, 
                   ul, lr, num_rows);
 
-  // Parent the text in.
+  // Parent the text in.  We create an intermediate node so we can
+  // choose to reinstance the text_root as the shadow, below.
   PT(PandaNode) text = new PandaNode("text");
   root->add_child(text, _draw_order + 2);
   text->add_child(text_root);
@@ -883,7 +884,7 @@ do_measure() {
 ////////////////////////////////////////////////////////////////////
 float TextNode::
 assemble_row(wstring::iterator &si, const wstring::iterator &send, 
-             TextFont *font, PandaNode *dest) {
+             TextFont *font, GeomNode *dest, const LMatrix4f &mat) {
   float xpos = 0.0f;
   while (si != send && (*si) != '\n') {
     wchar_t character = *si;
@@ -914,14 +915,26 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
         const RenderState *state = glyph->get_state();
 
         if (char_geom != (Geom *)NULL) {
-          LMatrix4f mat = LMatrix4f::scale_mat(glyph_scale);
-          mat.set_row(3, LVector3f(xpos, 0.0f, 0.0f));
-
-          string ch(1, (char)character);
-          PT(GeomNode) geode = new GeomNode(ch);
-          geode->add_geom(char_geom, state);
-          dest->add_child(geode);
-          geode->set_transform(TransformState::make_mat(mat));
+          LMatrix4f mat2 = LMatrix4f::scale_mat(glyph_scale);
+          mat2.set_row(3, LVector3f(xpos, 0.0f, 0.0f));
+          LMatrix4f xform = mat2 * mat;
+
+          // Transform the vertices of the geom appropriately.  We
+          // assume the geom is non-indexed.
+          PTA_Vertexf coords;
+          PTA_ushort index;
+          char_geom->get_coords(coords, index);
+          PTA_Vertexf new_coords;
+          new_coords.reserve(coords.size());
+          PTA_Vertexf::const_iterator vi;
+          for (vi = coords.begin(); vi != coords.end(); ++vi) {
+            new_coords.push_back((*vi) * xform);
+          }
+          nassertr(new_coords.size() == coords.size(), false);
+          char_geom->set_coords(new_coords);
+
+          // Now add the geom to the destination node.
+          dest->add_geom(char_geom, state);
         }
 
         xpos += glyph->get_advance() * glyph_scale;
@@ -943,27 +956,21 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
 PT(PandaNode) TextNode::
 assemble_text(wstring::iterator si, const wstring::iterator &send,
               TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) {
-  float line_height = get_line_height();
+  float line_height = font->get_line_height();
 
   ul.set(0.0f, 0.8f * line_height);
   lr.set(0.0f, 0.0f);
 
-  // Make a group node to hold our formatted text geometry.
-  PT(PandaNode) root_node = new PandaNode("text");
+  // Make a geom node to hold our formatted text geometry.
+  PT(GeomNode) root_node = new GeomNode("text");
 
   float posy = 0.0f;
-  int row_index = 0;
   while (si != send) {
-    char numstr[20];
-    sprintf(numstr, "row%d", row_index);
-    nassertr(strlen(numstr) < 20, root_node);
-
-    PT(PandaNode) row = new PandaNode(numstr);
-    float row_width = assemble_row(si, send, font, row);
-    if (si != send) {
-      // Skip past the newline.
-      ++si;
-    }
+    // First, just measure the row, so we know how wide it is.
+    // (Centered or right-justified text will require us to know this
+    // up front.)
+    wstring::iterator tsi = si;
+    float row_width = measure_row(tsi, send, font);
 
     LMatrix4f mat = LMatrix4f::ident_mat();
     if (_align == A_left) {
@@ -991,8 +998,13 @@ assemble_text(wstring::iterator si, const wstring::iterator &send,
       mat = shear * mat;
     }
 
-    row->set_transform(TransformState::make_mat(mat));
-    root_node->add_child(row);
+    // Now that we've computed the row's transform matrix, generate
+    // the actual geoms for the row.
+    assemble_row(si, send, font, root_node, mat);
+    if (si != send) {
+      // Skip past the newline.
+      ++si;
+    }
 
     posy -= line_height;
     num_rows++;
@@ -1000,7 +1012,7 @@ assemble_text(wstring::iterator si, const wstring::iterator &send,
 
   lr[1] = posy + 0.8f * line_height;
 
-  return root_node;
+  return root_node.p();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1046,7 +1058,7 @@ measure_row(wstring::iterator &si, const wstring::iterator &send,
 void TextNode::
 measure_text(wstring::iterator si, const wstring::iterator &send,
              TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) {
-  float line_height = get_line_height();
+  float line_height = font->get_line_height();
 
   ul.set(0.0f, 0.8f * line_height);
   lr.set(0.0f, 0.0f);

+ 3 - 2
panda/src/text/textNode.h

@@ -206,6 +206,7 @@ PUBLISHED:
 
   PT(PandaNode) generate();
   INLINE void update();
+  INLINE void force_update();
 
 public:
   // Direct support for wide-character strings.
@@ -249,8 +250,8 @@ private:
   void do_measure();
 
 #ifndef CPPPARSER  // interrogate has a bit of trouble with wstring.
-  float assemble_row(wstring::iterator &si, const wstring::iterator &send,
-                     TextFont *font, PandaNode *dest);
+  float assemble_row(wstring::iterator &si, const wstring::iterator &send, 
+                     TextFont *font, GeomNode *dest, const LMatrix4f &mat);
   PT(PandaNode) assemble_text(wstring::iterator si, const wstring::iterator &send,
                               TextFont *font,
                               LVector2f &ul, LVector2f &lr, int &num_rows);