Bingo, Computer Graphics & Game Developer

  1. 堆栈的序号可以从栈顶和栈底计数,从栈底计数,则栈底是1,向栈顶方向递增。从栈顶计数,则栈顶是-1,向栈底方向递减.
    因此不论使用何种计数方式都可以用来遍历栈

2.lua栈

3.建一个新表

void lua_createtable (lua_State *L, int narr, int nrec)

创建一个新的table, 并把它放在栈顶. narr和nrec分别指定该table的array部分和hash部分的预分配元素数量
无返回值
栈高度+1, 栈顶元素是新table

#define lua_newtable(L) lua_createtable(L, 0, 0) 

常用这个

4.C函数参数里的Lua栈是私有的,每一个函数都有自己的栈。当一个c/c++函数把返回值压入Lua栈以后,该栈会自动被清空。



struct CLS
{
    int m_i;
    CLS( int i ):m_i(i){}
    CLS()
    {
        CLS(0);
    }
};
int main()
{
    CLS obj;
    // obj.m_i = ?
    return 0;
}

从这里,我们归纳如下:

1)在c++里,由于构造函数允许有默认参数,使得这种构造函数调用构造函数来重用代码的需求大为减少

2)如果仅仅为了一个构造函数重用另一个构造函数的代码,那么完全可以把构造函数中的公共部分抽取出来定义一个成员函数(推荐为private),然后在每个需要这个代码的构造函数中调用该函数即可

3)偶尔我们还是希望在类的构造函数里调用另一个构造函数,可以按下面方式做:

在构造函数里调用另一个构造函数的关键是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存,这个可以用标准库的placement new做到:

先看看标准库中placement new的定义

inline void *__cdecl operator new(size_t, void *_P)
{
    return (_P); 
} 

可见没有分配新的内存。

正确的方式:

struct CLS
{
    int m_i;
    CLS( int i ) : m_i(i){}
    CLS()
    {
        new (this)CLS(0);
    }
};

另: 若构造函数调用自身,则会出现无限递归调用,是不允许的

若是构造函数嵌套调用 那么第二次调用产生的是匿名对象 也就是说 无论在第二次的构造函数中赋任何值 都会被作为临时对象给抹去 那么出了第一次的构造函数相当于没有初始化任何东西



1.这个裁剪算法可用于当3d光栅化完毕需要将图形渲染到屏幕上方时所作的裁剪 也可以是类似Box2d在多边形碰撞深度计算的时候所作的运算

Polygon SutherlandHodgman( const Polygon startingPolygon, Plane[] clippingPlanes )
{
  Polygon output = startingPolygon
  for each Plane clippingPlane in clippingPlanes
    input = output
    output.Clear( )
    Vec2 startingPoint = input.Last( )
    for each Vec2 endPoint in input
      if startingPoint and endPoint in front of clippingPlane
        out.push( endPoint )
      else if startingPoint in front and endPoint behind clippingPlane
        out.push( Intersection( clippingPlane, startingPoint, endPoint ) )
      else if startingPoint and endPoint behind clippingPlane
        out.push( Intersection( clippingPlane, startingPoint, endPoint ) )
        out.push( endPoint )
      endPoint = startingPoint
  return output
}

其本质就是遍历需要被裁减的多边形的所有的边 每边与裁剪多边形的所有边进行位置判断

// InFront = plane.Distance( point ) > 0.0f
// Behind  = plane.Distance( point ) < 0.0f

Vec2 p1, p2;
ClipPlane plane;

case p1 InFront and p2 InFront
  push p2
case p1 InFront and p2 Behind
  push intersection
case p1 Behind and p2 InFront
  push intersection
  push p2

上方代码的含义基本为下图

1.当边的方向进入裁剪区域 添加P与P1

2.当边的方向是背离裁剪区域 只添加P

3.倘若全部都在背离方向上 不添加点

4.整个边都在内部 只添加P1

这里P是p0->p1与裁剪边的交接点 (一元二次的直线方程可以计算出)

下方为一个裁剪的案例

详情见



1.Support Point碰撞检测的理念与SAT并无差别 只是在效率上更胜一筹

support point是在给定方向上距离最远(投影最大)的点

在碰撞检测中也需要寻找分离轴 那么这时候 support point就是在面法线相反的方向上最远的点 也就是背离这个方向深交最深的点

倘若两个多边形相互碰撞 那么一定能找到一个顶点与给定平面之间的距离小于0(在面法线上的投影)

这与两个多边形互不碰撞那么一定可以找到一跟分离轴分离两个多边形的理论是类似的

每次循环都挑选一个给定轴 在这个轴的反面法线上找一个深度最深的点 若这个点在这个面的背面(距离为正) 那么就证明存在一条分离轴可以用来分割这两个图形



1.要检测圆形与多边形的碰撞 其实可以分解为圆与多边形上最近点的向量与面法线方向是否一致的问题

再继续分解下去求解最近点 就能够发现只需要一个多边形的面和一个圆心即可 在这个多边形面上 这个线段可以被分为三个区域

如图所示

  • 在Face Region中 圆心到多边形最近的点就在Face Region上 且与圆心的连线垂直于这条边
  • 在Edge Region内 那么最近点就是线段边缘点本身

  • 确定圆心在哪个区域内 可以让圆心与线段本身进行点积
  • 可以通过想象出一个三角形来完成这样的一个任务

  • 在这里 若是圆心位置为Edge Region那么圆心与线段端点的夹角theta一定大于90度 或者小于90度(对应的变化要看线段的向量方向走向规定)



1.现有点(x0, y0)与直线ax+by+c=0
点P到直线的距离为d=
但是当仅仅只是需要判断点(x0, y0)与直线的位置关系 那么直接可以采用以下式子来计算

d=ax0+by0+cA2+B2d = \frac{|ax0 + by0 + c|}{\sqrt{A^2 + B^2}}

下图就表示了几种直线的情况和d与直线的位置判断



Bingo

@BentleyJobs

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