孙陪你,了解它的权力--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 ...
随机推荐
- Flash Android ANE打包之基本流程
搭建环境这里就不详细说明了 一.Android本地库编写 1.从Flash Air SDK中提取需要的jar包 Android下需要的jar包在Flash Air SDK/lib/android目录下 ...
- Swift的属性,方法,下标脚本以及继承
从这篇章节起,Swift编程语言指南大部分的重要内容在于概念,代码并非太多.理解Swift的面向对象理念,语法以及类结构,构造析构过程对于非常好的应用Swift语言将会有比較大的帮助. 属性 存储属性 ...
- H264 编解码框架简单介绍
阅读完H264/AVC 编解码器的介绍,脑海中仅仅是留下下面三条: 1.H264并没有明白规定一个编解码器怎样实现,仅仅是规定了一个编码后的视频比特流的句法,和该比特流的解码方法,这个与MPEG 类似 ...
- JFinal开发8个常见问题
下面是8个最常见的问题总结. 1.Can not create instance of class: demo.DemoConfig. 觉得应该是你的路径有问题, 打开你项目的java build p ...
- php查找字符串是否存在
strstr //搜索字符串在另一字符串中的首次出现(对大小写敏感) //该函数返回字符串的其余部分(从匹配点).如未找到则返回 false stristr //查找字符串在另一字符串中第一次出现的位 ...
- windows phone (25) Canvas元素B
原文:windows phone (25) Canvas元素B ZIndex 这也是一个附加属性,表示canvas的children集合内的子元素的显示顺序,在canvas中的元素默认情况下是后面的 ...
- UDE-00008 ORA-31626 ORA-06512 ORA-25254
今天在导出一个模式的时候,约140GB,出现例如以下错误: UDE-00008: operation generated ORACLE error 31626 ORA-31626: job does ...
- poj 3250 Bad Hair Day (单调栈)
Bad Hair Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14883 Accepted: 4940 Des ...
- Ibatis之3个不经常使用的Query方法
1.queryForObject /** * Executes a mapped SQL SELECT statement that returns data to populate * the su ...
- Java进阶 创建和销毁对象
最近准备写点Javase的东西,希望可以帮助大家写出更好的代码. 1.给不可实例化的类提供私有构造器 比如:每个项目中都有很多工具类,提供了很多static类型的方法供大家使用,谁也不希望看到下面的代 ...