alexisheloir / slsi-nui-interaction-scripts

Collection of Python Blender scripts to author virtual characters using Natural User Interfaces.
slsi.dfki.de
18 stars 4 forks source link

Long shot but worth asking #1

Open ectomia opened 2 months ago

ectomia commented 2 months ago

Hi there, I have been trying to get this script to work with a new version of blender but to no avail.

I am wondering if you maybe have an up to date script that will work?

I can get faceshift to talk to blender, and the data received, the issue I am having is with the transfer of the data to the blendshapes.

here is my code so far, wondering if you could help please

import bpy import socket import threading import struct

Define the UDP IP address and port

UDP_IP = "127.0.0.1" # Localhost (change to the IP address Faceshift Studio is sending to) UDP_PORT = 5005 # The port Faceshift Studio is sending to

Create a socket to listen for UDP packets

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((UDP_IP, UDP_PORT))

List of blendshape names

blendshape_names = [ "EyeBlink_L", "EyeBlink_R", "EyeSquint_L", "EyeSquint_R", "EyeDown_L", "EyeDown_R", "EyeIn_L", "EyeIn_R", "EyeOpen_L", "EyeOpen_R", "EyeOut_L", "EyeOut_R", "EyeUp_L", "EyeUp_R", "BrowsD_L", "BrowsD_R", "BrowsU_C", "BrowsU_L", "BrowsU_R", "JawOpen", "LipsTogether", "JawLeft", "JawRight", "JawFwd", "LipsUpperUp_L", "LipsUpperUp_R", "LipsLowerDown_L", "LipsLowerDown_R", "LipsUpperClose", "LipsLowerClose", "MouthSmile_L", "MouthSmile_R", "MouthDimple_L", "MouthDimple_R", "LipsStretch_L", "LipsStretch_R", "MouthFrown_L", "MouthFrown_R", "MouthPress_L", "MouthPress_R", "LipsPucker", "LipsFunnel", "MouthLeft", "MouthRight", "ChinLowerRaise", "ChinUpperRaise", "Sneer_L", "Sneer_R", "Puff", "CheekSquint_L", "CheekSquint_R" ]

def udp_listener(): while True: try:

Receive data from Faceshift Studio

        data, addr = sock.recvfrom(1024)  # Buffer size is 1024 bytes
        print(f"Received message: {data} from {addr}")

        # Process the binary data (replace with actual parsing logic)
        parsed_data = parse_binary_data(data)

        # Update the blendshapes in Blender
        if parsed_data:
            bpy.app.timers.register(lambda: update_blendshapes(parsed_data))
    except Exception as e:
        print(f"Error in udp_listener: {e}")

def parse_binary_data(data):

Determine the number of blendshape weights expected

num_blendshapes = len(blendshape_names)

# Calculate the expected data size (num_blendshapes * 4 bytes per float)
expected_data_size = num_blendshapes * 4

# Check if the received data matches the expected size
if len(data) >= expected_data_size:
    # Unpack the data into floats
    weights = struct.unpack('f' * num_blendshapes, data[:expected_data_size])
    return weights
else:
    print(f"Received data size ({len(data)}) does not match expected size ({expected_data_size})")
    return None

def update_blendshapes(weights):

This function updates the blendshapes of a Blender object based on received weights

obj = bpy.data.objects.get("Head_Mesh")  # Replace with your mesh object name
if obj and obj.data.shape_keys:
    for i, weight in enumerate(weights):
        shape_key = obj.data.shape_keys.key_blocks.get(blendshape_names[i])
        if shape_key:
            shape_key.value = weight

Start the UDP listener in a separate thread

thread = threading.Thread(target=udp_listener) thread.daemon = True thread.start()

print("Started UDP listener...")

Keep the script running

def keep_running(): pass

bpy.app.timers.register(keep_running)

ectomia commented 2 months ago

Help_Faceshift