예제 #1
0
파일: Cut.py 프로젝트: dvochin/Blender
def gBL_ClothCut_ApplyCut(
    sNameBody, sNameCurve, nCenterX, nCenterY, nCenterZ
):  # Client-side wrapup of Cut_ApplyCut() that apples the given cutter to a virgin new cloth mesh copied from source
    oMeshClothCutO = DuplicateAsSingleton(
        sNameBody + G.C_NameSuffix_ClothBase,
        sNameBody + G.C_NameSuffix_ClothCut, G.C_NodeFolder_Game,
        True)  # Copy the base mesh to reset the cut to start
    oCurveO = bpy.data.objects[sNameCurve]
    aBorderLocatorVertPos = {}
    vecCurveCenterClient = Vector((nCenterX, nCenterY, nCenterZ))
    vecCurveCenter = G.VectorU2B(vecCurveCenterClient)
    Cut_ApplyCut(oMeshClothCutO, oCurveO, vecCurveCenter,
                 aBorderLocatorVertPos)
    Client.Client_ConvertMeshForUnity(
        oMeshClothCutO, True
    )  # Mesh has changed topology, update its state for Client  ###CHECK!!!! Expensive complex call???  Do all of that???
    return G.DumpStr(
        "OK: gBL_Cut_ApplyCut(ClothCut = '[]'  Curve='{}')".format(
            oMeshClothCutO.name, sNameCurve))
예제 #2
0
파일: Cut.py 프로젝트: dvochin/Blender
def Cut_ApplyCuts(sNameClothSource, sNameClothOutput,
                  bCleanupBorders):  ###OBS???
    print("\n======= Cut_ApplyCuts BEGIN =======")

    #=== Prepare for function by extracting needed objects from scene ===
    oMeshO = DuplicateAsSingleton(sNameClothSource, sNameClothOutput,
                                  G.C_NodeFolder_Game, True)
    Util_HideMesh(oMeshO)
    oMeshO.hide_render = False
    bpy.ops.object.mode_set(mode='EDIT')
    oCurves = bpy.data.objects[G.C_NodeName_Curve]
    aBorderLocatorVertPos = {
    }  # Map of 'locator verts' for each border.  Because boolean destroys most mesh metainfo, we're using the vertex position of one vertex on each border to rebuild the list of verts per border

    #=== Iterate through all active curves to obtain their cutters and get them to work cutting the working cloth ===
    print("\n===== Cut_ApplyCuts Phase1: Applying cutters =====")
    for oCurve in oCurves.children:
        if oCurve.hide_render:
            continue  ###TEMP ###CHECK: Keep this (useful) technique to disable objects without changing parent??
        Cut_ApplyCut(oMeshO, oCurve, aBorderLocatorVertPos)

    #=== Now that the highly-destructive boolean operations are all done (which prevent any type of mesh meta info from traversing), perform border reconstruction and cleanup ===
    if bCleanupBorders:
        print("\n===== Cut_ApplyCuts Phase2: Cleaning up borders =====")
        for oCurve in oCurves.children:
            if oCurve.hide_render:
                continue  ###TEMP ###CHECK: Keep this (useful) technique to disable objects without changing parent??
            Cut_CleanupBorder(
                oMeshO, oCurve, aBorderLocatorVertPos
            )  # Prepare the border by cleaning it up toward the final topology that will be used to actually create the border (run after any cloth simulation)

    bpy.ops.uv.seams_from_islands(
        mark_seams=True, mark_sharp=False
    )  # Not sure this is really needed but just to make sure...
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.context.scene.update()

    return G.DumpStr(
        "OK: Cut_ApplyCuts('{}', '{}', Cleanup={} with {} verts and {} faces.".
        format(sNameClothSource, sNameClothOutput, bCleanupBorders,
               len(oMeshO.data.vertices), len(oMeshO.data.polygons)))
예제 #3
0
    def Unity_GetBones(self):
        ###BROKEN: Breaks CBodyEd!  Called by the CBodyEd (Unity's run-in-edit-mode code for CBody) to update the position of the bones for the selected Unity template.  Non destructive call that assumes existing bones are already there with much extra information such as ragdoll colliders, components on bones, etc.)
        ###IDEA: Move this to a new class that encapsulates the concept of an armature?  (e.g. CArmature with all kinds of functions to service it)
        # This call only updates bones position and creates bones if they are missing.  Rotation isn't touched and extraneous bones have to be deleted in Unity if needed.
        print("\n=== gBL_GetBones('{}') ===".format(self.sMeshPrefix))
        oMeshO = self.oMeshMorph.GetMesh()
        if "Armature" not in oMeshO.modifiers:
            return G.DumpStr(
                "ERROR: gBL_GetBones() cannot find armature modifier for '" +
                self.sMeshPrefix + "'")
        oArmObject = oMeshO.modifiers[
            "Armature"].object  ###INFO: How to get Blender node that holds bones
        oArm = oArmObject.data

        #=== Send bone tree (without bone positions) Unity needs our order to map to its existing bone which remain the authority ===
        oBA = CByteArray()
        SelectObject(oArmObject.name)  # Select armature node
        bpy.ops.object.mode_set(mode='EDIT')
        oBA.AddBone(
            oArm.edit_bones[0]
        )  # Recursively send the bone tree starting at root bone (0)
        bpy.ops.object.mode_set(mode='OBJECT')

        return oBA.CloseArray()
예제 #4
0
    def CMorphChannel_GetMorphVerts(
        self, sNameShapeKey
    ):  # Called by CBMeshMorph to get the morphed verts on a given shape key and a given mesh.  Used to morph non-skinned meshes at runtime such as face eyelids and mouth open/close
        #=== Find requested shape key to obtain morph data ===
        oMeshMorphO = self.oMeshMorph.GetMesh()
        oMeshShapeKeyBlocks = oMeshMorphO.data.shape_keys.key_blocks
        if sNameShapeKey in oMeshShapeKeyBlocks:
            nMorphKeyBlockIndex = oMeshShapeKeyBlocks.find(
                sNameShapeKey
            )  ###INFO: How to find a key's index in a collection! (Set by oMeshMorphO.active_shape_key_index)
        else:
            return G.DumpStr(
                "ERROR: CMorphChannel_GetMorphVerts() cannot find shape key " +
                sNameShapeKey)

        #=== Obtain access to shape key vert data ===
        aVertsBasis = oMeshShapeKeyBlocks[
            0].data  # 'Basis' is always index zero
        aVertsMorph = oMeshShapeKeyBlocks[
            nMorphKeyBlockIndex].data  # We obtain the vert positions from the 'baked shape key'  ###INFO: How to get raw shape key data
        bmMorph = bmesh.new(
        )  ###INFO: How to operate with bmesh without entering edit mode!        ###TODO11: Change codebase to this technique?
        bmMorph.from_object(oMeshMorphO,
                            bpy.context.scene)  ###DESIGN: Selection of body!

        #=== Obtain access to the 'morph result' mesh.  We need it to expand result set to duplicate morph deltas accross verts split by material seams ===
        oMeshMorphResultO = self.oMeshMorphResult.GetMesh()
        bmMorphResult = bmesh.new()
        bmMorphResult.from_object(oMeshMorphResultO, bpy.context.scene)
        oLaySplitVertID = bmMorphResult.verts.layers.int[
            G.C_DataLayer_SplitVertIDs]
        bmMorphResult.verts.ensure_lookup_table()

        #=== Iterate through all the mesh verts and test all verts that are different for the given shape key so we can serialize its delta data to client
        print("\n=== CMorphChannel_GetMorphVerts('{}', '{}' ===".format(
            self.oMeshMorph.GetName(), sNameShapeKey))
        oBA = CByteArray()
        for oVert_Morph in bmMorph.verts:
            oVert_MorphResult = bmMorphResult.verts[
                oVert_Morph.
                index]  ###CHECK: Same verts except for split ones??
            vecVertBasis = aVertsBasis[oVert_Morph.index].co
            vecVertMorph = aVertsMorph[oVert_Morph.index].co
            vecVertDelta = vecVertMorph - vecVertBasis
            nLengthDelta = vecVertDelta.length
            if (
                    nLengthDelta >= 0.0001
            ):  # Don't bother with verts that change such a tiny amount to optimize performance          #if vecVertBasis != vecVertMorph:            ###INFO: For some reason this doesn't work!  It lets through tiny values through like 0.00000001!
                #print("{:4}  #{:5} = Dist {:6.4} = ({:10.7},{:10.7},{:10.7})".format(nMorphedVerts, oVert_Morph.index, nLengthDeltaSqr, vecVertDelta.x, vecVertDelta.y, vecVertDelta.z))
                oBA.AddFloat(
                    oVert_Morph.index
                )  ###NOTE: Packing ID as a float so that we can conveniently view all data as float (as vector is three floats)
                oBA.AddVector(
                    vecVertDelta
                )  ###NOTE: AddVector() will convert from Blender coordinate system to Unity.  (Unity can read straight up)
                nSplitVertID = oVert_MorphResult[oLaySplitVertID]
                if nSplitVertID >= G.C_OffsetVertIDs:
                    aSplitVerts = self.oMeshMorphResult.aaSplitVerts[
                        nSplitVertID]
                    for nVertSplit in aSplitVerts:
                        if nVertSplit != oVert_Morph.index:  # Don't add the vert already added above
                            oBA.AddFloat(nVertSplit)
                            oBA.AddVector(vecVertDelta)

        return oBA.Unity_GetBytes()