Преглед изворни кода

egg: add ability to read <Tangent> with four components

This is not intended to be used just yet in 1.10, but already added in preparation for changes on master to support #546.  I'm just allowing Panda to parse the syntax ahead of time to reduce potential .egg incompatiblities.
rdb пре 6 година
родитељ
комит
63d2992d5e

+ 37 - 0
panda/src/egg/eggVertexUV.I

@@ -97,6 +97,14 @@ has_tangent() const {
   return (_flags & F_has_tangent) != 0;
   return (_flags & F_has_tangent) != 0;
 }
 }
 
 
+/**
+ *
+ */
+INLINE bool EggVertexUV::
+has_tangent4() const {
+  return (_flags & F_has_tangent4) != 0;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -106,6 +114,19 @@ get_tangent() const {
   return _tangent;
   return _tangent;
 }
 }
 
 
+/**
+ *
+ */
+INLINE LVecBase4d EggVertexUV::
+get_tangent4() const {
+  LVecBase4d tangent4(_tangent, 1.0);
+  nassertr_always(has_tangent(), tangent4);
+  if (_flags & F_flip_computed_binormal) {
+    tangent4[3] = -1.0;
+  }
+  return tangent4;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -113,6 +134,22 @@ INLINE void EggVertexUV::
 set_tangent(const LNormald &tangent) {
 set_tangent(const LNormald &tangent) {
   _tangent = tangent;
   _tangent = tangent;
   _flags |= F_has_tangent;
   _flags |= F_has_tangent;
+  _flags &= ~(F_has_tangent4 | F_flip_computed_binormal);
+}
+
+/**
+ * Sets the tangent vector, along with a fourth parameter that is multiplied
+ * with the result of cross(normal, tangent) when computing the binormal.
+ */
+INLINE void EggVertexUV::
+set_tangent4(const LVecBase4d &tangent) {
+  _tangent = tangent.get_xyz();
+  _flags |= F_has_tangent4 | F_has_tangent;
+  if (tangent[3] < 0.0) {
+    _flags |= F_flip_computed_binormal;
+  } else {
+    _flags &= ~F_flip_computed_binormal;
+  }
 }
 }
 
 
 /**
 /**

+ 4 - 1
panda/src/egg/eggVertexUV.cxx

@@ -145,7 +145,10 @@ write(std::ostream &out, int indent_level) const {
     } else {
     } else {
       indent(out, indent_level+2) << get_uv() << "\n";
       indent(out, indent_level+2) << get_uv() << "\n";
     }
     }
-    if (has_tangent()) {
+    if (has_tangent4()) {
+      indent(out, indent_level + 2)
+        << "<Tangent> { " << get_tangent4() << " }\n";
+    } else if (has_tangent()) {
       indent(out, indent_level + 2)
       indent(out, indent_level + 2)
         << "<Tangent> { " << get_tangent() << " }\n";
         << "<Tangent> { " << get_tangent() << " }\n";
     }
     }

+ 7 - 0
panda/src/egg/eggVertexUV.h

@@ -45,8 +45,11 @@ PUBLISHED:
   INLINE void set_uvw(const LTexCoord3d &texCoord);
   INLINE void set_uvw(const LTexCoord3d &texCoord);
 
 
   INLINE bool has_tangent() const;
   INLINE bool has_tangent() const;
+  INLINE bool has_tangent4() const;
   INLINE const LNormald &get_tangent() const;
   INLINE const LNormald &get_tangent() const;
+  INLINE LVecBase4d get_tangent4() const;
   INLINE void set_tangent(const LNormald &tangent);
   INLINE void set_tangent(const LNormald &tangent);
+  INLINE void set_tangent4(const LVecBase4d &tangent);
   INLINE void clear_tangent();
   INLINE void clear_tangent();
 
 
   INLINE bool has_binormal() const;
   INLINE bool has_binormal() const;
@@ -69,6 +72,10 @@ private:
     F_has_tangent   = 0x001,
     F_has_tangent   = 0x001,
     F_has_binormal  = 0x002,
     F_has_binormal  = 0x002,
     F_has_w         = 0x004,
     F_has_w         = 0x004,
+    F_has_tangent4  = 0x008,
+
+    // Only defined temporarily as we can't add a float to this class in 1.10.
+    F_flip_computed_binormal = 0x010,
   };
   };
 
 
   int _flags;
   int _flags;

+ 8 - 0
panda/src/egg/parser.yxx

@@ -1103,6 +1103,14 @@ vertex_uv_body:
   } else {
   } else {
     DCAST(EggVertexUV, egg_stack.back())->set_tangent(LNormald($4, $5, $6));
     DCAST(EggVertexUV, egg_stack.back())->set_tangent(LNormald($4, $5, $6));
   }
   }
+}
+        | vertex_uv_body TANGENT '{' real real real real '}'
+{
+  if (DCAST(EggVertexUV, egg_stack.back())->has_tangent()) {
+    eggyywarning("Ignoring repeated tangent");
+  } else {
+    DCAST(EggVertexUV, egg_stack.back())->set_tangent4(LVecBase4d($4, $5, $6, $7));
+  }
 }
 }
         | vertex_uv_body BINORMAL '{' real real real '}'
         | vertex_uv_body BINORMAL '{' real real real '}'
 {
 {

+ 84 - 0
tests/egg/test_egg_vertex_uv.py

@@ -0,0 +1,84 @@
+import pytest
+from panda3d import core
+
+# Skip these tests if we can't import egg.
+egg = pytest.importorskip("panda3d.egg")
+
+
+def read_egg_vertex(string):
+    """Reads an EggVertex from a string."""
+    data = "<VertexPool> pool { <Vertex> 1 { %s } }" % (string)
+    stream = core.StringStream(data.encode('utf-8'))
+    data = egg.EggData()
+    assert data.read(stream)
+    pool, = data.get_children()
+    return pool.get_vertex(1)
+
+
+def test_egg_vertex_uv_empty():
+    vertex = read_egg_vertex("""
+        0 0 0
+        <UV> {
+            0 0
+        }
+    """)
+
+    obj = vertex.get_uv_obj("")
+    assert not obj.has_tangent()
+    assert not obj.has_tangent4()
+
+    assert '<Tangent>' not in str(obj)
+
+
+def test_egg_vertex_tangent():
+    vertex = read_egg_vertex("""
+        0 0 0
+        <UV> {
+            0 0
+            <Tangent> { 2 3 4 }
+        }
+    """)
+
+    obj = vertex.get_uv_obj("")
+    assert obj.has_tangent()
+    assert not obj.has_tangent4()
+    assert obj.get_tangent() == (2, 3, 4)
+    assert obj.get_tangent4() == (2, 3, 4, 1)
+
+    assert '{ 2 3 4 }' in str(obj)
+
+
+def test_egg_vertex_tangent4_pos():
+    vertex = read_egg_vertex("""
+        0 0 0
+        <UV> {
+            0 0
+            <Tangent> { 2 3 4 1 }
+        }
+    """)
+
+    obj = vertex.get_uv_obj("")
+    assert obj.has_tangent()
+    assert obj.has_tangent4()
+    assert obj.get_tangent() == (2, 3, 4)
+    assert obj.get_tangent4() == (2, 3, 4, 1)
+
+    assert '{ 2 3 4 1 }' in str(obj)
+
+
+def test_egg_vertex_tangent4_neg():
+    vertex = read_egg_vertex("""
+        0 0 0
+        <UV> {
+            0 0
+            <Tangent> { 2 3 4 -1 }
+        }
+    """)
+
+    obj = vertex.get_uv_obj("")
+    assert obj.has_tangent()
+    assert obj.has_tangent4()
+    assert obj.get_tangent() == (2, 3, 4)
+    assert obj.get_tangent4() == (2, 3, 4, -1)
+
+    assert '{ 2 3 4 -1 }' in str(obj)