Include only tangent in mesh data and calculate binormal on the fly
authorMikko Rasa <tdb@tdb.fi>
Tue, 13 Apr 2021 10:22:02 +0000 (13:22 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 13 Apr 2021 10:22:02 +0000 (13:22 +0300)
This saves one vertex attribute.

16 files changed:
blender/io_mspgl/export_mesh.py
blender/io_mspgl/mesh.py
blender/io_mspgl/properties.py
shaderlib/common.glsl
shaderlib/msp_interface.glsl
source/builders/box.cpp
source/builders/capsule.cpp
source/builders/cylinder.cpp
source/builders/geometrybuilder.cpp
source/builders/geometrybuilder.h
source/builders/grid.cpp
source/builders/sphere.cpp
source/builders/vertexbuilder.h
source/core/vertexarray.cpp
source/core/vertexformat.cpp
source/core/vertexformat.h

index 68d93cbc525b9b3872e209c58a33bb7548ca0cba..16f9514a97402443cadd8bb12d2ce1ca6e2170ee 100644 (file)
@@ -73,9 +73,8 @@ class MeshExporter:
                                        st.append(Token("TEXCOORD"+size))
                                else:
                                        st.append(Token("TEXCOORD{}_{}".format(size, u.unit)))
-                       if mesh.tbn_vecs:
+                       if mesh.tangent_vecs:
                                st.append(Token("TANGENT3"))
-                               st.append(Token("BINORMAL3"))
                if mesh.vertex_groups:
                        st.append(Token("GROUP{}".format(mesh.max_groups_per_vertex)))
                        st.append(Token("WEIGHT{}".format(mesh.max_groups_per_vertex)))
@@ -85,7 +84,6 @@ class MeshExporter:
                color = None
                uvs = [None]*len(mesh.uv_layers)
                tan = None
-               bino = None
                group = None
                weight = None
                for v in mesh.vertices:
@@ -102,13 +100,10 @@ class MeshExporter:
                                        else:
                                                st.sub.append(Statement("multitexcoord", u.unit, *v.uvs[i]))
                                        uvs[i] = v.uvs[i]
-                       if mesh.tbn_vecs:
+                       if mesh.tangent_vecs:
                                if v.tan!=tan:
                                        st.sub.append(Statement("tangent", *v.tan))
                                        tan = v.tan
-                               if v.bino!=bino:
-                                       st.sub.append(Statement("binormal", *v.bino))
-                                       bino = v.bino
                        if mesh.vertex_groups:
                                v_group = [g.group for g in v.groups]
                                v_weight = [g.weight for g in v.groups]
index 754e6ffc2d35460c0e474e7fc02e70b3e62c9568..9741b8dd916f28495d3e25cde8fd64e767a7d118 100644 (file)
@@ -48,11 +48,9 @@ class Vertex:
                if vertex.__class__==Vertex:
                        self.uvs = vertex.uvs[:]
                        self.tan = vertex.tan
-                       self.bino = vertex.bino
                else:
                        self.uvs = []
                        self.tan = None
-                       self.bino = None
                self.index = vertex.index
                self.co = mathutils.Vector(vertex.co)
                self.normal = mathutils.Vector(vertex.normal)
@@ -160,8 +158,8 @@ class Mesh:
                self.winding_test = mesh.winding_test
                self.smoothing = mesh.smoothing
                self.use_uv = mesh.use_uv
-               self.tbn_vecs = mesh.tbn_vecs
-               self.tbn_uvtex = mesh.tbn_uvtex
+               self.tangent_vecs = mesh.tangent_vecs
+               self.tangent_uvtex = mesh.tangent_uvtex
                self.vertex_groups = mesh.vertex_groups
 
                # Clone basic data
@@ -447,31 +445,31 @@ class Mesh:
                prog_count = len(self.uv_layers)
                prog_step = 0
 
-               # Split by the UV layer used for TBN vectors first so connectivity
-               # remains intact for TBN vector computation
-               tbn_layer_index = -1
-               if self.tbn_vecs:
-                       if self.tbn_uvtex:
+               # Split by the UV layer used for tangent vectors first so connectivity
+               # remains intact for tangent vector computation
+               tangent_layer_index = -1
+               if self.tangent_vecs:
+                       if self.tangent_uvtex:
                                uv_names = [u.name for u in self.uv_layers]
-                               if self.tbn_uvtex in uv_names:
-                                       tbn_layer_index = uv_names.index(self.tbn_uvtex)
+                               if self.tangent_uvtex in uv_names:
+                                       tangent_layer_index = uv_names.index(self.tangent_uvtex)
                        elif self.uv_layers[0].unit==0:
-                               tbn_layer_index = 0
+                               tangent_layer_index = 0
 
-                       if tbn_layer_index>=0:
+                       if tangent_layer_index>=0:
                                prog_count += 1
-                               progress.push_task_slice("Computing TBN", 0, prog_count)
-                               self.split_vertices(self.find_uv_group, progress, tbn_layer_index)
-                               progress.set_task_slice(self.tbn_uvtex, 1, prog_count)
-                               self.compute_tbn(tbn_layer_index, progress)
+                               progress.push_task_slice("Computing tangents", 0, prog_count)
+                               self.split_vertices(self.find_uv_group, progress, tangent_layer_index)
+                               progress.set_task_slice(self.tangent_uvtex, 1, prog_count)
+                               self.compute_tangents(tangent_layer_index, progress)
                                progress.pop_task()
                                prog_step = 2
                        else:
-                               raise Exception("TBN UV layer not found")
+                               raise Exception("Tangent UV layer not found")
 
                # Split by the remaining UV layers
                for i, u in enumerate(self.uv_layers):
-                       if i==tbn_layer_index:
+                       if i==tangent_layer_index:
                                continue
 
                        progress.push_task_slice(u.name, prog_step, prog_count)
@@ -620,14 +618,11 @@ class Mesh:
 
                        progress.set_progress(i/len(self.vertices))
 
-       def compute_tbn(self, index, progress):
-               # This function is called at an early stage during UV preparation when
-               # face UVs are not available yet
+       def compute_tangents(self, index, progress):
                layer_uvs = self.uv_layers[index].uvs
 
                for i, v in enumerate(self.vertices):
                        v.tan = mathutils.Vector()
-                       v.bino = mathutils.Vector()
                        for f in v.faces:
                                vi = f.pivot_vertex(v)
                                uv0 = layer_uvs[f.loop_indices[vi[0]]]
@@ -643,12 +638,9 @@ class Mesh:
                                if div:
                                        mul = edge1.angle(edge2)/div
                                        v.tan += (edge1*dv2-edge2*dv1)*mul
-                                       v.bino += (edge2*du1-edge1*du2)*mul
 
                        if v.tan.length:
                                v.tan.normalize()
-                       if v.bino.length:
-                               v.bino.normalize()
 
                        progress.set_progress(i/len(self.vertices))
 
@@ -817,8 +809,8 @@ def create_mesh_from_object(context, obj, progress, *, material_atlas=None):
                bmesh.vertex_groups = o.data.vertex_groups
                bmesh.max_groups_per_vertex = o.data.max_groups_per_vertex
                bmesh.use_uv = o.data.use_uv
-               bmesh.tbn_vecs = o.data.tbn_vecs
-               bmesh.tbn_uvtex = o.data.tbn_uvtex
+               bmesh.tangent_vecs = o.data.tangent_vecs
+               bmesh.tangent_uvtex = o.data.tangent_uvtex
 
                me = Mesh(bmesh)
                me.transform(m)
index baf9ac95c6105c5252e796f326f4d0beccf353fa..0d5a6d46e044f4374c231761997753b3ea24e908 100644 (file)
@@ -30,8 +30,8 @@ class MspGLMeshProperties(bpy.types.Panel):
                col = self.layout.column()
                col.label(text="Texturing")
                col.prop(mesh, "use_uv")
-               col.prop(mesh, "tbn_vecs")
-               col.prop(mesh, "tbn_uvtex")
+               col.prop(mesh, "tangent_vecs")
+               col.prop(mesh, "tangent_uvtex")
 
 class MspGLObjectProperties(bpy.types.Panel):
        bl_idname = "OBJECT_PT_mspgl_properties"
@@ -147,8 +147,8 @@ def register_properties():
                items=(("NONE", "None", "Ignore all UV coordinates"),
                        ("UNIT0", "Unit 0", "Use UV coordinates for unit 0"),
                        ("ALL", "All", "Use all UV coordinates")))
-       bpy.types.Mesh.tbn_vecs = bpy.props.BoolProperty(name="TBN vectors", description="Compute tangent and binormal vectors for vertices", default=False)
-       bpy.types.Mesh.tbn_uvtex = bpy.props.StringProperty(name="TBN UV layer", description="UV layer to use as basis for TBN vectors", default="")
+       bpy.types.Mesh.tangent_vecs = bpy.props.BoolProperty(name="Tangent vectors", description="Compute tangent vectors for vertices", default=False)
+       bpy.types.Mesh.tangent_uvtex = bpy.props.StringProperty(name="Tangent UV layer", description="UV layer to use as basis for tangent vectors", default="")
 
        bpy.types.Object.compound = bpy.props.BoolProperty(name="Compound with parent", description="Join this object to its parent when exporting")
        bpy.types.Object.lod_for_parent = bpy.props.BoolProperty(name="LoD for parent", description="This object is a level of detail for its parent")
index 54d66e602ed496d597982dce894ee62399f4f451..8bc652fcd0a509cf9076cfe761c498c75d99e86a 100644 (file)
@@ -42,7 +42,7 @@ void standard_transform()
 
        out vec3 eye_normal = normal_tf*get_vertex_normal();
        vec3 eye_tangent = normal_tf*tangent;
-       vec3 eye_binormal = normal_tf*binormal;
+       vec3 eye_binormal = cross(eye_normal, eye_tangent);
        out mat3 eye_tbn_matrix = mat3(eye_tangent, eye_binormal, eye_normal);
 
        out vec3 eye_look_dir = normalize(eye_vertex.xyz);
index b86d09bb32e4a5cdc3d49423f5336cf9d896cae1..fbbcec3b95a70d45bee3262b77d687340621d756 100644 (file)
@@ -42,11 +42,10 @@ layout(location=0) in vec4 vertex;
 layout(location=1) in vec4 color;
 layout(location=2) in vec3 normal;
 layout(location=3) in vec3 tangent;
-layout(location=4) in vec3 binormal;
-layout(location=7) in vec4 texcoord;
-layout(location=8) in vec4 texcoord1;
-layout(location=9) in vec4 texcoord2;
-layout(location=10) in vec4 texcoord3;
+layout(location=6) in vec4 texcoord;
+layout(location=7) in vec4 texcoord1;
+layout(location=8) in vec4 texcoord2;
+layout(location=9) in vec4 texcoord3;
 layout(location=13) in vec4 instance_transform[3];
 
 #pragma MSP stage(fragment)
index 46f1b48ed7bfc315a23a221134544adcccf5c19e..1435c976607750294ff26ae885298b9a6ed1f848 100644 (file)
@@ -36,17 +36,14 @@ void BoxBuilder::build(PrimitiveBuilder &builder) const
 void BoxBuilder::build_face(PrimitiveBuilder &builder, const Vector3 &o, const Vector3 &s1, const Vector3 &s2) const
 {
        float l1 = 1, l2 = 1;
-       if(generate_tbn || tex_fit!=STRETCH)
+       if(generate_tan || tex_fit!=STRETCH)
        {
                l1 = s1.norm();
                l2 = s2.norm();
        }
 
-       if(generate_tbn)
-       {
+       if(generate_tan)
                builder.tangent(s1/l1);
-               builder.binormal(s2/l2);
-       }
 
        float u_size = 1;
        float v_size = 1;
index 65a18eb3e2cbf6e8915d4c239b4a4460dc4b4eb3..a14e4ee5d888ae335fc92857dd351e23297d7a77 100644 (file)
@@ -43,11 +43,8 @@ void CapsuleBuilder::build(PrimitiveBuilder &builder) const
                        float sc = cos(sa);
                        float ss = sin(sa);
                        builder.normal(rs*sc, rs*ss, -rc);
-                       if(generate_tbn)
-                       {
+                       if(generate_tan)
                                builder.tangent(-ss, sc, 0);
-                               builder.binormal(rc*sc, rc*ss, rs);
-                       }
                        builder.texcoord(j*u_scale, v);
                        builder.vertex(rs*sc*radius, rs*ss*radius, cz-rc*radius);
                }
index 901a0f4b43cf057872a752960e30678a2a980b24..e3a8342ce27e58f60de23827bebbe40f2972cd7e 100644 (file)
@@ -19,14 +19,12 @@ CylinderBuilder::CylinderBuilder(float r, float l, unsigned s):
 
 void CylinderBuilder::build(PrimitiveBuilder &builder) const
 {
-       if(generate_tbn)
-               builder.binormal(0, 1, 0);
        for(unsigned i=0; i<2; ++i)
        {
                float z = (i-0.5)*length;
                builder.normal(0, 0, i*2.0-1.0);
                builder.texcoord(0.5, 0.5);
-               if(generate_tbn)
+               if(generate_tan)
                        builder.tangent((i ? 1 : -1), 0, 0);
                builder.vertex(0, 0, z);
                for(unsigned j=0; j<segments; ++j)
@@ -43,8 +41,6 @@ void CylinderBuilder::build(PrimitiveBuilder &builder) const
        float v_scale = 1;
        adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, length);
 
-       if(generate_tbn)
-               builder.binormal(0, 0, 1);
        for(unsigned i=0; i<2; ++i)
        {
                float z = (i-0.5)*length;
@@ -55,7 +51,7 @@ void CylinderBuilder::build(PrimitiveBuilder &builder) const
                        float s = sin(a);
                        builder.normal(c, s, 0);
                        builder.texcoord(j*u_scale, i*v_scale);
-                       if(generate_tbn)
+                       if(generate_tan)
                                builder.tangent(-s, c, 0);
                        builder.vertex(radius*c, radius*s, z);
                }
index 729b40facc1709ddecc794aa2637c65ac1bdd391..8e0ae53bbf2dda7f842373c5f8c6f1c72b97d81d 100644 (file)
@@ -5,13 +5,13 @@ namespace Msp {
 namespace GL {
 
 GeometryBuilder::GeometryBuilder():
-       generate_tbn(false),
+       generate_tan(false),
        tex_fit(STRETCH)
 { }
 
-GeometryBuilder &GeometryBuilder::tbn(bool t)
+GeometryBuilder &GeometryBuilder::tangents(bool t)
 {
-       generate_tbn = t;
+       generate_tan = t;
        return *this;
 }
 
index 40bcd13e6b37b504d3c22ad3780ccce7a9b521b1..87dd4e22bfcbb060a6d38095f85b0fbfdb64358a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MSP_GL_GEOMETRYBUILDER_H_
 #define MSP_GL_GEOMETRYBUILDER_H_
 
+#include <msp/core/attributes.h>
+
 namespace Msp {
 namespace GL {
 
@@ -18,13 +20,14 @@ public:
        };
 
 protected:
-       bool generate_tbn;
+       bool generate_tan;
        TextureFit tex_fit;
 
        GeometryBuilder();
 
 public:
-       GeometryBuilder &tbn(bool = true);
+       DEPRECATED GeometryBuilder &tbn(bool t = true) { return tangents(t); }
+       GeometryBuilder &tangents(bool = true);
        GeometryBuilder &texture_fit(TextureFit);
 protected:
        void adjust_texture_scale(float &, float &, float, float) const;
index 3f4d5e2fddb0fa11c9ab99f64f906fc3ecbaeece..d812a2c2558656212f086cffe96ef11564d2bc25 100644 (file)
@@ -75,11 +75,8 @@ void GridBuilder::build(PrimitiveBuilder &builder) const
        adjust_texture_scale(u_scale, v_scale, sqrt(l1_sq), l2);
 
        builder.normal(norm.x, norm.y, norm.z);
-       if(generate_tbn)
-       {
+       if(generate_tan)
                builder.tangent(side1);
-               builder.binormal(binorm);
-       }
 
        for(unsigned j=0; j<=v_div; ++j)
        {
index dd27fad40e28cc1608ad9699b121d1c4af0f0ffb..f7e06eb7041de62564329a807236a3db799e5ae0 100644 (file)
@@ -43,11 +43,8 @@ void UvSphereBuilder::build(PrimitiveBuilder &builder) const
 
                        builder.normal(cv*cu, cv*su, sv);
                        builder.texcoord(j*u_scale, i*v_scale);
-                       if(generate_tbn)
-                       {
+                       if(generate_tan)
                                builder.tangent(-su, cu, 0);
-                               builder.binormal(-sv*cu, -sv*su, cv);
-                       }
                        builder.vertex(cv*cu*radius, cv*su*radius, sv*radius);
                }
        }
index 5c29734607a9775e123ebef26446293cac6f01e3..82827cb4e56bed2cb10c47d7562354f8812771a6 100644 (file)
@@ -89,11 +89,11 @@ public:
        void tangent(const Vector3 &t)
        { attrib(get_attribute_semantic(TANGENT3), mtx*Vector4(t.x, t.y, t.z, 0)); }
 
-       void binormal(float x, float y, float z)
-       { binormal(Vector3(x, y, z)); }
+       DEPRECATED void binormal(float, float, float)
+       { }
 
-       void binormal(const Vector3 &b)
-       { attrib(get_attribute_semantic(BINORMAL3), mtx*Vector4(b.x, b.y, b.z, 0)); }
+       DEPRECATED void binormal(const Vector3 &)
+       { }
 
        void texcoord(float s)
        { texcoord(s, 0, 0, 1); }
index da868c7963f83a81efed4b08bdb10cb118cf7c80..347e42595a1387bf7630a87344a6dc96f7425ac3 100644 (file)
@@ -74,8 +74,6 @@ VertexArray::Loader::Loader(VertexArray &a):
        add("generic", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::generic));
        add("generic", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::generic));
        add("generic", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::generic));
-       add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
-       add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
        add("group", static_cast<void (Loader::*)(int)>(&Loader::group));
        add("group", static_cast<void (Loader::*)(int, int)>(&Loader::group));
        add("group", static_cast<void (Loader::*)(int, int, int)>(&Loader::group));
@@ -104,8 +102,13 @@ VertexArray::Loader::Loader(VertexArray &a):
        add("generic2",  static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::generic));
        add("generic3",  static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::generic));
        add("generic4",  static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::generic));
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        add("tangent3",  static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
        add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
+       add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
+       add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
+#pragma GCC diagnostic pop
 }
 
 } // namespace GL
index 908da99278defda2530f699aef308a90d116e99e..e529f4eb2632770e91ae68b3bd221cc913ca0382 100644 (file)
@@ -1,4 +1,5 @@
 #include <algorithm>
+#include <msp/io/print.h>
 #include <msp/strings/format.h>
 #include <msp/strings/lexicalcast.h>
 #include <msp/strings/utils.h>
@@ -141,7 +142,10 @@ void operator>>(const LexicalConverter &conv, VertexAttribute &a)
        else if(str=="TANGENT3")
                a = TANGENT3;
        else if(str=="BINORMAL3")
-               a = BINORMAL3;
+       {
+               IO::print(IO::cerr, "BINORMAL3 attribute is deprecated\n");
+               a = make_indexed_attribute(GENERIC3, 5);
+       }
        else if(!convert_attribute(str, "VERTEX", 2, 4, a, VERTEX2) &&
                !convert_attribute(str, "GROUP", 1, 4, a, GROUP1) &&
                !convert_attribute(str, "WEIGHT", 1, 4, a, WEIGHT1) &&
index 0dbde9f9a9be825247a366cb2246fae612d8c1b3..c7a2fcf166ef28d468289891db3ca9a82ab31e9b 100644 (file)
@@ -26,20 +26,19 @@ enum VertexAttribute
        COLOR4_FLOAT,
        NORMAL3 = 18,
        TANGENT3 = 26,
-       BINORMAL3 = 34,
-       GROUP1 = 40,
+       GROUP1 = 32,
        GROUP2,
        GROUP3,
        GROUP4,
-       WEIGHT1 = 48,
+       WEIGHT1 = 40,
        WEIGHT2,
        WEIGHT3,
        WEIGHT4,
-       TEXCOORD1 = 56,
+       TEXCOORD1 = 48,
        TEXCOORD2,
        TEXCOORD3,
        TEXCOORD4,
-       GENERIC1 = 88,
+       GENERIC1 = 80,
        GENERIC2,
        GENERIC3,
        GENERIC4,