Games101-动画与模拟(求解常微分方程,刚体与流体)

2024-05-08 20:20

本文主要是介绍Games101-动画与模拟(求解常微分方程,刚体与流体),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Single Particle Simulation

在这里插入图片描述
规定了任何一个物体任何时刻的速度,知道它的初始位置,求它某个时间后的位置?
如果一个物体是匀速直线运动,用初始位置加上速度和时间的乘积即可
如上图,如果想描述一个粒子在一个速度场(理想的情况:只要知道位置,就知道它这个时刻的速度)中如何运动
任何一个粒子在上面的速度场会沿着类似水流的方向往前走
在这里插入图片描述
任何一个位置x和任何时间t,都知道有一个速度
一阶常微分方程ODE,只有对一个变量的微分/导数
在这里插入图片描述
知道速度,一个起始位置,求任何时刻的位置
在这里插入图片描述
** Euler’s Method(欧拉方法)**
将时间细分成很多时间的小块,不断计算t+△t的位置
在t时刻有一个位置、速度和加速度,要算t+△t时刻的位置、速度和加速度
始终用上一个时刻的量去估计下一个时刻的量
在这里插入图片描述
欧拉方法有误差,会迅速的变得不稳定
通过减小△t来减小误差
用不同大小的步长(△t),△t分得越细,模拟就会越准越精确,如果越大(每次取一个速度,让它往前走很长一段),它就和实际的路线偏离得越多
在这里插入图片描述
不稳定:无论取多大的△t,它都会变得和实际结果相差无限远
如上图,不管取多大的步长,路线都肯定不会沿着螺旋形走,而且一定会离开这个螺旋形的速度场(可是事实上,粒子在一个螺旋形的速度场,一定会按照严格的圆周运动的)

一个像羽毛一样的速度场(实际上应该会按照一根曲线慢慢走到水平)(在信号与系统中这种情况叫正反馈,就是出现了一个问题后,这个问题会被无限的放大)
在这里插入图片描述
一切用数值方法解微分方程都会面临的问题
误差:误差其实问题不大,因为在每一步计算都会有误差,累积起来还是有误差。如果用的步长较小,就可以降低误差。对于图形学说,有时候模拟出来的误差问题也不大,因为图形学关注的是模拟看起来的效果,而不是物理上特别的真实
不稳定:更大的问题是不稳定,diverge(不管通过怎样的方法模拟得到的结果,最后都和实际的正确的结果差得越来越远)
在这里插入图片描述
车子撞上一辆摩托出现奇怪的翻滚的现象(在此不确定是否是不稳定造成的,但不稳定确实会出现这样的问题)

Combating Instability

在这里插入图片描述
中点法
自适应改变步长
隐式方法
在这里插入图片描述
不希望欧拉方法在模拟的过程中让结果离得越来越远

  1. 一开始有一个位置和一个方向,可以直接用欧拉方法来模拟某个△t,让其先到达a
  2. 取原始点和a点之间的中点b,考虑它所在的速度
  3. 再回到原始的出发点,应用b点的速度来重新再算一遍欧拉方法,到达c点

仍然用的欧拉方法,只不过用2次,第一次为了得到中点的速度,第二次用中点的速度再算一次欧拉方法
在这里插入图片描述
中点法比欧拉方法准确,是因为多了一个二次的项,也就是说通过中点法模拟出了抛物线的轨迹

可以认为原本的欧拉方法是局部线性的估计模型,而中点法作为修正的欧拉方法其实就算出了局部的二次的模型,所以比一次的模型准确
在这里插入图片描述
自适应改变步长
先正常一个△t算出新的位置XT,将时间减半,得到2个△t,算2遍,从原始点先用△t/2算到一个位置,再使用△t/2再算一次,到达XT/2
如果XT和XT/2这2个点差得挺远,这就意味着将△t分成2部分分别考虑这样做会更准确,那就应该考虑△t/2;如果差得不远,就没必要再分下去

是否将这个点划分成2部分取决于上面2个点差得远不远+

结果:会得到在不同位置选用不同△t来做计算
在这里插入图片描述
隐式欧拉方也叫backward methods

用的永远是下一个时间的速度和加速度(一开始并不知道)来更新此时的
在这里插入图片描述
最后要解方程组,解出一个位置和速度
如果速度和加速度不是按照简单的线性方法叠加的,就不好解。

认为在这一时刻位置知道, 以及下一时刻加速度知道。只需要解下一时刻的位置和速度。

可以用求根公式(如牛顿法),虽然比之前数值的解法要慢很多,但隐式的方法可以提供更好的稳定性
在这里插入图片描述
如何定义一个方法是稳定的?以及它有多么稳定?
通常对于数值方法会定义2个概念来衡量稳定性:
local truncation error:局部的截断误差(也就是每一步(△t)会产生多少误差)
total accumulated error:每一步累积起来的误差

正常情况下研究这2个数是没有意义的,但是应该研究它们的阶(它们和我们取的△t的关系)
隐式的欧拉方法是一阶的:
局部误差是O(h²)
全局误差是O(h)(如果把h减小一半,就期望得到的误差也会减小一半)
h表示取的步长△t
所以阶数越高越好,因为减小h,误差可以成指数倍的减小
在这里插入图片描述
龙格库塔方法是一类解常微分方程ODE方法,特别是非线性的情况
RK4方法是应用最广泛的(四阶的方法)
解决的方法和欧拉方法是一样的:有一个一阶导数,某个量和时间和位置有关,并且有一个初始情况
更新的时候稍微有点不一样:用上一帧的位置用△t(式中的h)乘以某个平均值来更新
4个值是不同位置和不同时间在速度场中的值
在这里插入图片描述
非物理的方法
只通过调整它的不同位置,使得它最后能够满足某种限制

有时,不是基于物理的方法是很好用的(比如作业8中,可以认为弹簧确实是弹簧,但只要它被拉开了某个位置后,可以通过非物理的方法直接改变它的位置,使其立刻回到原状。可以认为它是一个劲度系数无限大的弹簧)

优点:实现快、简单
缺点:有时不能保证能量守恒的性质(因为不是基于物理的)(比如应用在绳子模拟器上,这个绳子会很快停下来,会有很大的能量损失)

Rigid Body Simulation

在这里插入图片描述
刚体不会发生形变,它会让内部所有的点都按照同一种方式去运动(其实一个刚体的运动就是一个粒子的运动,只不过在刚体的模拟中会更多的考虑其他的物理量)

如上图,一个刚体的位置、朝向(旋转的角度)、速度、角速度(旋转有多快)分别对时间求导后得到速度、角速度、加速度、角加速度

使用欧拉方法等数值方法可以求出任意一个时间t之后,刚体对应位置和旋转

Fluid Simulation

在这里插入图片描述
通过模拟形成整个水的体积的小球的位置,来模拟整个水浪花的运动

  1. 认为整个一个水体是由很多不可压缩的刚体小球组成的
  2. 认为水在任何地方都是不可压缩的,即在任何时刻任何位置的密度都是一样的
  3. 给定任何一个时刻这些小球它们分布,都可以知道任何一个地方的密度。如果有任何一个地方的密度变得和水一开始平静的时候的密度不一样,那就需要通过移动小球的位置把这个密度修正过来
  4. 为了做上面的修正,需要知道任何一个点它的密度对所有的小球位置的梯度/导数(任何一个点,如果周围有一圈粒子都会影响它的密度,如果移动任何一个粒子,都会让它的密度发生一定的改变,那就是密度对于这一个粒子的导数)

就是机器学习中的梯度下降
在这里插入图片描述
在物理模拟中模拟大规模的物质用到的2个基本思路:
拉格朗日方法,俗称质点法:模拟水是认为水是由很多圆形的小水滴组成,挨个模拟小水滴。如上图,如果模拟一群小鸟的移动,就关注某一只
欧拉方法,俗称网格法:和解常微分方程的欧拉方法不是一回事。这里指如何去看待模拟的一系列大规模的物体。将整个空间分成不同的网格,不管网格中的东西是出去了还是进来了,只考虑这个网格随着不同的时间是如何变化的。如上图,分成了网格,就知道时间t应该显示黑色的鸟,时间t-1应该显示蓝色的鸟
在这里插入图片描述
物质点方法,既考虑欧拉,又考虑朗格朗日方法
首先认为这些不同的粒子都具有某些材质属性(粒子有质量、粘度等等,都存在点上)
融化的过程在网格中做
再将格子上的信息写回不同的粒子上去

作业

根据题目描述,以及代码看出,mass就是绳子的质点,spring是两个质点直接的弹簧
实现完构造函数,可画出绳子
在这里插入图片描述
显示欧拉,绳子飞了
在这里插入图片描述
半隐式欧拉:
在这里插入图片描述
16个质点
在这里插入图片描述
32仿真步数
在这里插入图片描述
128仿真步数
在这里插入图片描述
显示verlet
在这里插入图片描述
verlet加入阻尼
在这里插入图片描述
半隐式欧拉加上阻尼半隐式欧拉阻尼
在这里插入图片描述
更多步长,阻尼导致更快稳定
在这里插入图片描述
github作业地址

这篇关于Games101-动画与模拟(求解常微分方程,刚体与流体)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971339

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代