简介

PDB 比 隐式积分法 速度快很多.

全称 Position Based Dynamics 粒子动力学系统, 什么是PBD呢? 个人的理解就是, 多次迭代, 达到一步的稳定状态. 然后更新整个系统的状态. 简单的说, 就是对于局部的模拟扩展到全局. 经过一定的迭代, 达到稳态.

可以参看Image中的第一幅图片. 对于单个系统的更新, 导致的全局的收敛. 但是必须达到多次迭代, 才能达到类似整体的一次迭代.

参考文献

师弟代码~~

Q&A

Q1

In the Update function, set up the PBD solver as a particle system. Specifically, for every vertex, damp the velocity (as in 1.a), update the velocity by gravity, and finally

update the position:

\[\mathbf{x}_{i} \leftarrow \mathbf{x}_{i}+\Delta t \mathbf{v}_{i}
\]

简单而言就是, 改变速度. 通过重力改变, 然后加上速度衰减, 然后根据速度的改变更新坐标.

			V[i] += g * t;
V[i] *= damping;
X[i] += t * V[i];

Q2

1.b. Strain limiting (4 Points) In the Strain Limiting function, implement position-based

dynamics in a Jacobi fashion. The basic idea is to define two temporary arrays sum x[] and sum n[]

to store the sums of vertex position updates and vertex count updates. At the beginning of the

function, set both arrays to zeros. After that, for every edge e connecting i and j, update the arrays:

\[\begin{array}{ll}
\operatorname{sum}_{\mathbf{}} \mathbf{x}_{i} \leftarrow \operatorname{sum}_{-} \mathbf{x}_{i}+\frac{1}{2}\left(\mathbf{x}_{i}+\mathbf{x}_{j}+L_{e} \frac{\mathbf{x}_{i}-\mathbf{x}_{j}}{\left\|\mathbf{x}_{i}-\mathbf{x}_{j}\right\|}\right), & \text { sum_n }_{i} \leftarrow \text { sum_n }_{i}+1, \\
\text { sum_ } \mathbf{x}_{j} \leftarrow \text { sum_ } \mathbf{x}_{j}+\frac{1}{2}\left(\mathbf{x}_{i}+\mathbf{x}_{j}-L_{e} \frac{\mathbf{x}_{i}-\mathbf{x}_{j}}{\left\|\mathbf{x}_{i}-\mathbf{x}_{j}\right\|} \|,\right. & \text { sum_n }_{j} \leftarrow \text { sum_ } n_{j}+1 .
\end{array}
\]

Finally, update each vertex as:

\[\mathbf{v}_{i} \leftarrow \mathbf{v}_{i}+\frac{1}{\Delta t}\left(\frac{0.2 \mathbf{x}_{i}+s u m_{-} \mathbf{x}_{i}}{0.2+s u m_{-} n_{i}}-\mathbf{x}_{i}\right), \quad \mathbf{x}_{i} \leftarrow \frac{0.2 \mathbf{x}_{i}+s u m_{-} \mathbf{x}_{i}}{0.2+\operatorname{sum_n} n_{i}}
\]

作者给出的 \(\alpha = 0.2f\) 可以参考最后一张图.

	void Strain_Limiting()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] vertices = mesh.vertices; //Apply PBD here.
Vector3[] sum_x = new Vector3[vertices.Length];
int[] num_x = new int[vertices.Length];
for(int i=0; i<vertices.Length; i++)
{
sum_x[i] = new Vector3(0, 0, 0);
num_x[i] = 0;
} for(int ei = 0; ei < L.Length; ei++)
{
int i = E[ei * 2];
int j = E[ei * 2 + 1];
Vector3 xi_xj = vertices[i] - vertices[j];
float len_ij = L[ei] / xi_xj.magnitude; sum_x[i] += (vertices[i] + vertices[j] + len_ij * (xi_xj)) / 2;
sum_x[j] += (vertices[i] + vertices[j] - len_ij * (xi_xj)) / 2;
num_x[i]++;
num_x[j]++;
}
for(int i=0; i<vertices.Length; i++)
{
if (i == 0 || i == 20) continue;
V[i] += ((0.2f * vertices[i] + sum_x[i]) / (num_x[i] + 0.2f) -
vertices[i]) / t;
vertices[i] = (0.2f * vertices[i] + sum_x[i]) / (num_x[i] + 0.2f);
}
mesh.vertices = vertices;
}

image

code

using UnityEngine;
using System.Collections; public class PBD_model: MonoBehaviour { float t= 0.0333f;
float damping= 0.99f;
int[] E;
float[] L;
Vector3[] V;
Vector3 g = new Vector3(0, -9.8f, 0);
float r = 2.7f; // Use this for initialization
void Start ()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh; //Resize the mesh.
int n=21;
Vector3[] X = new Vector3[n*n];
Vector2[] UV = new Vector2[n*n];
int[] T = new int[(n-1)*(n-1)*6];
for(int j=0; j<n; j++)
for(int i=0; i<n; i++)
{
X[j*n+i] =new Vector3(5-10.0f*i/(n-1), 0, 5-10.0f*j/(n-1));
UV[j*n+i]=new Vector3(i/(n-1.0f), j/(n-1.0f));
}
int t=0;
for(int j=0; j<n-1; j++)
for(int i=0; i<n-1; i++)
{
T[t*6+0]=j*n+i;
T[t*6+1]=j*n+i+1;
T[t*6+2]=(j+1)*n+i+1;
T[t*6+3]=j*n+i;
T[t*6+4]=(j+1)*n+i+1;
T[t*6+5]=(j+1)*n+i;
t++;
}
mesh.vertices = X;
mesh.triangles = T;
mesh.uv = UV;
mesh.RecalculateNormals (); //Construct the original edge list
int[] _E = new int[T.Length*2];
for (int i=0; i<T.Length; i+=3)
{
_E[i*2+0]=T[i+0];
_E[i*2+1]=T[i+1];
_E[i*2+2]=T[i+1];
_E[i*2+3]=T[i+2];
_E[i*2+4]=T[i+2];
_E[i*2+5]=T[i+0];
}
//Reorder the original edge list
for (int i=0; i<_E.Length; i+=2)
if(_E[i] > _E[i + 1])
Swap(ref _E[i], ref _E[i+1]);
//Sort the original edge list using quicksort
Quick_Sort (ref _E, 0, _E.Length/2-1); int e_number = 0;
for (int i=0; i<_E.Length; i+=2)
if (i == 0 || _E [i + 0] != _E [i - 2] || _E [i + 1] != _E [i - 1])
e_number++; E = new int[e_number * 2];
for (int i=0, e=0; i<_E.Length; i+=2)
if (i == 0 || _E [i + 0] != _E [i - 2] || _E [i + 1] != _E [i - 1])
{
E[e*2+0]=_E [i + 0];
E[e*2+1]=_E [i + 1];
e++;
} L = new float[E.Length/2];
for (int e=0; e<E.Length/2; e++)
{
int i = E[e*2+0];
int j = E[e*2+1];
L[e]=(X[i]-X[j]).magnitude;
} V = new Vector3[X.Length];
for (int i=0; i<X.Length; i++)
V[i] = new Vector3 (0, 0, 0);
} void Quick_Sort(ref int[] a, int l, int r)
{
int j;
if(l<r)
{
j=Quick_Sort_Partition(ref a, l, r);
Quick_Sort (ref a, l, j-1);
Quick_Sort (ref a, j+1, r);
}
} int Quick_Sort_Partition(ref int[] a, int l, int r)
{
int pivot_0, pivot_1, i, j;
pivot_0 = a [l * 2 + 0];
pivot_1 = a [l * 2 + 1];
i = l;
j = r + 1;
while (true)
{
do ++i; while( i<=r && (a[i*2]<pivot_0 || a[i*2]==pivot_0 && a[i*2+1]<=pivot_1));
do --j; while( a[j*2]>pivot_0 || a[j*2]==pivot_0 && a[j*2+1]> pivot_1);
if(i>=j) break;
Swap(ref a[i*2], ref a[j*2]);
Swap(ref a[i*2+1], ref a[j*2+1]);
}
Swap (ref a [l * 2 + 0], ref a [j * 2 + 0]);
Swap (ref a [l * 2 + 1], ref a [j * 2 + 1]);
return j;
} void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
} void Strain_Limiting()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] vertices = mesh.vertices; //Apply PBD here.
Vector3[] sum_x = new Vector3[vertices.Length];
int[] num_x = new int[vertices.Length];
for(int i=0; i<vertices.Length; i++)
{
sum_x[i] = new Vector3(0, 0, 0);
num_x[i] = 0;
} for(int ei = 0; ei < L.Length; ei++)
{
int i = E[ei * 2];
int j = E[ei * 2 + 1];
Vector3 xi_xj = vertices[i] - vertices[j];
float len_ij = L[ei] / xi_xj.magnitude; sum_x[i] += (vertices[i] + vertices[j] + len_ij * (xi_xj)) / 2;
sum_x[j] += (vertices[i] + vertices[j] - len_ij * (xi_xj)) / 2;
num_x[i]++;
num_x[j]++;
}
for(int i=0; i<vertices.Length; i++)
{
if (i == 0 || i == 20) continue;
V[i] += ((0.2f * vertices[i] + sum_x[i]) / (num_x[i] + 0.2f) -
vertices[i]) / t;
vertices[i] = (0.2f * vertices[i] + sum_x[i]) / (num_x[i] + 0.2f);
}
mesh.vertices = vertices;
} void Collision_Handling()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] X = mesh.vertices; //For every vertex, detect collision and apply impulse if needed.
GameObject sphere = GameObject.Find("Sphere");
Vector3 c = sphere.transform.position;
//Handle colllision.
for (int i = 0; i < X.Length; i++)
{
if (i == 0 || i == 20) continue;
float distance = (X[i] - c).magnitude;
if (distance < r)
{
V[i] += (c + r * (X[i] - c) / distance - X[i]) / t;
X[i] = c + r * (X[i] - c) / distance;
} } mesh.vertices = X;
} // Update is called once per frame
void Update ()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] X = mesh.vertices; for(int i=0; i<X.Length; i++)
{
if(i==0 || i==20) continue;
//Initial Setup
V[i] += g * t;
V[i] *= damping;
X[i] += t * V[i];
}
mesh.vertices = X; for(int l=0; l<32; l++)
Strain_Limiting (); Collision_Handling (); mesh.RecalculateNormals (); } }

Games 103 cloth PDB 浅析的更多相关文章

  1. ORACLE 12C PDB 维护基础介绍

    来自:http://www.xifenfei.com/2013/05/oracle-12c-pdb-%E7%AE%A1%E7%90%86%E4%BB%8B%E7%BB%8D1.html CDB和PDB ...

  2. PDB Files: What Every Developer Must Know

    Reference:  http://www.wintellect.com/blogs/jrobbins/pdb-files-what-every-developer-must-know Most d ...

  3. Linux系统编程——进程调度浅析

    概述 操作系统要实现多进程.进程调度不可缺少. 有人说,进程调度是操作系统中最为重要的一个部分.我认为这样的说法说得太绝对了一点,就像非常多人动辄就说"某某函数比某某函数效率高XX倍&quo ...

  4. 安装12C小问题及pdb表空间配置

    安装12C小问题及pdb表空间配置 一.安装 1.RPM包 #安装12C需要安装的rpm包,官网搜索,做个记录 bc binutils-2.23.52.0.1-12.el7(x86_64) compa ...

  5. Oracle 12c CDB PDB

    先说基本用法: 先按11G之前进行 conn / as sysdba; create user test identifed by test; ORA-65096: 公用用户名或角色名无效. 查官方文 ...

  6. pdb文件及引发的思考

    最初只想知道线上iis里需要不需要pdb文件,了解部分之后对于.net底层产生了浓厚的兴趣,看了一点点资料 资料来源: https://www.cnblogs.com/itech/archive/20 ...

  7. 2018ACM山东省赛 Games(dp取数)

    Games Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description Alice and Bob ...

  8. objectARX2010及其以上版本使用publish打印(发布)图纸,后台布局打印图纸例子浅析

    AutoCAD 2010版本开始新增了一个发布图纸的功能,可以后台打印图纸,以下是ADN官方博客例子浅析 原文地址 https://adndevblog.typepad.com/autocad/201 ...

  9. Oracle 12c 多租户家族(12c 18c 19c)如何在 PDB 中添加 HR 模式

    Oracle 12c 多租户家族(12c [12.2.0.1].18c [12.2.0.2].19c [12.2.0.3])如何在 PDB 中添加模式:19c (19.3) 手工添加示例 HR 用户 ...

  10. protobuf 协议浅析

    目录 Protobuf 协议浅析 1. Protobuf 介绍 1.1 Protobuf 基本概念 1.2 Protobuf 的优点 1.3 Protobuf, JSON, XML 的区别 2. Pr ...

随机推荐

  1. 测试用例Xmind转XML格式教程

    运行环境: Python版本:3.7(Python2.x和Python2.x均可) 第三方库:xmind2testlink/xmind2testcase 1.安装Python(以Python3.x为例 ...

  2. Goland搭建Go开发环境

    1.下载和安装Golang 下载链接: 谷歌链接:https://golang.google.cn/dl/ 国内链接:https://studygolang.com/dl 安装示意图: 安装完成后配置 ...

  3. 多线程的waiting与notify

    一.waiting()与notify() /* 进入到TimeWaiting(计时等待)有两种方式 1.使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Block ...

  4. TVM:使用自动调度优化算子

    与基于模板的AutoTVM不同(会依赖手动模板定义搜索空间),自动调度器不需要任何模板.用户只需要编写计算声明,而不需要任何调度命令或模板.自动调度器可以自动生产一个大的搜索空间,并在空间中找到一个好 ...

  5. 操作系统:Linux如何获取所有设备信息

    本节了解下Linux是如何管理设备的,将从Linux如何组织设备开始,然后研究设备相关的数据结构,最后写一个Linux设备驱动实例. 感受一下Linux下的设备信息 Linux的设计哲学是一起皆是文件 ...

  6. CSS 之overflow属性简结

    CSS的overflow 属性用来处理一个元素的尺寸超出其容器尺寸的情况.当一个元素包含的内容超粗自身的大小时,就会发生内容溢出,这种情况,可以对内容进行"裁剪",只让一部分内容可 ...

  7. B1036 跟奥巴马一起编程

    美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统.2014年底,为庆祝"计算机科学教育周"正式启动,奥巴马编写了很简单的计算机代 ...

  8. codeup之查找

    Description 输入数组长度 n 输入数组 a[1-n] 输入查找个数m 输入查找数字b[1-m] 输出 YES or NO 查找有则YES 否则NO . Input 输入有多组数据. 每组输 ...

  9. 【最新】MySQL 5.6 保姆级安装详细教程

    MySQL5.6简介 MySQL 5.6 是 MySQL 数据库管理系统的一个重要版本,以其稳定性.性能优化和功能扩充受到广泛关注与使用.该版本在数据库领域中提供了更加高效的数据处理能力.增强的复制功 ...

  10. 布局控件:Grid和StackPanel

    布局控件:Grid和StackPanel 本文同时为b站WPF课程的笔记,相关示例代码 一个窗口顶上的部分叫做非客户区,下面的部分叫做客户区域.非客户区域主要就是一个Title和三个窗口样式按钮.我们 ...