From 63d2992d5ed36be5a5273a96237814e953e36b04 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 5 Feb 2019 00:30:54 +0100 Subject: [PATCH] egg: add ability to read 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. --- panda/src/egg/eggVertexUV.I | 37 +++++++++++++++ panda/src/egg/eggVertexUV.cxx | 5 +- panda/src/egg/eggVertexUV.h | 7 +++ panda/src/egg/parser.yxx | 8 ++++ tests/egg/test_egg_vertex_uv.py | 84 +++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/egg/test_egg_vertex_uv.py diff --git a/panda/src/egg/eggVertexUV.I b/panda/src/egg/eggVertexUV.I index 05f6f8609f..eef97e52e3 100644 --- a/panda/src/egg/eggVertexUV.I +++ b/panda/src/egg/eggVertexUV.I @@ -97,6 +97,14 @@ has_tangent() const { 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; } +/** + * + */ +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) { _tangent = 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; + } } /** diff --git a/panda/src/egg/eggVertexUV.cxx b/panda/src/egg/eggVertexUV.cxx index 49a3c39ace..bcc0c1055e 100644 --- a/panda/src/egg/eggVertexUV.cxx +++ b/panda/src/egg/eggVertexUV.cxx @@ -145,7 +145,10 @@ write(std::ostream &out, int indent_level) const { } else { indent(out, indent_level+2) << get_uv() << "\n"; } - if (has_tangent()) { + if (has_tangent4()) { + indent(out, indent_level + 2) + << " { " << get_tangent4() << " }\n"; + } else if (has_tangent()) { indent(out, indent_level + 2) << " { " << get_tangent() << " }\n"; } diff --git a/panda/src/egg/eggVertexUV.h b/panda/src/egg/eggVertexUV.h index 2ab0447639..e729f28101 100644 --- a/panda/src/egg/eggVertexUV.h +++ b/panda/src/egg/eggVertexUV.h @@ -45,8 +45,11 @@ PUBLISHED: INLINE void set_uvw(const LTexCoord3d &texCoord); INLINE bool has_tangent() const; + INLINE bool has_tangent4() const; INLINE const LNormald &get_tangent() const; + INLINE LVecBase4d get_tangent4() const; INLINE void set_tangent(const LNormald &tangent); + INLINE void set_tangent4(const LVecBase4d &tangent); INLINE void clear_tangent(); INLINE bool has_binormal() const; @@ -69,6 +72,10 @@ private: F_has_tangent = 0x001, F_has_binormal = 0x002, 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; diff --git a/panda/src/egg/parser.yxx b/panda/src/egg/parser.yxx index 1ffaa3a078..6125ead479 100644 --- a/panda/src/egg/parser.yxx +++ b/panda/src/egg/parser.yxx @@ -1103,6 +1103,14 @@ vertex_uv_body: } else { 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 '}' { diff --git a/tests/egg/test_egg_vertex_uv.py b/tests/egg/test_egg_vertex_uv.py new file mode 100644 index 0000000000..e2f1deeebf --- /dev/null +++ b/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 = " pool { 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 + { + 0 0 + } + """) + + obj = vertex.get_uv_obj("") + assert not obj.has_tangent() + assert not obj.has_tangent4() + + assert '' not in str(obj) + + +def test_egg_vertex_tangent(): + vertex = read_egg_vertex(""" + 0 0 0 + { + 0 0 + { 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 + { + 0 0 + { 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 + { + 0 0 + { 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)