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.
This commit is contained in:
rdb 2019-02-05 00:30:54 +01:00
parent 2afd604c9d
commit 63d2992d5e
5 changed files with 140 additions and 1 deletions

View File

@ -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;
}
}
/**

View File

@ -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)
<< "<Tangent> { " << get_tangent4() << " }\n";
} else if (has_tangent()) {
indent(out, indent_level + 2)
<< "<Tangent> { " << get_tangent() << " }\n";
}

View File

@ -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;

View File

@ -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 '}'
{

View File

@ -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)