Games 103 cloth PDB 浅析
简介
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:
\]
简单而言就是, 改变速度. 通过重力改变, 然后加上速度衰减, 然后根据速度的改变更新坐标.
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:
\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:
\]
作者给出的 \(\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 浅析的更多相关文章
- 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 ...
- PDB Files: What Every Developer Must Know
Reference: http://www.wintellect.com/blogs/jrobbins/pdb-files-what-every-developer-must-know Most d ...
- Linux系统编程——进程调度浅析
概述 操作系统要实现多进程.进程调度不可缺少. 有人说,进程调度是操作系统中最为重要的一个部分.我认为这样的说法说得太绝对了一点,就像非常多人动辄就说"某某函数比某某函数效率高XX倍&quo ...
- 安装12C小问题及pdb表空间配置
安装12C小问题及pdb表空间配置 一.安装 1.RPM包 #安装12C需要安装的rpm包,官网搜索,做个记录 bc binutils-2.23.52.0.1-12.el7(x86_64) compa ...
- Oracle 12c CDB PDB
先说基本用法: 先按11G之前进行 conn / as sysdba; create user test identifed by test; ORA-65096: 公用用户名或角色名无效. 查官方文 ...
- pdb文件及引发的思考
最初只想知道线上iis里需要不需要pdb文件,了解部分之后对于.net底层产生了浓厚的兴趣,看了一点点资料 资料来源: https://www.cnblogs.com/itech/archive/20 ...
- 2018ACM山东省赛 Games(dp取数)
Games Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description Alice and Bob ...
- objectARX2010及其以上版本使用publish打印(发布)图纸,后台布局打印图纸例子浅析
AutoCAD 2010版本开始新增了一个发布图纸的功能,可以后台打印图纸,以下是ADN官方博客例子浅析 原文地址 https://adndevblog.typepad.com/autocad/201 ...
- 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 用户 ...
- protobuf 协议浅析
目录 Protobuf 协议浅析 1. Protobuf 介绍 1.1 Protobuf 基本概念 1.2 Protobuf 的优点 1.3 Protobuf, JSON, XML 的区别 2. Pr ...
随机推荐
- 搜索算法1——聊聊dfs与回溯
搜索算法1--聊聊dfs与回溯 目录 1.dfs 的概念 $\ \ \ $1.1 dfs 的概念 2.dfs 的做法 $\ \ \ $2.1 为什么要用 dfs $\ \ \ $2.2 dfs 如何实 ...
- 详细介绍Java的SPI机制
一.什么是SPI机制 SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.s ...
- kettle介绍-Step之Return steps metrics
Return steps metrics转换步骤信息统计介绍 转换步骤信息统计步骤可以用于统计当前转换中的其它步骤信息,包括步骤执行后的输入行数.输入行数.读入行数.更新行数等.此步骤可以直接拖入转换 ...
- P1166题解
思路 花了半天去理解题意--意思是说给你一个选手的滚球情况,打出他当前的成绩.简单的说这题就是一个模拟(我才不是因为懒才找模拟题写的)思路也很简单,对每一轮进行以下几个判断就行啦: 首先判断有没有在两 ...
- Asp.net core 少走弯路系列教程(二)HTML 学习
前言 新人学习成本很高,网络上太多的名词和框架,全部学习会浪费大量的时间和精力. 新手缺乏学习内容的辨别能力,本系列文章为新手过滤掉不适合的学习内容(比如多线程等等),让新手少走弯路直通罗马. 作者认 ...
- ArcGIS拼接、镶嵌同一空间位置的不同遥感影像
本文介绍在ArcGIS下属的ArcMap软件中,对处于同一空间位置的多幅栅格图像加以拼接.融合与叠加等操作的方法. 假如现在我们分别有以下三幅栅格图像,三者分别是独立的三个图层.第一个图层如下 ...
- Nacos简介—4.Nacos架构和原理
Nacos简介-4.Nacos架构和原理 大纲 1.Nacos的定位和优势 2.Nacos的整体架构 3.Nacos的配置模型 4.Nacos内核设计之一致性协议 5.Nacos内核设计之自研Dist ...
- 一个基于 C# Unity 开发的金庸群侠传 3D 版,直呼牛逼!
前言 大家应该都知道 Unity 游戏引擎是基于 C# 编程语言开发的,今天大姚给大家分享一个基于 C# Unity 开发的金庸群侠传 3D 版,该游戏真的是勾起了一代人的慢慢回忆. 项目介绍 JYX ...
- 摸鱼神器:打造一款让VS Code成为你私人影院的插件
@charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...
- WPF中Resx文件中添加Byte[]
参考:https://learn.microsoft.com/zh-tw/dotnet/api/system.resources.resxresourcewriter.generate?view=wi ...