Thay trang phục ảo theo chuyển động cơ thể bằng Kinect và Unity

Thiết lập hiển thị

  1. Tạo một GameObject rỗng, đặt tên KinectController, gắn các component KinectManager, KinectGestures và OverlayController.
  2. Trên KinectManager, bật ComputeColorMap và UseMultiSourceReader.
  3. Cấu hình Main Camera như camera foreground:
    • Clear Flags: Depth only
    • Culling Mask: bỏ chọn Everything, sau đó chọn tất cả các layer còn lại
    • Clipping Planes: Near = 0.1, Far = 10
    • Depth = 0
    Tạo camera mới, đặt tên BackgroundCamera:
    • Clear Flags: Solid Color
    • Culling Mask: Everything
    • Depth = -1
  4. Trong OverlayController, đổi kiểu của BackgroundImage thành RawImage hoặc Image.

    Nếu dùng RawImage:

    if (backgroundImage.texture == null)
    {
        backgroundImage.texture = manager.GetUsersClrTex();
    }
    

    Nếu dùng Image:

    Image image = backgroundImage.GetComponent<Image>();
    if (image.material.mainTexture == null)
    {
        image.material.mainTexture = manager.GetUsersClrTex();
    }
    
  5. Tạo một Image hoặc RawImage trong scene, gán hai camera và image đó vào OverlayController, sau đó chạy thử.

Hình hiển thị có thể bị lật ngược. Có thể khắc phục bằng cách đặt Rotation.x = 180 trên image.

Đồng bộ và hiển thị mô hình

Gắn hai script AvatarController và AvatarScaler lên mô hình nhân vật.

AvatarController

  • Bật Mirrored Movement.
  • Bật Vertical Movement.
  • Đặt Move Rate = 1.
  • Đặt Smooth Factor = 0 hoặc giữ giá trị mặc định.
  • Gán BackgroundCamera vào Pos Relative To Camera.
  • Bật Pos Rel Overlay Color.

AvatarScaler

  • Bật Mirrored Avatar.
  • Bật Continuous Scaling.
  • Đặt Smooth Factor = 5.
  • Gán Main Camera vào Foreground Camera.

Nếu kéo thả trực tiếp trong Inspector, dùng cách gán trên. Nếu muốn thiết lập bằng code, xem phần tiếp theo.

Cấu hình Canvas

  • Đặt RenderMode thành Screen Space - Camera.
  • Gán BackgroundCamera vào Render Camera.

Chế độ mặc định Screen Space - Overlay thường đưa UI lên trên cùng nên có thể che mất các đối tượng 3D. Chuyển sang Screen Space - Camera để UI hiển thị theo phạm vi camera.

Đổi mẫu trang phục theo cử chỉ cơ thể

  1. Tạo một GameObject rỗng, đặt tên GestureController. Tạo script ClothingGestureListener.cs để nhận cử chỉ từ người dùng.
using UnityEngine;
using UnityEngine.UI;

public class ClothingGestureListener : MonoBehaviour, KinectGestures.GestureListenerInterface
{
    [Tooltip("Chỉ số người dùng được theo dõi. 0 là người thứ nhất, 1 là người thứ hai, ...")]
    public int trackedPlayer = 0;

    [Tooltip("Text hiển thị thông tin cử chỉ nhận được")]
    public Text gestureStatusText;

    public WardrobeModelSwitcher wardrobeController;

    private bool showingProgress;

    public void UserDetected(long userId, int userIndex)
    {
        KinectManager manager = KinectManager.Instance;
        if (manager == null || userIndex != trackedPlayer)
        {
            return;
        }

        manager.DetectGesture(userId, KinectGestures.Gestures.SwipeLeft);
        manager.DetectGesture(userId, KinectGestures.Gestures.SwipeRight);
    }

    public void UserLost(long userId, int userIndex)
    {
        if (userIndex != trackedPlayer)
        {
            return;
        }
    }

    public void GestureInProgress(long userId, int userIndex, KinectGestures.Gestures gesture,
                                  float progress, KinectInterop.JointType joint, Vector3 screenPos)
    {
        if (userIndex != trackedPlayer || gestureStatusText == null)
        {
            return;
        }

        string message = null;

        if ((gesture == KinectGestures.Gestures.ZoomOut || gesture == KinectGestures.Gestures.ZoomIn) && progress > 0.5f)
        {
            message = string.Format("{0} - {1:F0}%", gesture, screenPos.z * 100f);
        }
        else if ((gesture == KinectGestures.Gestures.Wheel ||
                  gesture == KinectGestures.Gestures.LeanLeft ||
                  gesture == KinectGestures.Gestures.LeanRight) && progress > 0.5f)
        {
            message = string.Format("{0} - {1:F0} độ", gesture, screenPos.z);
        }
        else if (gesture == KinectGestures.Gestures.Run && progress > 0.5f)
        {
            message = string.Format("{0} - tiến trình: {1:F0}%", gesture, progress * 100f);
        }

        if (message != null)
        {
            gestureStatusText.text = message;
            showingProgress = true;
        }
    }

    public bool GestureCompleted(long userId, int userIndex, KinectGestures.Gestures gesture,
                                 KinectInterop.JointType joint, Vector3 screenPos)
    {
        if (userIndex != trackedPlayer)
        {
            return false;
        }

        if (gestureStatusText != null)
        {
            gestureStatusText.text = gesture + " đã nhận diện";
        }

        switch (gesture)
        {
            case KinectGestures.Gestures.SwipeLeft:
                if (wardrobeController != null)
                {
                    wardrobeController.OutfitIndex++;
                }
                break;

            case KinectGestures.Gestures.SwipeRight:
                if (wardrobeController != null)
                {
                    wardrobeController.OutfitIndex--;
                }
                break;
        }

        return true;
    }

    public bool GestureCancelled(long userId, int userIndex, KinectGestures.Gestures gesture,
                                 KinectInterop.JointType joint)
    {
        if (userIndex != trackedPlayer)
        {
            return false;
        }

        if (showingProgress)
        {
            showingProgress = false;

            if (gestureStatusText != null)
            {
                gestureStatusText.text = string.Empty;
            }
        }

        return true;
    }
}

Mô hình hiển thị và bám theo chuyển động của người thật chủ yếu nhờ hai script AvatarController và AvatarScaler. Trong đó, AvatarScaler có nhiệm vụ căn kích thước mô hình theo người thật.

  1. Tạo một GameObject rỗng, đặt tên WardrobeController. Tạo script WardrobeModelSwitcher.cs để đổi mẫu trang phục. Gán hai camera đã tạo vào các trường tương ứng trong Inspector.
using UnityEngine;

public class WardrobeModelSwitcher : MonoBehaviour
{
    public Camera backgroundCamera;
    public Camera mainCamera;

    public GameObject[] outfits;
    public int trackedPlayer = 0;

    private int currentIndex = 0;

    public int OutfitIndex
    {
        get { return currentIndex; }
        set
        {
            if (outfits == null || outfits.Length == 0)
            {
                return;
            }

            currentIndex = value;

            if (currentIndex < 0)
            {
                currentIndex = outfits.Length - 1;
            }
            else if (currentIndex >= outfits.Length)
            {
                currentIndex = 0;
            }

            SwitchOutfit(currentIndex);
        }
    }

    public void SwitchOutfit(int targetIndex = 0)
    {
        if (outfits == null || outfits.Length == 0)
        {
            return;
        }

        if (targetIndex < 0 || targetIndex >= outfits.Length)
        {
            targetIndex = 0;
        }

        currentIndex = targetIndex;

        for (int i = 0; i < outfits.Length; i++)
        {
            if (outfits[i] != null)
            {
                outfits[i].SetActive(i == currentIndex);
            }
        }

        GameObject activeOutfit = outfits[currentIndex];
        if (activeOutfit == null)
        {
            return;
        }

        AvatarController avatarController = activeOutfit.GetComponent<AvatarController>();
        if (avatarController == null)
        {
            avatarController = activeOutfit.AddComponent<AvatarController>();
            avatarController.playerIndex = trackedPlayer;
            avatarController.mirroredMovement = true;
            avatarController.verticalMovement = true;
            avatarController.moveRate = 1;
            avatarController.verticalOffset = 0;
            avatarController.forwardOffset = 0;
            avatarController.smoothFactor = 0;
        }

        avatarController.posRelativeToCamera = backgroundCamera;
        avatarController.posRelOverlayColor = true;

        KinectManager manager = KinectManager.Instance;
        if (manager != null && manager.IsInitialized())
        {
            long userId = manager.GetUserIdByIndex(trackedPlayer);
            if (userId != 0)
            {
                avatarController.SuccessfulCalibration(userId, false);
            }

            manager.avatarControllers.Clear();

            MonoBehaviour[] behaviours = FindObjectsOfType<MonoBehaviour>();
            foreach (MonoBehaviour behaviour in behaviours)
            {
                AvatarController avatar = behaviour as AvatarController;
                if (avatar != null && avatar.enabled)
                {
                    manager.avatarControllers.Add(avatar);
                }
            }
        }

        AvatarScaler avatarScaler = activeOutfit.GetComponent<AvatarScaler>();
        if (avatarScaler == null)
        {
            avatarScaler = activeOutfit.AddComponent<AvatarScaler>();
            avatarScaler.playerIndex = trackedPlayer;
            avatarScaler.mirroredAvatar = true;
            avatarScaler.continuousScaling = true;
            avatarScaler.smoothFactor = 5;
            avatarScaler.bodyScaleFactor = 1;
            avatarScaler.bodyWidthFactor = 1;
            avatarScaler.armScaleFactor = 1;
            avatarScaler.legScaleFactor = 1;
        }

        avatarScaler.foregroundCamera = mainCamera;
    }
}

Thẻ: Kinect Unity C# KinectGestures AvatarController

Đăng vào ngày 25 tháng 9 lúc 20:55