]> git.tdb.fi Git - libs/gl.git/commitdiff
Fix and improve vertex group support
authorMikko Rasa <tdb@tdb.fi>
Sun, 28 Mar 2021 09:46:33 +0000 (12:46 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 28 Mar 2021 09:46:45 +0000 (12:46 +0300)
Some parts of the export code had gotten out of sync in 306be12.

Groups and weights now have dedicated attributes instead of using an
arbitrary generic attribute.  They're also separate attributes,
allowing up to four groups per vertex.

blender/io_mspgl/export_mesh.py
blender/io_mspgl/mesh.py
source/builders/vertexbuilder.h
source/core/vertexarray.cpp
source/core/vertexformat.cpp
source/core/vertexformat.h

index 0d27a71cdf6c2b1e57121a2e064bec4d5067b9bb..68d93cbc525b9b3872e209c58a33bb7548ca0cba 100644 (file)
@@ -77,7 +77,8 @@ class MeshExporter:
                                st.append(Token("TANGENT3"))
                                st.append(Token("BINORMAL3"))
                if mesh.vertex_groups:
-                       st.append(Token("GENERIC{}_0".format(mesh.max_groups_per_vertex*2)))
+                       st.append(Token("GROUP{}".format(mesh.max_groups_per_vertex)))
+                       st.append(Token("WEIGHT{}".format(mesh.max_groups_per_vertex)))
                st.append(Token("VERTEX3"))
 
                normal = None
@@ -86,6 +87,7 @@ class MeshExporter:
                tan = None
                bino = None
                group = None
+               weight = None
                for v in mesh.vertices:
                        if v.normal!=normal:
                                st.sub.append(Statement("normal", *v.normal))
@@ -108,13 +110,14 @@ class MeshExporter:
                                        st.sub.append(Statement("binormal", *v.bino))
                                        bino = v.bino
                        if mesh.vertex_groups:
-                               group_attr = [(group_index_map[g.group], g.weight*v.group_weight_scale) for g in v.groups[:mesh.max_groups_per_vertex]]
-                               while len(group_attr)<mesh.max_groups_per_vertex:
-                                       group_attr.append((0, 0.0))
-                               group_attr = list(itertools.chain(*group_attr))
-                               if group_attr!=group:
-                                       st.sub.append(Statement("generic", 0, *group_attr))
-                                       group = group_attr
+                               v_group = [g.group for g in v.groups]
+                               v_weight = [g.weight for g in v.groups]
+                               if v_group!=group:
+                                       st.sub.append(Statement("group", *v_group))
+                                       group = v_group
+                               if v_weight!=weight:
+                                       st.sub.append(Statement("weight", *v_weight))
+                                       weight = v_weight
                        st.sub.append(Statement("vertex", *v.co))
 
                statements.append(st)
index da5e76aaf34ed259d48ff5f3a0b872c32f36cdda..d9ae6b760ff545c8043269bb9e120b597f8b05f7 100644 (file)
@@ -70,8 +70,12 @@ class Vertex:
 
 class VertexGroup:
        def __init__(self, group):
-               self.group = group.group
-               self.weight = group.weight
+               if group:
+                       self.group = group.group
+                       self.weight = group.weight
+               else:
+                       self.group = 0
+                       self.weight = 0.0
 
 
 class Face:
@@ -162,8 +166,9 @@ class Mesh:
 
                # Clone basic data
                self.vertices = [Vertex(v) for v in mesh.vertices]
-               for v in self.vertices:
-                       v.groups = [VertexGroup(g) for g in v.groups]
+               if self.vertex_groups:
+                       for v in self.vertices:
+                               v.groups = [VertexGroup(g) for g in v.groups]
 
                self.faces = [Face(f) for f in mesh.polygons]
                self.edges = [Edge(e) for e in mesh.edges]
@@ -172,6 +177,7 @@ class Mesh:
 
                self.use_auto_smooth = mesh.use_auto_smooth
                self.auto_smooth_angle = mesh.auto_smooth_angle
+               self.max_groups_per_vertex = mesh.max_groups_per_vertex
 
                # Clone only the desired UV layers
                if mesh.use_uv=='NONE' or not mesh.uv_layers:
@@ -371,6 +377,9 @@ class Mesh:
                progress.pop_task()
 
        def prepare_vertex_groups(self, obj):
+               if not self.vertex_groups:
+                       return
+
                for v in self.vertices:
                        if v.groups:
                                weight_sum = sum(g.weight for g in v.groups)
@@ -378,6 +387,8 @@ class Mesh:
                                weight_scale = weight_sum/sum(g.weight for g in v.groups)
                                for g in v.groups:
                                        g.weight *= weight_scale
+                       while len(v.groups)<self.max_groups_per_vertex:
+                               v.groups.append(VertexGroup(None))
 
                if obj.parent and obj.parent.type=="ARMATURE":
                        armature = obj.parent.data
index b5278045baa0ec4227cea6798436d01b879d468a..5c29734607a9775e123ebef26446293cac6f01e3 100644 (file)
@@ -140,6 +140,30 @@ public:
        void color(const Color &c)
        { attrib(get_attribute_semantic(COLOR4_FLOAT), Vector4(c.r, c.g, c.b, c.a)); }
 
+       void group(int g0)
+       { group(g0, 0, 0, 0); }
+
+       void group(int g0, int g1)
+       { group(g0, g1, 0, 0); }
+
+       void group(int g0, int g1, int g2)
+       { group(g0, g1, g2, 0); }
+
+       void group(int g0, int g1, int g2, int g3)
+       { attrib(get_attribute_semantic(GROUP4), Vector4(g0, g1, g2, g3)); }
+
+       void weight(float w0)
+       { weight(w0, 0, 0, 0); }
+
+       void weight(float w0, float w1)
+       { weight(w0, w1, 0, 0); }
+
+       void weight(float w0, float w1, float w2)
+       { weight(w0, w1, w2, 0); }
+
+       void weight(float w0, float w1, float w2, float w3)
+       { attrib(get_attribute_semantic(WEIGHT4), Vector4(w0, w1, w2, w3)); }
+
        void generic(unsigned i, float x)
        { generic(i, x, 0, 0, 1); }
 
index 712e76e6011c2ce8aec1e70668d4e8f0ec76f21b..67a90ef7e2ea6810de672903d64a44674d35fe67 100644 (file)
@@ -76,6 +76,14 @@ VertexArray::Loader::Loader(VertexArray &a):
        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));
+       add("group", static_cast<void (Loader::*)(int, int, int, int)>(&Loader::group));
+       add("weight", static_cast<void (Loader::*)(float)>(&Loader::weight));
+       add("weight", static_cast<void (Loader::*)(float, float)>(&Loader::weight));
+       add("weight", static_cast<void (Loader::*)(float, float, float)>(&Loader::weight));
+       add("weight", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::weight));
 
        add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
        add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
index 5d026e2ebbbfa919e6aa0369ed19d07f867b278e..2ce02e2edc693189ee0a84f50426d40dc8c6b0ba 100644 (file)
@@ -120,6 +120,10 @@ void operator>>(const LexicalConverter &conv, VertexAttribute &a)
                a = TANGENT3;
        else if(str=="BINORMAL3")
                a = BINORMAL3;
+       else if(str.size()==6 && !str.compare(0, 5, "GROUP") && str[5]>='1' && str[5]<='4')
+               a = static_cast<VertexAttribute>(GROUP1+(str[5]-'1'));
+       else if(str.size()==7 && !str.compare(0, 6, "WEIGHT") && str[6]>='1' && str[6]<='4')
+               a = static_cast<VertexAttribute>(WEIGHT1+(str[6]-'1'));
        else if(str.size()>=9 && !str.compare(0, 8, "TEXCOORD") && str[8]>='1' && str[8]<='4')
        {
                if(str.size()==9)
index 93794c353cafcb24027253ac2491cf59ef6e731b..0dbde9f9a9be825247a366cb2246fae612d8c1b3 100644 (file)
@@ -27,7 +27,14 @@ enum VertexAttribute
        NORMAL3 = 18,
        TANGENT3 = 26,
        BINORMAL3 = 34,
-       // Attributes 5 and 6 reserved for vertex groups and weights
+       GROUP1 = 40,
+       GROUP2,
+       GROUP3,
+       GROUP4,
+       WEIGHT1 = 48,
+       WEIGHT2,
+       WEIGHT3,
+       WEIGHT4,
        TEXCOORD1 = 56,
        TEXCOORD2,
        TEXCOORD3,