GAMES 103 动画基础作业1 Shape Matching 浅浅解析


简介

作业1简单实现了一个以一定初始速度和角速度的模型和墙壁碰撞的效果.
总共讲解了三种算法

  1. impulse (脉冲法)

  2. Shape Matching(基于形状保持的算法, 不包含物理特性)

  3. Penalty methods

Shape Matching 可以说是最简单的方法之一

因为完全不涉及角速度. 基础逻辑理论就是, 当模型和墙壁发生碰撞的时候.这些碰撞的粒子会产生相反的形变但是. 我们强制将其整理保持形状的一致性. 就是先形变. 再变回来.
由于形变的步骤. 是中间步骤. 不会展示出来. 所以效果还是挺好的.

Image



TIPS

code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rigid_Bunny_by_Shape_Matching : MonoBehaviour
{
	public bool launched = false;
	Vector3[] X; // world position
	Vector3[] Y; // temp world position
	Vector3[] Q; // Local coordinates
	Vector3[] V; // speed
	Vector3[] OldX;
	Matrix4x4 QQt = Matrix4x4.zero;
	Vector3 G = new Vector3(0.0f, -9.8f, 0.0f);
	float linear_decay = 0.999f;
	Vector3 ground = new Vector3(0, 0.01f, 0);
	Vector3 groundNormal = new Vector3(0, 1, 0);
	Vector3 wall = new Vector3(2.01f, 0, 0);
	Vector3 wallNormal = new Vector3(-1, 0, 0);
	float mu_T = 0.5f;  // μ_T may be coefficient of air resistance
	float mu_N = 5.0f; // μ_N may be Coefficient of Restitution
	float m_timer = 0;


	// Start is called before the first frame update
	void Start()
    {
    	Mesh mesh = GetComponent().mesh;
        V = new Vector3[mesh.vertices.Length];
        X = mesh.vertices;
		Y = mesh.vertices;
		OldX = mesh.vertices;
        Q = mesh.vertices;

        //Centerizing Q.
        Vector3 c=Vector3.zero;
        for(int i=0; i 1.0f) value= 1.0f;
	        float phi = Mathf.Acos(value);
	        float lambda2=(I_c+2*k_root*Mathf.Cos(phi/3))/3.0f;
	        float lambda=Mathf.Sqrt(lambda2);
	        
	        float III_u = Mathf.Sqrt(III_c);
	        if(det<0)   III_u=-III_u;
	        float I_u = lambda + Mathf.Sqrt(-lambda2 + I_c + 2*III_u/lambda);
	        float II_u=(I_u*I_u-I_c)*0.5f;
	        
	        
	        float inv_rate, factor;
	        inv_rate=1/(I_u*II_u-III_u);
	        factor=I_u*III_u*inv_rate;
	        
	       	Matrix4x4 U = Matrix4x4.zero;
			U[0,0]=factor;
	        U[1,1]=factor;
	        U[2,2]=factor;
	        
	        factor=(I_u*I_u-II_u)*inv_rate;
	        for(int i=0; i<3; i++)
	        for(int j=0; j<3; j++)
	            U[i,j]+=factor*C[i,j]-inv_rate*C2[i,j];
	        
	        inv_rate=1/III_u;
	        factor=II_u*inv_rate;
	        inv_U[0,0]=factor;
	        inv_U[1,1]=factor;
	        inv_U[2,2]=factor;
	        
	        factor=-I_u*inv_rate;
	        for(int i=0; i<3; i++)
	        for(int j=0; j<3; j++)
	            inv_U[i,j]+=factor*U[i,j]+inv_rate*C[i,j];
	    }
	    
	    Matrix4x4 R=Matrix4x4.zero;
	    for(int ii=0; ii<3; ii++)
	    for(int jj=0; jj<3; jj++)
	    for(int kk=0; kk<3; kk++)
	        R[ii,jj]+=F[ii,kk]*inv_U[kk,jj];
	    R[3,3]=1;
	    return R;
	}

	// Update the mesh vertices according to translation c and rotation R.
	// It also updates the velocity.
	void Update_Mesh(Vector3 c, Matrix4x4 R, float inv_dt)
   	{
   		for(int i=0; i().mesh;
		mesh.vertices=X;
   	}

	void Collision(float inv_dt)
	{
		for(int i=0; i

TRICK

PIPELINE

计算 C (模型质心坐标)

计算 A (通过A计算得到R, 即 旋转矩阵) == 从A得到R. 老师已经提供了.

更新顶点坐标

Trick

在处理碰撞的函数中. 里面的参数是自己调整的参数. 比如 5.0f 逻辑上 μ_T μ_N 都应该是一个小于1的数. 但是, 测试后感觉效果不是特别好. 如果你知道为什么的话, 请留言.

请看完bilibli 4个视屏后开始自己的作业.

参考链接

配置VS 作为 Unity 的配置环境
https://blog.csdn.net/qq_34405576/article/details/105572069

源码参考师弟写出来的, 大部分是抄的嘿嘿~~ 侵权删除.