孙陪你,了解它的权力--Kinect结合的发展Unity3D游戏应用开发
unity3d正在使用kinect三维模型数据控制(它切成脚本)
博主在做项目时须要利用kinect数据控制三维模型中人物的动作。但不是实时控制,而是利用之前获得的骨骼数据,直接控制。无需再利用脚本打开kinect设备。
在博主转载的一篇博客中有一个unity3d的project包,特别适合。实现unity与kinect的交互。
http://blog.csdn.net/a350203223/article/details/22040119
该project中有多个脚本,之间联系复杂。本人使用此project中的脚本。经过分析。去除了当中冗余的脚本,能够实现直接传入数据就可以控制三维模型动作,不须要实时打开kinect,能够直接读取之前存录的骨骼点数据。
Kinect
KinectModelControllerV2 - 你须要将这个脚本拖放到你想要应用Kinect控制的模型上。为了让模型可以跟上人的节奏。你须要将模型上控制模型动作的关键骨骼拖放到这个脚本暴漏的合适的变量中 ,也就是将模型中的骨骼与kincet识别到的人的骨骼绑定起来。
另外这个脚本暴漏的变量中。另一个变量时标识模型是受哪个玩家控制。
KinectPointController - 你也须要将这个脚本拖放到场景中的游戏物体上。
可是这个游戏物体不是模型,而是由一系列分别代表头部、肩部、手等人体部位的点组成。你须要将游戏物体中的这些关键点都拖放到这个脚本暴漏的外部变量中。
这样就能够使用Kinect控制游戏物体了,游戏物体是由一系列的点组成的人体。
DisplayDepth - 这个脚本得到深度图像。
DisplayColor - 这个脚本得到RGB图像。
KinectRecorder - 这个脚本用于记录你的动作。并为Kinect模拟器(emulator)产生回放文件。
KinectEmulator - 这个脚本模拟Kinect设备.和KinectRecorder产生的回放文件一起工作。
KinectSensor - 这个脚本从Kinect设备中取得数据。须要替换这个文件使用特用版本号的SDK.
DeviceOrEmulator - 这个脚本设置使用Kinect物理设备还是Kinect模拟设备.
SkeletonWrapper - 这个脚本抓取骨骼数据.
DepthWrapper - 这个脚本抓取深度图像数据.
KinectInterop - 这个脚本从Microsoft Kinect SDK中抓取数据.
Recordings/playbackDefault - 这是为Kinect模拟设备准备的默认的回放文件.
可是我仅仅想找到控制模型的机制,传入数据直接控制模型。于是我分析了全部的脚本。找到当中的 Matrix4x4矩阵变换的关键,kinect坐标转化为世界坐标。删减了冗余的脚本。
整合到KinectModelControllerV2一个脚本中。
/*
* KinectModelController.cs - Handles rotating the bones of a model to match
* rotations derived from the bone positions given by the kinect
*
* Developed by Peter Kinney -- 6/30/2011
*
*/
using UnityEngine;
using System;
using System.Collections;
public class KinectModelControllerV2 : MonoBehaviour {
//Assignments for a bitmask to control which bones to look at and which to ignore
public enum BoneMask
{
None = 0x0,
//EMPTY = 0x1,
Spine = 0x2,
Shoulder_Center = 0x4,
Head = 0x8,
Shoulder_Left = 0x10,
Elbow_Left = 0x20,
Wrist_Left = 0x40,
Hand_Left = 0x80,
Shoulder_Right = 0x100,
Elbow_Right = 0x200,
Wrist_Right = 0x400,
Hand_Right = 0x800,
Hips = 0x1000,
Knee_Left = 0x2000,
Ankle_Left = 0x4000,
Foot_Left = 0x8000,
//EMPTY = 0x10000,
Knee_Right = 0x20000,
Ankle_Right = 0x40000,
Foot_Right = 0x80000,
All = 0xEFFFE,
Torso = 0x1000000 | Spine | Shoulder_Center | Head, //the leading bit is used to force the ordering in the editor
Left_Arm = 0x1000000 | Shoulder_Left | Elbow_Left | Wrist_Left | Hand_Left,
Right_Arm = 0x1000000 | Shoulder_Right | Elbow_Right | Wrist_Right | Hand_Right,
Left_Leg = 0x1000000 | Hips | Knee_Left | Ankle_Left | Foot_Left,
Right_Leg = 0x1000000 | Hips | Knee_Right | Ankle_Right | Foot_Right,
R_Arm_Chest = Right_Arm | Spine,
No_Feet = All & ~(Foot_Left | Foot_Right),
Upper_Body = Torso | Left_Arm | Right_Arm
}
public GameObject Hip_Center;
public GameObject Spine;
public GameObject Shoulder_Center;
public GameObject Head;
public GameObject Collar_Left;
public GameObject Shoulder_Left;
public GameObject Elbow_Left;
public GameObject Wrist_Left;
public GameObject Hand_Left;
public GameObject Fingers_Left; //unused
public GameObject Collar_Right;
public GameObject Shoulder_Right;
public GameObject Elbow_Right;
public GameObject Wrist_Right;
public GameObject Hand_Right;
public GameObject Fingers_Right; //unused
public GameObject Hip_Override;
public GameObject Hip_Left;
public GameObject Knee_Left;
public GameObject Ankle_Left;
public GameObject Foot_Left;
public GameObject Hip_Right;
public GameObject Knee_Right;
public GameObject Ankle_Right;
public GameObject Foot_Right;
public int player;
public BoneMask Mask = BoneMask.All;
public bool animated;
public float blendWeight = 1;
private GameObject[] _bones; //internal handle for the bones of the model
private uint _nullMask = 0x0;
private Quaternion[] _baseRotation; //starting orientation of the joints
private Vector3[] _boneDir; //in the bone's local space, the direction of the bones
private Vector3[] _boneUp; //in the bone's local space, the up vector of the bone
private Vector3 _hipRight; //right vector of the hips
private Vector3 _chestRight; //right vectory of the chest
[HideInInspector]
public Vector3[,] bonePos;
private float[] stion=new float[80] {0.2f,-0.6f,1.7f,1.0f,-0.1f,-0.2f,1.9f,1.0f,-0.2f,0.2f,2.0f,1.0f,-0.3f, 0.4f, 2.0f, 1.0f,-0.3f, 0.1f, 2.1f, 1.0f,
-0.3f, -0.2f, 2.0f, 1.0f,-0.2f, -0.3f, 1.8f, 1.0f,-0.3f, -0.3f, 1.7f, 1.0f,-0.1f, 0.1f, 1.9f, 1.0f,
-0.1f, 0.0f, 1.6f, 1.0f,-0.3f, 0.0f, 1.5f, 1.0f,-0.4f, 0.0f, 1.5f, 1.0f,-0.2f, -0.3f, 1.8f, 1.0f,-0.3f, -0.6f, 1.9f, 1.0f,
-0.4f, -0.8f, 2.1f, 1.0f,-0.4f, -0.8f, 2.1f, 1.0f,-0.1f, -0.3f, 1.9f, 1.0f,-0.2f, -0.4f, 1.5f, 1.0f,0.1f, -0.6f, 1.7f, 1.0f
,0.0f, -0.6f, 1.7f, 1.0f};//手动加载的20个骨骼点的数据,以后能够需改传入数据
private Vector4 dfds;
private Matrix4x4 kinectToWorld ;
// Use this for initialization
void Start () {
//store bones in a list for easier access, everything except Hip_Center will be one
//higher than the corresponding Kinect.NuiSkeletonPositionIndex (because of the hip_override)
_bones = new GameObject[25] {
null, Hip_Center, Spine, Shoulder_Center,
Collar_Left, Shoulder_Left, Elbow_Left, Wrist_Left,
Collar_Right, Shoulder_Right, Elbow_Right, Wrist_Right,
Hip_Override, Hip_Left, Knee_Left, Ankle_Left,
null, Hip_Right, Knee_Right, Ankle_Right,
//extra joints to determine the direction of some bones
Head, Hand_Left, Hand_Right, Foot_Left, Foot_Right};
//determine which bones are not available
for(int ii = 0; ii < _bones.Length; ii++)
{
if(_bones[ii] == null)
{
_nullMask |= (uint)(1 << ii);
}
}
//store the base rotations and bone directions (in bone-local space)
_baseRotation = new Quaternion[20];
_boneDir = new Vector3[20];
//first save the special rotations for the hip and spine
_hipRight = Hip_Right.transform.position - Hip_Left.transform.position;
_hipRight = Hip_Override.transform.InverseTransformDirection(_hipRight);
_chestRight = Shoulder_Right.transform.position - Shoulder_Left.transform.position;
_chestRight = Spine.transform.InverseTransformDirection(_chestRight);
//get direction of all other bones
for( int ii = 0; ii < 20; ii++)
{
if((_nullMask & (uint)(1 << ii)) <= 0)
{
//save initial rotation
_baseRotation[ii] = _bones[ii].transform.localRotation;
//if the bone is the end of a limb, get direction from this bone to one of the extras (hand or foot).
if(ii % 4 == 3 && ((_nullMask & (uint)(1 << (ii/4) + 20)) <= 0))
{
_boneDir[ii] = _bones[(ii/4) + 20].transform.position - _bones[ii].transform.position;
}
//if the bone is the hip_override (at boneindex Hip_Left, get direction from average of left and right hips
else if(ii == 12)
{
_boneDir[ii] = ((Hip_Right.transform.position + Hip_Left.transform.position) / 2F) - Hip_Override.transform.position;
}
//otherwise, get the vector from this bone to the next.
else if((_nullMask & (uint)(1 << ii+1)) <= 0)
{
_boneDir[ii] = _bones[ii+1].transform.position - _bones[ii].transform.position;
}
else
{
continue;
}
//Since the spine of the kinect data is ~40 degrees back from the hip,
//check what angle the spine is at and rotate the saved direction back to match the data
if(ii == 1)
{
float angle = Vector3.Angle(transform.up,_boneDir[ii]);
_boneDir[ii] = Quaternion.AngleAxis(-40 + angle,transform.right) * _boneDir[ii];
}
//transform the direction into local space.
_boneDir[ii] = _bones[ii].transform.InverseTransformDirection(_boneDir[ii]);
}
}
//make _chestRight orthogonal to the direction of the spine.
_chestRight -= Vector3.Project(_chestRight, _boneDir[1]);
//make _hipRight orthogonal to the direction of the hip override
Vector3.OrthoNormalize(ref _boneDir[12],ref _hipRight);
bonePos = new Vector3[2,20];
kinectToWorld = Matrix4x4.zero;
kinectToWorld[0,0] = 1;
kinectToWorld[1,1] = 1;
kinectToWorld[1,3] = 1;
kinectToWorld [2, 2] = -1;
kinectToWorld [2, 3] = 2;
kinectToWorld [3, 3] = 1;
}
void Update () {
for (int bone = 0; bone < 20; bone++)
{
dfds = new Vector4 (stion[bone*4],stion[bone*4+1],stion[bone*4+2],stion[bone*4+3]);
bonePos[0,bone] = kinectToWorld.MultiplyPoint3x4(dfds);
}
//update the data from the kinect if necessary
//if(sw.pollSkeleton()){
for( int ii = 0; ii < 20; ii++)
{
if( ((uint)Mask & (uint)(1 << ii) ) > 0 && (_nullMask & (uint)(1 << ii)) <= 0 )
{
RotateJoint(ii);
}
// }
}
}
void RotateJoint(int bone) {
//if blendWeight is 0 there is no need to compute the rotations
if( blendWeight <= 0 ){ return; }
//if the model is not animated, reset rotations to fix twisted joints
if(!animated){_bones[bone].transform.localRotation = _baseRotation[bone];}
Vector3 dir = _boneDir[bone];
Vector3 target;
//if bone % 4 == 0 then it is either an outside shoulder or the hip override
if(bone % 4 == 0)
{
if(bone == 12)
{
target = ((bonePos[player,12] + bonePos[player,16]) / 2F) - bonePos[player,0];
}
else
{
//target = vector from shoulder_center to bone
target = bonePos[player,bone] - bonePos[player,2];
}
}
else
{
//target = vector from previous bone to bone
target = bonePos[player,bone] - bonePos[player,bone-1];
}
//transform it into bone-local space (independant of the transform of the controller)
target = transform.TransformDirection(target);
target = _bones[bone].transform.InverseTransformDirection(target);
//create a rotation that rotates dir into target
Quaternion quat = Quaternion.FromToRotation(dir,target);
//if bone is the spine, add in the rotation along the spine
if(bone == 12)
{
//rotate the chest so that it faces forward (determined by the shoulders)
dir = _chestRight;
target = bonePos[player,4] - bonePos[player,8];
target = transform.TransformDirection(target);
target = _bones[bone].transform.InverseTransformDirection(target);
target -= Vector3.Project(target,_boneDir[bone]);//Projects a vector onto another vector.
quat *= Quaternion.FromToRotation(dir,target);
//Creates a rotation which rotates from fromDirection to toDirection.
}
//if bone is the hip override, add in the rotation along the hips
else if(bone == 12)
{
//rotate the hips so they face forward (determined by the hips)
dir = _hipRight;
target = bonePos[player,16] - bonePos[player,12];
target = transform.TransformDirection(target);
target = _bones[bone].transform.InverseTransformDirection(target);
target -= Vector3.Project(target,_boneDir[bone]);
quat *= Quaternion.FromToRotation(dir,target);
}
//reduce the effect of the rotation using the blend parameter
quat = Quaternion.Lerp(Quaternion.identity, quat, blendWeight);
//apply the rotation to the local rotation of the bone
_bones[bone].transform.localRotation = _bones[bone].transform.localRotation * quat;
return;
}
}
脚本Gameobject与骨骼关节相应
版权声明:本文博客原创文章,博客,未经同意,不得转载。
孙陪你,了解它的权力--Kinect结合的发展Unity3D游戏应用开发的更多相关文章
- 孙陪你,了解它的力量——unity3d流程暂停
干unity3dproject什么时候,有时需要对进程暂停一段时间. 有人建议使用yield return new WaitForSeconds(value);使用的方法如以下: IEnumerato ...
- Kinect for Windows V2和V1对照开发___深度数据获取并用OpenCV2.4.10显示
V1深度分辨率:320x240 V2深度分辨率:512x424 1. 打开深度图像帧的方式 对于V1: hr = m_PNuiSensor->NuiImageStreamOpen( NUI_I ...
- Kinect for Windows V2和V1对照开发___彩色数据获取并用OpenCV2.4.10显示
V1彩色分辨率:640x480 V2彩色分辨率:1920x1080 1,打开彩色图像帧的方式 对于V1: 使用NuiImageStreamOpen方法打开 hr = m_PNuiSensor-> ...
- Kinect一代学习(一):开发环境搭建
https://blog.csdn.net/hongbin_xu/article/details/80722749 我用的是kinect一代(Xbox 360)的所以选择了v1.x的SDK,如果是ki ...
- 使用HTML5开发Kinect体感游戏
一.简介 我们要做的是怎样一款游戏? 在前不久成都TGC2016展会上,我们开发了一款<火影忍者手游>的体感游戏,主要模拟手游章节<九尾袭来 >,用户化身四代,与九尾进行对决, ...
- Kinect for Windows SDK开发入门(一):开发环境配置
[译]Kinect for Windows SDK开发入门(一):开发环境配置 前几天无意中看到微软发布了Kinect for windows sensor,进去看了一下Kinect应用的例子,发现K ...
- Kinect开发学习笔记之(一)Kinect介绍和应用
Kinect开发学习笔记之(一)Kinect介绍和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
- kinect for windows - 初认识
kinect是微软开发的一种计算机输入设备,原来只是用于xbox,kinect负责捕捉用户的动作,让xbox游戏做出相应的反应.很快大家对此非常有兴趣,因此有些geek和组织为kinect开发了驱动和 ...
- Kinect的学习笔记发展(一)Kinect引进和应用
Kinect的学习笔记发展(一)Kinect引进和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
随机推荐
- MongoDB--Getting Started with Java Driver
原文链接 http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-java-driver/ 介绍 本文的目的是让你对怎样使用M ...
- POJ 1422 Air Raid(二分图匹配最小路径覆盖)
POJ 1422 Air Raid 题目链接 题意:给定一个有向图,在这个图上的某些点上放伞兵,能够使伞兵能够走到图上全部的点.且每一个点仅仅被一个伞兵走一次.问至少放多少伞兵 思路:二分图的最小路径 ...
- 在Java中怎样逐行地写文件?
下边是写东西到一个文件里的Java代码. 执行后每一次,一个新的文件被创建,而且之前一个也将会被新的文件替代.这和给文件追加内容是不同的. public static void writeFile1( ...
- Learning Cocos2d-x for WP8(9)——Sprite到哪,我做主
原文:Learning Cocos2d-x for WP8(9)--Sprite到哪,我做主 工程文件TouchesTest.h和TouchesTest.cpp 相关素材文件 事件驱动同样适用于coc ...
- linux下使用vi操作
ESC : 进入命令模式 linux下使用vi后,怎样跳转到文件结尾 pagedown键连续按 虽然我也这么用,但还是太笨了.问了高手,方法是按shift+g,另外,到文件开头是gg. linux ...
- WPF 各种基础动画实现
C# using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste ...
- Portal.MVC
Portal.MVC Portal.MVC 简介 项目是基于MVC4+EF,带有角色,权限,用户中心及账户相关(登录,注册,修改密码,找回密码等)等基本功能.参考的开源项目nopcommerce,这是 ...
- 即时编译和打包您的 Groovy 脚本(转)
在本文中将会涉及到: 使用 CliBuilder 来实现对命令行选项的支持,脚本执行时所需要的参数将通过命令行选项的方式传递. 使用 GroovyClassLoader 加载 Groovy class ...
- poj 2586 Y2K Accounting Bug (贪心)
Y2K Accounting Bug Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8678 Accepted: 428 ...
- SharePoint 2013 创建web应用程序报错"This page can’t be displayed"
错误描写叙述 This page can't be displayed •Make sure the web address http://centeradmin is correct. •Look ...