Transfer shape keys does not work for figures that are exported with a non-zero world transform

Issue #1873 invalid
Rakete created an issue

If I move a figure to somewhere that is not the 0,0,0 in world coordinates and export, then transfer shape keys in blender does not work. Reason is that all shape keys are skipped because this:

if self.outsideBox(srcboxes[sname], trgbox):
    print(" 0", sname)
    continue

will be true for all of them. When you export you use var geom = obj.getCachedGeom(); and then get the vertices from that, but getCachedGeom returns:

  • The final world-space transformed mesh for the current shape.

and so the vertices will be different depending on where the figure is located. Why not just use getGeometry? The script also sets the LOD to 0 for the figure so that the mesh is exported without subd applied, so it shouldn’t make a difference if getGeometry was used. Alternatively the script should apply the inverse world transform of the object to every vertex. Or maybe just move the figure to 0,0,0 (and rotation and scale) before exporting the vertices.

Comments (12)

  1. Rakete reporter

    Moving the figure to 0,0,0 before exporting is a bad idea, it would mean you need to get the cached geometry again, so lets ignore that.

  2. Rakete reporter

    Also I found one other problem while investigating the problem, in merge.py, in reparentObjects, you call setWorldMatrix. That will update the world matrix of the figure mesh and then the transfer code will complain about the world transform not being applied to the mesh. So if you merge the face controls, and then try to transfer shapes it won’t work. I fixed that temporarily by writing a check so that setWorldMatrix(ob, wmat) is only called when the parent actually changed, otherwise I don’t actually see why you would want to set the world matrix in there?

    def reparentObjects(self, info, rig, adds, hdadds, removes):
            for ob,data in info.objects:
                partype, parbone = data
                if partype in ['VERTEX', 'VERTEX_3', 'VERTEX_TRI']:
                    continue
                parentIsDifferent = ob.parent != rig
                if partype == 'BONE':
                    if parbone in rig.pose.bones.keys():
                        parentIsDifferent = parentIsDifferent or ob.parent_bone != parbone
                    else:
                        parentIsDifferent = parentIsDifferent or ob.parent_bone != info.getBoneKey(parbone)
                wmat = ob.matrix_world.copy()
                ob.parent = rig
                ob.parent_type = partype
                if parbone is None:
                    pass
                elif parbone in rig.data.bones.keys():
                    ob.parent_bone = parbone
                else:
                    ob.parent_bone = info.getBoneKey(parbone)
                if parentIsDifferent:
                    setWorldMatrix(ob, wmat)
                self.addToCollections(ob, adds, hdadds, removes)
    

  3. Rakete reporter

    Oh, now I tried getGeometry and I see what the problem is. The mesh is not where is should be then when importing, so the code relies on the vertices being in world space when the scene is build in blender, so that armature and mesh line up correctly. Ok then.

  4. Thomas Larsson repo owner

    Sorry, but I don’t understand. A DS object doesn’t have a method called getGeometry as far as I know (I tried and the script failed). The cached geometry at LOD = 0 is used because it gives the figure with all morphs applied and transferred to clothes. At least I didn’t find another way to achieve that. Other methods return the unmorphed mesh, but I don’t need that because it is already available in the dsf files.

  5. Thomas Larsson repo owner

    But that method returns the unmorphed mesh. The morphed armature is found in the duf file, but the morphed mesh is normally not. Here what I get when I replace obj.getCachedGeom with shape.getGeometry:

  6. Thomas Larsson repo owner

    Note that in the HD script, the only thing that shape.getGeometry is used for is to get the number of vertices of the base mesh, not the vertex locations.

  7. Rakete reporter

    Ok, trying to reproduce the issue manually by doing all the steps I do in my addon actually fails. So I can figure this one out by going through what I do differently when importing and transfering shape keys programmatically. I do just call the diffeo operators usually, so that is why I thought there is a bug.

  8. Rakete reporter

    Alright, my problem is I call apply_rest_pose after importing (don’t remember why though), and that resets the object pivot to the world root. And I assume that then throws off the bounding box calculation.

  9. Log in to comment