用unity实现在线课程

GAMES103-基于物理的计算机动画入门-王华民

的作业1

链接:

课程主页https://games-cn.org/games103/

作业内容:

Angry Bunny: 使兔子模型带有刚体动画效果

参考链接:

games103,作业1(逻辑梳理)_Elsa的迷弟的博客-CSDN博客

Tips: 文章最下方附有全部源码

目录

一,程序演示

二,公式推导

1. 定义动画中下一时刻的v与w

2. 计算冲量j

三,代码实现



一,程序演示

  键盘操作:

  • 点击“L”:发射兔子。
  • 点击“R”:重置兔子。

二,公式推导

 使用冲量法(Impulse)实现物体的刚体碰撞动画:物体的动画与两个参数,位置Position与旋转Rotation有关,而这两个参数的更新分别与线速度v与角速度w相关。冲量法的本质就是在动画计算过程中,时刻求解不断改变的v与w。

1. 定义动画中下一时刻的v与w

解释:

  j表示冲量,定义如下:

假设dt无限小,所以在这段时间内的加速度a可以近似看作常量,​所以可以根据牛顿第二定律F=Ma近似认为

(1.1)新线速度v^{^{new}}

(1.2)新角速度w^{new}

 <1.2.1> 首先定义刚体绕定点转动时,刚体的动量矩L为:

i表示组成刚体的mesh的第i个顶点,进而将等式L展开,可以得到以下形式,

 <1.2.2> 其中,我们将红框部分称为惯性张量I_{ref},同时,惯性张量可整理为:

 <1.2.3> 上式1为单位矩阵。此时,我们可将动量矩L表示为:

  <1.2.4> 因为力矩\tau的物理定义为:

且动量矩L可变形为:

所以,我们可以得出结论,力矩\tau等于动量矩L的一阶导,即:

<1.2.5> 由<1.2.3>知,

  则关于角速度w的一阶导\bigtriangledown w为:

 <1.2.6> 所以,最终下一时刻的新角速度w^{new}为:

<1.2.7> 注意最终一个细节,考虑到要将刚体的局部坐标系转到世界坐标系,所以对上式出现的所有ri左乘一个旋转矩阵,然后进行替换。

<1.2.8> 则新角速度为

 

这时回到开头,根据冲量J的定义,则新角速度为:

2. 计算冲量j

根据上述公式知,只要知道冲量j,就可以计算出新的v^{^{new}}w^{new},然后更新刚体的新位置和状态。

冲量j可根据假设下一时刻的新速度v^{^{new}}已知,从而通过计算得到。

2.1 刚体上某一点的新速度v_{i}^{new}与线速度和角速度的关系为

 2.2 定义一个新的计算符号,将向量叉乘转换为向量*乘

 2.3 这时,根据新旧速度差(v_{i}^{new}v_{i} ),我们可以计算得到冲量j

2.4 此时,除假设的v_{i}^{new}外,一切参数已知。而v_{i}^{new}可通过提前设定的摩擦力系数\mu _{N}\mu _{T}计算得到。

note:由公式知,冲量和当前帧与下一帧的速度差有关,所以速度差越小,冲量越小。表现在动画效果上,即兔子在碰撞多次后,速度不断减缓,并慢慢停了下来

三,代码实现

代码逻辑结构如下,

  1. 首先寻找该帧中所有发生碰撞且未产生回弹的点,然后取这些碰撞点的平均点,参与之后计算。
  2. 计算平均碰撞点的新速度v_{i}^{new}
  3. 根据已知参数,计算系数K与冲量j
  4. 更新线速度v^{^{new}}和角速度w^{new}
  5. (最后在update()函数中,根据LeapFrog Integration蛙跳法更新刚体新的位置position与旋转状态rotation)

脚本源码:

using UnityEngine;
using System.Collections;public class Rigid_Bunny : MonoBehaviour
{bool launched      = false;float dt            = 0.015f;Vector3 v          = new Vector3(0, 0, 0); // velocityVector3 w           = new Vector3(0, 0, 0); // angular velocityfloat mass;                                   // massMatrix4x4 I_ref;                         // reference inertiafloat linear_decay  = 0.999f;               // for velocity decayfloat angular_decay    = 0.98f;                float restitution   = 0.5f;                 // for collisionfloat restitution_T = 0.2f;                      //水平面的摩擦力(自己给定)Vector3 gravity =new Vector3(0.0f, -9.8f, 0.0f);// Use this for initializationvoid Start () {     Mesh mesh = GetComponent<MeshFilter>().mesh;Vector3[] vertices = mesh.vertices;float m = 1;mass=0;for (int i=0; i<vertices.Length; i++) {mass += m;float diag=m*vertices[i].sqrMagnitude;I_ref[0, 0]+=diag;I_ref[1, 1]+=diag;I_ref[2, 2]+=diag;I_ref[0, 0]-=m*vertices[i][0]*vertices[i][0];I_ref[0, 1]-=m*vertices[i][0]*vertices[i][1];I_ref[0, 2]-=m*vertices[i][0]*vertices[i][2];I_ref[1, 0]-=m*vertices[i][1]*vertices[i][0];I_ref[1, 1]-=m*vertices[i][1]*vertices[i][1];I_ref[1, 2]-=m*vertices[i][1]*vertices[i][2];I_ref[2, 0]-=m*vertices[i][2]*vertices[i][0];I_ref[2, 1]-=m*vertices[i][2]*vertices[i][1];I_ref[2, 2]-=m*vertices[i][2]*vertices[i][2];}I_ref [3, 3] = 1;}Matrix4x4 Get_Cross_Matrix(Vector3 a){//Get the cross product matrix of vector aMatrix4x4 A = Matrix4x4.zero;A [0, 0] = 0; A [0, 1] = -a [2]; A [0, 2] = a [1]; A [1, 0] = a [2]; A [1, 1] = 0; A [1, 2] = -a [0]; A [2, 0] = -a [1]; A [2, 1] = a [0]; A [2, 2] = 0; A [3, 3] = 1;return A;}// In this function, update v and w by the impulse due to the collision with//a plane <P, N>void Collision_Impulse(Vector3 P, Vector3 N){// 0. 检测mesh的所有点,是否与平面发生碰撞Matrix4x4 mat_R = Matrix4x4.Rotate(transform.rotation);Vector3 pos = transform.position;Mesh mesh = GetComponent<MeshFilter>().mesh;Vector3[] vertices = mesh.vertices;Vector3 avg_Collision_Point = new Vector3(0.0f, 0.0f, 0.0f); //平均碰撞点int num_Collision = 0;Vector3 ri = new Vector3(0.0f, 0.0f, 0.0f);Vector3 vi = new Vector3(0.0f, 0.0f, 0.0f);//计算在该帧中,模型一共有多少点发生了碰撞,最终取这些碰撞点的平均点参与计算for (int i = 0; i < vertices.Length; i++){//0.0 计算xi在世界坐标中的位置ri = vertices[i];Vector3 xi = pos + mat_R.MultiplyVector(ri);//0.1 计算是否发生碰撞if (Vector3.Dot((xi - P), N) >= 0.0f)continue;//0.2 计算碰撞后mesh是否已经处在回弹状态vi = v + Vector3.Cross(w, mat_R.MultiplyVector(ri));if (Vector3.Dot(vi, N) >= 0.0f)continue;avg_Collision_Point += ri;num_Collision++;}if (num_Collision == 0) //如果模型没有发生碰撞,则返回return;// 1. 如果发生碰撞,则进行模型回弹处理ri = avg_Collision_Point / num_Collision; //此时ri为模型的平均碰撞点Vector3 Rri = mat_R.MultiplyVector(ri);vi = v + Vector3.Cross(w, Rri);// 1.0 计算碰撞后的新速度 vi_newVector3 vi_N = Vector3.Dot(vi, N) * N;Vector3 vi_T = vi - vi_N;float a = Mathf.Max(1.0f - (restitution_T * (1.0f + restitution) * vi_N.magnitude / vi_T.magnitude), 0.0f);Vector3 vi_new_N = -restitution * vi_N;Vector3 vi_new_T = a * vi_T;Vector3 vi_new = vi_new_N + vi_new_T;// 1.1 计算冲量JMatrix4x4 I = mat_R * I_ref * mat_R.transpose;Matrix4x4 K_temp = Get_Cross_Matrix(Rri) * I.inverse * Get_Cross_Matrix(Rri);因为 unity没有提供matrix的加减法,所以手动计算Matrix4x4 K = Matrix4x4.zero;K[0, 0] = 1.0f / mass - K_temp[0, 0];K[0, 1] = -K_temp[0, 1];K[0, 2] = -K_temp[0, 2];K[0, 3] = -K_temp[0, 3];K[1, 0] = -K_temp[1, 0];K[1, 1] = 1.0f / mass - K_temp[1, 1];K[1, 2] = -K_temp[1, 2];K[1, 3] = -K_temp[1, 3];K[2, 0] = -K_temp[2, 0];K[2, 1] = -K_temp[2, 1];K[2, 2] = 1.0f / mass - K_temp[2, 2];K[2, 3] = -K_temp[2, 3];K[3, 0] = -K_temp[3, 0];K[3, 1] = -K_temp[3, 1];K[3, 2] = -K_temp[3, 2];K[3, 3] = 1.0f / mass - K_temp[3, 3];Vector3 J = K.inverse.MultiplyVector(vi_new - vi);//1.2 更新v and wv += 1.0f / mass * J;w += I.inverse.MultiplyVector(Vector3.Cross(Rri, J));}// Update is called once per framevoid Update(){//Game Controlif (Input.GetKey("r")){transform.position = new Vector3(0, 0.6f, 0);transform.rotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);launched = false;}if (Input.GetKey("l")){v = new Vector3(5, 2, 0);w = new Vector3(0, 1, 0); // angular velocitlaunched = true;}if (launched == false)return;// Part I: Update velocities// -- linear velocityv = v + dt * gravity;v *= linear_decay;// -- angular velocityw *= angular_decay;//Part II: Collision ImpulseCollision_Impulse(new Vector3(0, 0.01f, 0), new Vector3(0, 1, 0));Collision_Impulse(new Vector3(2, 0, 0), new Vector3(-1, 0, 0));// Part III: Update position & orientation//Update linear statusVector3 x    = transform.position;x += dt * v;//Update angular statusQuaternion q = transform.rotation;Vector3 wt = 0.5f * dt * w;Quaternion dq = new Quaternion(wt.x, wt.y, wt.z, 0.0f) * q;q.Set(q.x + dq.x, q.y + dq.y, q.z + dq.z, q.w + dq.w);// Part IV: Assign to the objecttransform.position = x;transform.rotation = q;}
}

[计算机动画]Games103-作业1-刚体动画相关推荐

  1. 第36.1节 动画-刚体动画控制

    目录 本节功能 具体实现 存放动画 寻找动画 播放/暂停 复位 加速/减速 最后用一个事件响应来联接这一切 所有代码 本节功能 本节后几个章节会介绍和动画有关的课程. 本节实现一个从3DMAX导出的地 ...

  2. PAOGD个人作业2-角色动画基础(Blender骨骼动画)

    PAOGD_HW2 介绍 开发环境 场景描述 Tips 实现过程和内容 1. 添加骨架 2. 添加约束器 3. 编辑权重 4. 编辑动作与动画 5. 最后效果 实验思考 资源文件下载 介绍 PAOGD ...

  3. games103,作业1(逻辑梳理)

    理论相关部分可以参照刚体动力学 作业框架已知条件 兔子模型的顶点集 每个墙体的上的点P及法线N: 兔子初始速度(角速度w&线速度v) 全局速度衰减系数(linear_decay,angular ...

  4. 计算机动画基本概念,计算机三维动画基本概念简介

    简单介绍三维计算机动画技术的原理和实现,对里面的几项关键部分的概念进行阐述说明. 2 1 0 0年 9月 第 9期 (第 1 2期 )总 4 广西轻工业 G A G IOR A F IH D SR 计 ...

  5. 计算机动画原理课程设计,小议动画运动规律的课程设计论文

    小议动画运动规律的课程设计论文 通过动画实训项目制作,增强实践.实操能力.其次,以项目任务构建教学环节,设计完整的基于工作过程的教学内容,选择课程进入的最佳时机,精心筛选与行业企业合作开发的项目内容, ...

  6. 计算机动画类型中只有一维动画和二维动画,二维动画与计算机技术论文(2)

    二维动画与计算机技术论文篇二 <计算机二维动画艺术设计浅析> [摘要]计算机技术是二维动画艺术设计的主要制作手法,掌握扎实的专业知识是熟练进行计算机二维动画艺术设计的前提.本文概述了利用计 ...

  7. c语言计算机动画生成原理,计算机组成原理动画演示系统 - 源码下载|多媒体|源代码 - 源码中国...

    计算机组成原理动画演示系统 ..........................\flashwork ..........................\.........\Address .... ...

  8. 简述传统动画跟计算机动画的异同点,Flash动画设计与传统动画设计的特点比较研究...

    Flash动画设计与传统动画设计的特点比较研究 计算机是现代社会发展的科技产物,在很大程度上丰富了人们的视野,也加强了人们与外界的联系,传统的动画设计方法不能赋予动画更多的内容,而运用了Flash动画 ...

  9. 计算机动画技术的应用领域,3D动画技术的应用领域

    随着计算机三维影像技术的不断发展,CG动画技术越来越被人们所重视.因其比平面图更直观,更能给受众以身临其境的感觉,尤其适用于那些尚未实现或准备实施的项目,使观者提前领略实施后的精彩结果.三维动画,从简 ...

最新文章

  1. Hadoop运行模式 之 伪分布式运行模式
  2. The copy of Windows is not genuine-微软自己用盗版
  3. 分享Silverlight/WPF/Windows Phone一周学习导读(10月16日-10月22日)
  4. find: paths must precede expression(转)
  5. Memcached:列出所有Key
  6. C# CSV文件读取(带换行单元格中内容处理)
  7. 耗时两年,19岁小伙采用230片纯74逻辑芯片搭建出32位处理器!可玩贪吃蛇
  8. 升级无法登录_JeeSite v4.2.2 发布,代码生成增强、Boot 2.3、短信登录、性能提升...
  9. Mybatis如何给某个包中类起别名,以及起别名报错的解决方案
  10. Unity 工具 之 XChart UGUI 表格工具,轻松简单的帮你实现需要的数据图表形式,建议 Mark 一下
  11. 人性的弱点-读书笔记
  12. 如何快速成为数据分析师?
  13. 蛋白质非标记定量技术lable free
  14. Flink无法在yarn提交任务:取消检查虚拟内存
  15. bugku ctf 多种方法解决 (在做题过程中你会得到一个二维码图片)
  16. 洗碗机,加速中国化才能更适合中国厨房
  17. V型反弹的名场面,荣耀能否在海外市场“荣耀”?
  18. 北斗导航 | ION GNSS+ 2014到 ION GNSS+ 2017会议论文下载:ION 美国导航学会
  19. 大学物理实验长度的测量实验报告_大学物理实验长度的测量实验总结
  20. Linux内核cgroup使用介绍

热门文章

  1. ByteBuff常用方法,使用
  2. Soul网关源码分析-环境搭建
  3. 从微信的成功看移动AppUI设计的精髓
  4. 用GATK进行二代测序数据 SNP Calling 流程:(四)变异过滤
  5. 5G/NR 5G核心网(5GC)之网络功能服务通信
  6. 游戏中的语音聊天方案
  7. 基于机智云物联网平台的实验室智能安防报警系统
  8. 《我和我的祖国》之《夺冠》:所有人都在欢呼,只有他在哭......
  9. 响应式微服务_低风险整体式微服务演进第一部分
  10. MySQL-InnoDB引擎-架构和事务原理