Bingo, Computer Graphics & Game Developer

1.

原式中已知两点都是位于交点的两侧

这样也就求出了最后的结果

2.

这里Dot(n, face[0]) - c得到的方程式其实并不是将face[0]代入到ax+by+cax + by + c

而是代入到于ax+by+cax + by + c垂直的真实裁剪线中去的

这里有多重方法可以证明 因为两种Clip情况都相似 所以只取一种情况予以证明

(1).

n=(x1x2,y1y2)c=[x1.(x2x1)+y1.(y2y1)]n = (x1 - x2, y1 - y2) c = -[x1 \ldotp (x2 - x1) + y1 \ldotp (y2 - y1)]

n.(x,y)c=(x1x2).x+(y1y2).y+x1.(x2x1)+y1.(y2y1)=(x2x1).(xx1)+(y2y1).(yy1)n \ldotp (x, y) - c = (x1 - x2) \ldotp x + (y1 - y2) \ldotp y + x1 \ldotp (x2 - x1) + y1 \ldotp (y2 - y1) = (x2 - x1) \ldotp (x - x1) + (y2 - y1) \ldotp (y - y1)

这个式子是两个向量的点积

这里的几何意义就表明

(2).上一则方法是一步步推导实现的

第二种方法是直接给出这条真实裁剪线的方程 因为垂直 所以斜率乘积为-1 已知直线斜率为 k=abk = -\frac{a}{b}

那么所求直线斜率为 k=bak = \frac{b}{a} 并且过(x1,y1)(x1, y1) (两点式已知a = y2 - y1, b = x1 - x2

可得 k.x+y1k.x1=yk \ldotp x + y1 - k \ldotp x1 = y

最终式子为

(x1x2).x+y1.(y2y1)(x1x2).x1=y.(y2y1)(x1 - x2) \ldotp x + y1 \ldotp (y2 - y1) - (x1 - x2) \ldotp x1 = y \ldotp (y2 - y1)

(x1x2).(xx1)=(yy1)(y2y1)(x1 - x2) \ldotp (x - x1) = (y - y1)(y2 - y1)也就是第一种情况中所求得的式子 可以证明得到Dot(n, face[0]) - c得到的方程式的的确确就是垂直于已知直线并且过(x1,y1)(x1, y1)点的直线

2.

在最后计算深度的时候需要注意到的是倘若clip计算出来的边长都在reference face内部 那么两点都为contact point



1.摩擦力的方向与大小计算与冲量相似 需要计算出与碰撞法线方向垂直的切线方向

这里定义切线的方向为两个对象之间相对速度的正方向

VR=VBVAV_R=V_B-V_A

t=VR(VRn)nt=V_R-(V_Rn)n

这里因tangent切线方向与相对速度方向相同 因此 VrVrV_r - V_r在碰撞法线上的投影向量就能够得到一个与n垂直的切线向量t


2.在两对象发生碰撞的时候 直接计算出相互作用力F的办法几乎没有 因此想到可以使用已经计算完成的冲量来计算出两个物体之间的作用力大小

  • P=mvP = mv 动量
  • I=FtI = Ft =>这里就可以使用已经计算好的冲量I来表示出滑动摩擦力
  • I=P2P1I = P2 - P1 冲量 = 动量改变量

Ff<=μFnFf<=\mu Fn

PS:

库伦摩擦力定理

  • 库仑摩擦第一定律:摩擦力跟作用在摩擦面上的正压力成正比,跟外表的接触面积无关
  • 库仑摩擦第二定律:滑动摩擦力和滑动速度大小无关
  • 库仑摩擦第三定律:最大静摩擦大于滑动摩擦力,即f静>f滑。
    静摩擦力:
  • 静滑动摩擦力与一般约束反力不同,它并不随外力的增大而无限制地增大。
  • 当外力的大小达到一定数值时,物体处于将要滑动,但又未开始滑动的临界状态。此时,只要外力再大一点,物体就开始滑动。当物体处于平衡的临界状态时,静摩擦力达到最大值,即为最大静滑动摩擦力,简称最大静摩擦力。

此处计算的Ff就是滑动摩擦力 而uFn也就是最大静摩擦力 由于滑动而产生的摩擦力不会超过最大静摩擦力


3.有一向量与一单位向量点积 那么结果就是得到该向量在单位向量/方向向量上的投影向量 同理 倘若有一点与一单位向量点积 那么结果就是得到这个点在单位向量上的投影点


4.转动惯量(Moment of Inertia)是刚体绕轴转动时惯性(回转物体保持其匀速圆周运动或静止的特性)的量度,用字母I或J表示。其量值取决于物体的形状、质量分布及转轴的位置。

PS:
转动惯量的表达式为

若刚体的质量是连续分布的,则转动惯量的计算公式可写成

角加速度与合外力矩的关系 因此这里可以得到角速度的计算公式 dw = (M(力矩) / I(转动惯量) )*dt

力矩 M=L×FLM = L \times F * L是从着力点到转动轴的距离矢量, F是矢量力;力矩也是矢量。



1.在一个物理引擎当中一个物体对象通常有三个自由度 分别是xy轴上的自由平移和旋转

2.两物体碰撞 恢复系数取决于小的那个物体

3.冲量 = 动量改变量

Impulse=massVelocityImpulse=mass*Velocity

Velocity=ImpulsemassVelocity=Impulsemass

V=V+(jn)massV' = V + \frac{(j * n )}{mass}

此处的(jn)mass\frac{(j * n )}{mass} 表示速度改变量

4.这里的VABV_{AB}实质上是在应用了恢复系数之后的VabV_{ab}'

VABn=e(VBVA)nV_{AB}' n = e (V_B - V_A)*n

原来式子中的负号是有误的

因此后面在使用这三个式子来推导最终结果的时候就可以理解了

VA=VA+(jn)massAV'_A=V_A+\frac{(j*n)}{mass_A}

VB=VB(jn)massBV'_B=V_B-\frac{(j*n)}{mass_B}

5.正确的推导

(VBVA(jn)/massA(jn)/massB)n=e(VBVA)n(V_B-V_A-(j n) / mass_A-(j n) / mass_B)n= e (V_B-V_A) * n

(VBVA)nj((jn)/massA+(jn)/massB)ne(VBVA)n=0(V_B-V_A) n-j((j n) / mass_A+(j n)/ mass_B)n-e (V_B-V_A) * n= 0

(1+e)((VBVA)n)+j((jn)massA+(jn)massB)n=0(1+e)((V_B-V_A) n)+j (\frac{(j n)}{mass_A} + \frac{(j n)}{mass_B}) * n=0

j=(1+e)((VBVA)n)(1/massA+1/massB)j=-\frac{(1+e)((V_B-V_A) * n)}{(1/mass_A+1/mass_B)}

原本的计算方式中虽然最终结果是正确的 但是推导过程中两次负号都出错 因此导致结果正确但是推导不正确的情况

6.预计算质量的倒数是非常有必要的

 A.inv_mass = 1 / A.mass

将 j 根据质量大小来分配给两个对象

mass_sum = A.mass + B.mass
float ratio = A.mass / mass_sum
A.velocity -= ratio * impulse

ratio = B.mass / mass_sum
B.velocity += ratio * impulse

PS:这个步骤 实质上就是ResolveCollision()这里也能看出来质量的倒数的重要性

7.位置修正的本质就是将两个互相碰撞的物体(在应用了冲量之后) 在其碰撞法线上移动一定距离(渗透距离的一定百分比 通常在20%~80%之间 作者推荐使用40%)



1.基于数据驱动的命令行使用方式

-z 指针指向的数据集开始的位置为0
-Q 不会输出任何调式信息
-V 输出调试信息
-N 不会在三角形上出现边界线


2.triangleio的结构体简析

-pointlist 点坐标集合(数组)
-pointattributelist 点属性数组(每个点的属性占据一个numberOfPointAttributes中的一个位置)
-pointmarkerlist 点标记数组(每个点一个int)


-trianglelist 三角形拐角数组(从第一个[0]开始 另外的两个拐角逆时针顺序存放)
-triangleattributelist 三角形属性数组(每个三角形的属性都会占据一个numberoftriangleattributes中的一个位置)
-trianglearealist 一个三角形面积约束的数组(input only) 用于限制生成的三角形面积大小不一的情况 PS:暂时不清楚[0]和[1]的作用
-neighborlist 三角形相邻三角形的数组 每一个三角形占据三个int数据(output only)


-segmentlist 段断点的数组集合 从第一段占据的[0]和[1]开始依次为剩余的段(每段占据两个int型数据)
-segmentmarkerlist 段标记 每段一个标记(int)


-holelist 洞数组 第一个孔的x, y 坐标为[0]和[1] 剩余的依次为其余的孔(每个孔占两个实数 input only但为了方便起见也会将结果拷贝到output的结构体当中)
-regionlist 地区范围属性(给定的点集的最大AABB/最大xy范围)和面积约束的数组 第一个约束是x, y 坐标占[0]和[1] 其次是范围属性[2] 最后是最大的面积约束[3] 因此每个范围约束都会占据四个int型数据 PS:范围属性只在传入-A参数才有效 面积约束只在传入-a参数才会有效


-edgelist 边缘数组 第一个边缘的结束点占位[0]和[1] 剩余按照顺序依次占据(output only)
-edgemarkerlist 边缘标记数组(每个边缘占一个int型数据 output only)
-normlist 法向量数组 用于确定泰森多边形法图解中的无限远射线 第一个法向量的x, y坐标占据[0]和[1] 剩余法向量依次顺序占位 对于每个泰森多边形法图解的无限远边缘而言 法向量会填写为零向量(output only)


3.对于每个需要输出的结构体中的指针都必须要分配好合适的空间 或者可以将指针初始化为NULL 这样triangle库本身就会帮你分配所需要的内存空间
PS:原作者推荐奖指针初始化为NULL 因为前者的方法多数用于Fortran代码dangzhong

triangle也不会自动的释放in/out的数组 这都取决于使用者 trifree()的本质就是调用标准库的free()


4.必须要在triangulate()之前初始化好的部分

in
pointlist 必须是指向一系列点指针的指针
numberofpoints和numberofpointattributes 应该被合理的设置
pointmarkerlist = NULL(所有的标记都应该设置为NULL)
pointattributelist 务必是一个指向点属性的指针
使用了-r命令 那么trianglelist就必须要指向一列三角形 numberoftriangles numberofcorners以及numberoftriangleattributes都必须要根据其本身的含义来初始化
numberoftriangleattributes != 0 那么triangleattributelist就要指向一三角形属性集合
使用了-a命令 trianglearealist就一定要指向一的面积约束数组
可以忽略neighborlist, edgelist, edgemarkerlist, normlist, numberofedges的初始化
使用了-p命令 segmentlist就必须要指向一片段集合 numberofsegments就要根据其本身含义来初始化;holelist numberofholes 以及numberofregions都会被拷贝至out结构体当中 除非使用了-r命令 否则使用者是不要初始化这些部件的
segmentmarkerlist = NULL(使用库本身的空间分配) 否则就需要自己手动指向一标记集合


out

pointlist 需要被初始化(NULL / 指向一定的内存空间) 除非使用了-N命令
pointmarkerlist 需要被初始化(NULL / 指向一定的内存空间) 除非使用了-N 或者 -B命令
in->numberofpointattributes != 0 并且没有是使用过-N命令 pointattributelist就需要被初始化
trianglelist 需要被初始化 除非使用了-E命令
neighborlist 需要被初始化 除非使用了-n命令
in->numberofelementattributes != 0并且没有使用-E命令而是使用了-A命令 那么elementattributelist需要被初始化
trianglearealist, holelist, regionlist, normlist以及其他的标量初始化可以被忽略
使用了-p或者-c命令并且没有使用-P命令的话 那么segmentlist就需要被初始化
使用了-B命令 segmentmarkerlist 也需要被初始化
使用了-e命令 edgelist需要被初始化 在此基础上 倘若没有使用-B命令 那么edgemarkerlist也需要被初始化


vorout(只有在使用了-r命令后才需要这部分的参数)

pointlist需要被初始化
edgelist 和 normlist都需要被初始化
in->numberofpointattributes != 0 那么pointattributelist也需要被初始化
pointmarkerlist, edgemarkerlist以及上述中没有出现的都可以被忽略


5.segment段和hole是需要互相配合使用的

segment为多边形中小孔相关线段形成的闭合区域

hole部分只需要是孔中的任意一点即可



1.在类中声明一个指针并不意味着在程序运行中这个指针指向的内容就是0

class A
{
     float *a;
};

这时指针a指向的位置是不确定的 只有在构造函数或者某个初始化位置的地方明确的给定值

a = nullptr / a = 0 / a = NULL;之类的 才可以在后续的指针是否为空判断中正确操作

否则

if(a == NULL)这样的判断在没有初始化的指针下是没有意义的 始终会被认定为真值



1.就当前引擎的设计角度而言 倘若从设计模式的角度来讲 也就是建筑这个引擎的过程而言C++的整体结构思想远远超过C语言不知道多少倍 就从类的包装继承而言 C++更像是为了这种的项目而诞生的

举个简单的粒子

C语言想要实现数学库 那么你就必须面对通用性的考验 这就意味着你很有可能要面对好几十个+的重载运算

而只是为了达到类似多态的效果……但这不像是一个很聪明的解决办法

齐次 我倘若想要创建一int型的向量 还有一个float的 还有一个unsigned int的甚至各种各样的 难道还需要强制规定响亮的格式不成?

其实以上的C++早用了函数模板以及模板类来实现 通用性大大加强 我想 同样的情况下 牺牲那1%的速度去换取100%的简洁性是可以理解的

2.结构体和类本身都是不矛盾的两者 既然在实现上使用了效率更高的C 那么汇编去哪里工作呢?数学库本应该是使用SIMD之类进行优化的

在设计的时候就不要太多的关照效率的问题……除非实在是太慢了



Bingo

@BentleyJobs

Graduated from JNU, interested in cg & game developing, once worked in Aurogon to develope GuJianOL. See about for more info.