zoukankan      html  css  js  c++  java
  • kinect笔记 六、简单的虚拟换衣

    显示

      1、新建一个空对象,命名为KinectController,在此对象上绑定KinectManager、KinectGestures、OverlayController

      2、KinectManager上的ComputeColorMap和UseMultiSourceReader勾选上

      3、设置Main Camera(这里的摄像头作为一个Foreground Camera)

        (1) Clear Flags设置为Depth only

        (2) Culling Mask 设置为 除Everything外的其他选项都勾选上

        (3) Clipping Plans 的Near设置为0.1 Far设置为10

        (4) Depth设为0

      新建一个camera,命名为BackgroundCamera

        (1)将Clear Flags设置为Solid Color

        (2)Culling Mask设置为Everything

        (3)Depth设为-1

      4、将OverlayController中的BackgroundImage的类型更改为RawImage或Image

        如果改为RawImage则

          if (backgroundImage.texture == null)

                 {

                        backgroundImage.texture = manager.GetUsersClrTex();

           }

        如果改为Image则

          if(backgroundImage.GetComponent<Image>().material.mainTexture==null){

            backgroundImage.GetComponent<Image>().material.mainTexture=manager.GetUsersClrTex();

          }

      5、在场景中新建一个Image或RawImage,然后将两个Camera和Image跟OverlayController关联上,然后运行即可

      显示的图像可能是上下颠倒的,在这里我只是将image的Rotation的X改为了180

    设置模型的同步和显示

      在模型上绑定AvatarController和AvatarScaler两个脚本

        AvatarController

          勾选上Mirrored Movement

          勾选上Vertical Movement

          Move Rate设为1

          Smooth Factor设为0(或者默认数值也可以)

          将backgroundCamera关联到Pos Relative To Camera上

          勾选上Pos Rel Overlay Color

        Avatar Scaler

          勾选上Mirrored Avatar

          勾选上Continuous Scaling

          Smooth Factor设为5

          将Main Camrera关联到Foreground Camera

       如果是直接拖拽,则使用以上绑定这两个脚本的方法,如果要用代码来写,那还请继续看下去。

      设置画布 Canvas

        将RenderMode设为Screen Space - Camera

        将backgroundCamera关联到Render Camera

        因为之前默认的模式是Screen Space - Overlay,我感觉应该是将UI层置顶了,所以无法显示3D场景中的东西,现在设置为Screen Space - Camera,应该是显示摄像机范围内的物体

    以下是根据人体动作来更换显示的衣物模型

    1、 

      在场景中创建一个空物体,命名为MyGestureListener,创建一个脚本,命名为MyGestureListener.cs(这是我的一个小习惯,如果不喜欢的话,可以随便放在哪,只要你在用的时候能很快找到就行)

      这个脚本主要用于获取人体的动作

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class MyGestureListener : MonoBehaviour , KinectGestures.GestureListenerInterface
    {
        [Tooltip("由该组件跟踪的播放器索引。0代表第一人,1人,第二人,2人,第三人,等等。")]
        public int playerIndex = 0;
    
        [Tooltip("Text 用于显示监听到的手势动作的信息")]
        public Text gestureInfo;
    
        //跟踪进程消息是否已显示的内部变量
        private bool progressDisplayed;
        private float progressGestureTime;
    
        public MyController myController;
    
        /// <summary>
        /// 当检测到新用户时调用。在这里,可以通过调用KinectManager.DetectGesture()来开始手势跟踪。
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="userIndex">User index</param>
        public void UserDetected(long userId, int userIndex)
        {
            // 只允许主要用户使用手势
            KinectManager manager = KinectManager.Instance;
            if (!manager || (userIndex != playerIndex))
            {
                return;
            }
    
            // 检测这些用户特定的手势
            manager.DetectGesture(userId, KinectGestures.Gestures.SwipeLeft);
            manager.DetectGesture(userId, KinectGestures.Gestures.SwipeRight);
        }
        /// <summary>
        /// 当用户丢失时调用。此用户的所有跟踪手势都会自动清除
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="userIndex">User index</param>
        public void UserLost(long userId, int userIndex)
        {
            // 只允许主要用户使用手势
            if (userIndex != playerIndex)
            {
                return;
            }
           
        }
    
        /// <summary>
        /// 当手势正在进行时调用
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="userIndex">User index</param>
        /// <param name="gesture">Gesture type</param>
        /// <param name="progress">Gesture progress [0..1]</param>
        /// <param name="joint">Joint type</param>
        /// <param name="screenPos">Normalized viewport position</param>
        public void GestureInProgress(long userId, int userIndex, KinectGestures.Gestures gesture,
                                      float progress, KinectInterop.JointType joint, Vector3 screenPos)
        {
            // 只允许主要用户使用手势
            if (userIndex != playerIndex)
                return;
            /*Debug.Log("ing");
            Debug.Log(gesture);
            Debug.Log("----ing----");*/
            if ((gesture == KinectGestures.Gestures.ZoomOut || gesture == KinectGestures.Gestures.ZoomIn) && progress > 0.5f)
            {
                if (gestureInfo != null)
                {
                    string sGestureText = string.Format("{0} - {1:F0}%", gesture, screenPos.z * 100f);
                    gestureInfo.text = sGestureText;
    
                    progressDisplayed = true;
                    progressGestureTime = Time.realtimeSinceStartup;
                }
    
            }
            else if ((gesture == KinectGestures.Gestures.Wheel || gesture == KinectGestures.Gestures.LeanLeft ||
                     gesture == KinectGestures.Gestures.LeanRight) && progress > 0.5f)
            {
                if (gestureInfo != null)
                {
                    string sGestureText = string.Format("{0} - {1:F0} degrees", gesture, screenPos.z);
                    gestureInfo.text = sGestureText;
    
                    progressDisplayed = true;
                    progressGestureTime = Time.realtimeSinceStartup;
    
                }
    
            }
            else if (gesture == KinectGestures.Gestures.Run && progress > 0.5f)
            {
                if (gestureInfo != null)
                {
                    string sGestureText = string.Format("{0} - progress: {1:F0}%", gesture, progress * 100);
                    gestureInfo.text = sGestureText;
    
                    progressDisplayed = true;
                    progressGestureTime = Time.realtimeSinceStartup;
                }
            }
            /*if (gesture == KinectGestures.Gestures.Tpose)
            {
                Debug.Log("放大");
            }*/
        }
        /// <summary>
        /// 如果手势完成,则调用。
        /// </summary>
        /// <returns>true</returns>
        /// <c>false</c>
        /// <param name="userId">User ID</param>
        /// <param name="userIndex">User index</param>
        /// <param name="gesture">Gesture type</param>
        /// <param name="joint">Joint type</param>
        /// <param name="screenPos">Normalized viewport position    标准视口位置</param>
        public bool GestureCompleted(long userId, int userIndex, KinectGestures.Gestures gesture,
                                      KinectInterop.JointType joint, Vector3 screenPos)
        {
            // 只允许主要用户使用手势
            if (userIndex != playerIndex)
                return false;
    
            if (gestureInfo != null)
            {
                string sGestureText = gesture + " detected";
                gestureInfo.text = sGestureText;
            }
    
            if (gesture == KinectGestures.Gestures.SwipeLeft)
            {
                /*swipeLeft = true;
                //udpClient.SocketSend(gesture.ToString());
                udpClient.SocketSend("xiangZuo");*/
                Debug.Log("swipeLeft");
                //myController.changeModelFunc();
                myController.modelIndex++;
            }
            else if (gesture == KinectGestures.Gestures.SwipeRight)
            {
                /*swipeRight = true;
                //udpClient.SocketSend(gesture.ToString());
                udpClient.SocketSend("xiangYou");*/
                Debug.Log("swipeRight");
                myController.modelIndex--;
    
            }
            else if (gesture == KinectGestures.Gestures.SwipeUp)
            {
                /*swipeUp = true;
                //udpClient.SocketSend(gesture.ToString());
                udpClient.SocketSend("xiangShang");*/
            }
            else if (gesture == KinectGestures.Gestures.RaiseLeftHand || gesture == KinectGestures.Gestures.RaiseRightHand)
            {
                //udpClient.SocketSend("fangDa");
            }
    
            return true;
        }
        /// <summary>
        /// 如果手势被取消,则调用
        /// </summary>
        /// <returns>true</returns>
        /// <c>false</c>
        /// <param name="userId">User ID</param>
        /// <param name="userIndex">User index</param>
        /// <param name="gesture">Gesture type</param>
        /// <param name="joint">Joint type</param>
        public bool GestureCancelled(long userId, int userIndex, KinectGestures.Gestures gesture,
                                      KinectInterop.JointType joint)
        {
            // 只允许主要用户使用手势
            if (userIndex != playerIndex)
                return false;
    
            if (progressDisplayed)
            {
                progressDisplayed = false;
    
                if (gestureInfo != null)
                {
                    gestureInfo.text = String.Empty;
                }
            }
    
            return true;
        }
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    }

    2、  

      模型的显示和跟随着真人的动作而动,主要应该是在于两个脚本,一个是AvatarController,一个是AvatarScaler,其中的AvatarScaler主要作用应该是照着真人适配模型的大小

      创建一个空物体,命名为MyController,生成一个脚本,命名为MyController.cs(呐,如上,这是我的一个小习惯,如果不喜欢的话,可以随便放在哪,只要你在用的时候能很快找到就行)

      这个脚本的作用是更换衣物模型,里面的两个摄像机的命名跟之前创建摄像机的命名相同,对应的关联上就行了

      

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MyController : MonoBehaviour {
    
        /*public GameObject model1;
        public GameObject model2;
        public GameObject model3;*/
    
        public Camera backgroundCamera;
        public Camera mainCamera;
    
        //public GameObject[] models = new GameObject[3];
        public GameObject[] models;//存放所有模型的数组
        public int index=0;//当前选中的模型的索引
    
        public int playerIndex = 0;//跟字面的意思一样,就是playerIndex
        // Use this for initialization
        void Start () {
            //changeModelFunc();
        }
        
        // Update is called once per frame
        void Update () {
            
        }
        public int modelIndex
        {
            get {
                return index;
            }
            set
            {
                index = value;
                if (index < 0)
                {
                    index = models.Length - 1;
                }
                else if (index > models.Length - 1)
                {
                    index = 0;
                }
                changeModelFunc(index);
            }
        }
        public void changeModelFunc(int _index=0)//因为直接就能获取到全局的那个index,所以其实这里的 _index没什么用
        {
            //index = 1;
            index = _index;
            Debug.Log(index);
            //model1
            /*Debug.Log("sssssssssssssss");
            Debug.Log(models[index].GetComponent<AvatarController>());
            Debug.Log("eeeeeeeeee");*/
    
            //只显示当前选择的模型
            for (int i = 0; i < models.Length; i++)
            {
                models[i].SetActive(false);
            }
            models[index].SetActive(true);
    
            
    
            AvatarController avatarController = models[index].GetComponent<AvatarController>();
    
            if (avatarController == null)
            {
                avatarController =models[index].AddComponent<AvatarController>();
                avatarController.playerIndex = playerIndex;
                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 km = KinectManager.Instance;
            //ac.Awake();
    
            if (km && km.IsInitialized())
            {
                long userId = km.GetUserIdByIndex(playerIndex);
                if (userId != 0)
                {
                    avatarController.SuccessfulCalibration(userId, false);
                }
    
                // locate the available avatar controllers
                MonoBehaviour[] monoScripts = FindObjectsOfType(typeof(MonoBehaviour)) as MonoBehaviour[];
                km.avatarControllers.Clear();
    
                foreach (MonoBehaviour monoScript in monoScripts)
                {
                    if ((monoScript is AvatarController) && monoScript.enabled)
                    {
                        AvatarController avatar = (AvatarController)monoScript;
                        km.avatarControllers.Add(avatar);
                    }
                }
            }
    
            AvatarScaler avatarScaler = models[index].GetComponent<AvatarScaler>();
            if (avatarScaler == null)
            {
                avatarScaler =models[index].AddComponent<AvatarScaler>();
                avatarScaler.playerIndex = playerIndex;
                avatarScaler.mirroredAvatar = true;
                avatarScaler.continuousScaling = true;
                avatarScaler.smoothFactor = 5;
                avatarScaler.bodyScaleFactor = 1;
                avatarScaler.bodyWidthFactor = 1;
                avatarScaler.armScaleFactor = 1;
                avatarScaler.legScaleFactor = 1;
            }
            avatarScaler.foregroundCamera = mainCamera;
            //avatarScaler.Start();
    
    
        }
    }

    应该就是这样了,如果都做完的话,那就运行看看吧,本来我是把博客当做笔记本了。但是想想吧,博客毕竟是个公开的东西,所以就尽量的多写一些了注释,希望能帮到那些不会的人。

    最后,如有问题,还请指出,望请赐教,共同进步。

  • 相关阅读:
    C#Type类中的IsAssignableFrom、IsInstanceOfType、IsSubclassOf
    C# IsAssignableFrom & IsInstanceOfType & IsSubclassOf & Is
    VS2017桌面应用程序打包成.msi或者.exe
    C# 10个常用特性
    ADO.NET 的六大对象及其关系图
    Expression表达式树(C#)
    表达式树 Expression Trees
    特性 Attribute
    C# 特性(attribute)
    Vue中使用axios
  • 原文地址:https://www.cnblogs.com/lingLuoChengMi/p/9708204.html
Copyright © 2011-2022 走看看