简介

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. 搜索算法1——聊聊dfs与回溯

    搜索算法1--聊聊dfs与回溯 目录 1.dfs 的概念 $\ \ \ $1.1 dfs 的概念 2.dfs 的做法 $\ \ \ $2.1 为什么要用 dfs $\ \ \ $2.2 dfs 如何实 ...

  2. 详细介绍Java的SPI机制

    一.什么是SPI机制 SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.s ...

  3. kettle介绍-Step之Return steps metrics

    Return steps metrics转换步骤信息统计介绍 转换步骤信息统计步骤可以用于统计当前转换中的其它步骤信息,包括步骤执行后的输入行数.输入行数.读入行数.更新行数等.此步骤可以直接拖入转换 ...

  4. P1166题解

    思路 花了半天去理解题意--意思是说给你一个选手的滚球情况,打出他当前的成绩.简单的说这题就是一个模拟(我才不是因为懒才找模拟题写的)思路也很简单,对每一轮进行以下几个判断就行啦: 首先判断有没有在两 ...

  5. Asp.net core 少走弯路系列教程(二)HTML 学习

    前言 新人学习成本很高,网络上太多的名词和框架,全部学习会浪费大量的时间和精力. 新手缺乏学习内容的辨别能力,本系列文章为新手过滤掉不适合的学习内容(比如多线程等等),让新手少走弯路直通罗马. 作者认 ...

  6. ArcGIS拼接、镶嵌同一空间位置的不同遥感影像

      本文介绍在ArcGIS下属的ArcMap软件中,对处于同一空间位置的多幅栅格图像加以拼接.融合与叠加等操作的方法.   假如现在我们分别有以下三幅栅格图像,三者分别是独立的三个图层.第一个图层如下 ...

  7. Nacos简介—4.Nacos架构和原理

    Nacos简介-4.Nacos架构和原理 大纲 1.Nacos的定位和优势 2.Nacos的整体架构 3.Nacos的配置模型 4.Nacos内核设计之一致性协议 5.Nacos内核设计之自研Dist ...

  8. 一个基于 C# Unity 开发的金庸群侠传 3D 版,直呼牛逼!

    前言 大家应该都知道 Unity 游戏引擎是基于 C# 编程语言开发的,今天大姚给大家分享一个基于 C# Unity 开发的金庸群侠传 3D 版,该游戏真的是勾起了一代人的慢慢回忆. 项目介绍 JYX ...

  9. 摸鱼神器:打造一款让VS Code成为你私人影院的插件

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  10. WPF中Resx文件中添加Byte[]

    参考:https://learn.microsoft.com/zh-tw/dotnet/api/system.resources.resxresourcewriter.generate?view=wi ...