Box2d源码学习<九>形状(中):边缘形状和链形状的实现

本系列博客是由扭曲45原创,欢迎转载,转载时注明出处,http://blog.csdn.net/cg0206/article/details/8302347

Box2d 2.2.1中父形状shape将有4个子形状,分别是b2EdgeShape(边缘形状)、b2ChainShape(链形状)、b2Circle(圆形状)和b2PolygonShape(多边形形状)。我们今天就来先看看边缘形状和链形状。

1、 边缘形状,边缘形状是由多条线段组成。不能与自己进行碰撞检测,只能与圆和多边形进行碰撞检测。在box2d中,如果要想检测两个形状是否碰撞,形状必须要有体积的,故边缘形状不能和边缘形状碰撞。我们就来看看b2EdgeShape的定义吧,打开b2EdgeShape.h文件。

[cpp]  view plain  copy
  1.  //  一个线段(边缘)形状。这些可以连接在链或者环其他边缘形状。  
  2. //连接信息是用来确保正确的联系法线  
  3. class b2EdgeShape : public b2Shape  
  4. {  
  5. public:  
  6.     /************************************************************************** 
  7.     * 功能描述: 构造函数 
  8.     * 参数说明: (void) 
  9.     * 返 回 值: (void) 
  10.     ***************************************************************************/  
  11.     b2EdgeShape();  
  12.     /************************************************************************** 
  13.     * 功能描述: 设置独立的边缘 
  14.     * 参数说明: v1 : 第一个顶点 
  15.                  v2 : 第二个顶点 
  16.     * 返 回 值: (void) 
  17.     ***************************************************************************/  
  18.     void Set(const b2Vec2& v1, const b2Vec2& v2);  
  19.     /************************************************************************** 
  20.     * 功能描述:用soa块分配器克隆一个具体的形状 
  21.     * 参数说明: allocator :soa分配器对象指针 
  22.     * 返 回 值: 形状指针 
  23.     ***************************************************************************/  
  24.     b2Shape* Clone(b2BlockAllocator* allocator) const;  
  25.     /************************************************************************** 
  26.     * 功能描述:获取形状的孩子元素的数量 
  27.     * 参数说明: (void) 
  28.     * 返 回 值: 孩子元素的数量 
  29.     ***************************************************************************/  
  30.     int32 GetChildCount() const;  
  31.     /************************************************************************** 
  32.     * 功能描述:在这个形状中测试这个点的密封性,只适合用于凸的形状 
  33.     * 参数说明: xf : 形状的变换 
  34.                  p  : world坐标中的一个点 
  35.     * 返 回 值: true : 密封 
  36.                  false:敞开 
  37.     ***************************************************************************/  
  38.     bool TestPoint(const b2Transform& transform, const b2Vec2& p) const;  
  39.     /************************************************************************** 
  40.     * 功能描述:投射一束光到一个孩子形状中 
  41.     * 参数说明: output      :输出光线投射的结果 
  42.                  input       :输入光线投射 
  43.                  transform   :变换应用到此形状中 
  44.                  childeIndex :孩子形状索引 
  45.     * 返 回 值: true : 成功 
  46.                  false:失败 
  47.     ***************************************************************************/  
  48.     bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,  
  49.                 const b2Transform& transform, int32 childIndex) const;  
  50.     /************************************************************************** 
  51.     * 功能描述:给出一个变换,计算一个孩子形状的轴对齐包围盒(aabb) 
  52.     * 参数说明: aabb       : 孩子形状的aabb指针 
  53.                  xf         : 一个变换的引用 
  54.                  childIndex : 孩子的索引值 
  55.     * 返 回 值: (void) 
  56.     ***************************************************************************/  
  57.     void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const;  
  58.     /************************************************************************** 
  59.     * 功能描述:用它的大小和密度计算形状的质量 
  60.     * 参数说明: massData   : 计算形状的质量 
  61.                  density    : 密度 
  62.     * 返 回 值: (void) 
  63.     ***************************************************************************/  
  64.     void ComputeMass(b2MassData* massData, float32 density) const;  
  65.     //  边缘形状的顶点  
  66.     b2Vec2 m_vertex1, m_vertex2;  
  67.     // 可选的相邻的顶点,它们用于平滑碰撞  
  68.     b2Vec2 m_vertex0, m_vertex3;  
  69.     //是否含有相邻顶点  
  70.     bool m_hasVertex0, m_hasVertex3;  
  71. };  
  72. //构造函数,用于初始化  
  73. inline b2EdgeShape::b2EdgeShape()  
  74. {  
  75.     m_type = e_edge;  
  76.     m_radius = b2_polygonRadius;  
  77.     m_vertex0.x = 0.0f;  
  78.     m_vertex0.y = 0.0f;  
  79.     m_vertex3.x = 0.0f;  
  80.     m_vertex3.y = 0.0f;  
  81.     m_hasVertex0 = false;  
  82.     m_hasVertex3 = false;  
  83. }  

我们可以看到b2EdgeShape继承了b2Shape类,并对虚方法进行了重新定义。同时我们也实现了一个内联构造函数,进行对b2EdgeShape类进行初始化的时候使用。这方面,也不多说了,再来看看它的实现。

[cpp]  view plain  copy
  1. //设置独立的边缘  
  2. void b2EdgeShape::Set(const b2Vec2& v1, const b2Vec2& v2)  
  3. {  
  4.     m_vertex1 = v1;  
  5.     m_vertex2 = v2;  
  6.     m_hasVertex0 = false;  
  7.     m_hasVertex3 = false;  
  8. }  
  9.   
  10. //用soa块分配器克隆一个具体的形状  
  11. b2Shape* b2EdgeShape::Clone(b2BlockAllocator* allocator) const  
  12. {  
  13.     //在内存池中申请一块内存  
  14.     void* mem = allocator->Allocate(sizeof(b2EdgeShape));  
  15.     //在一块已存在的内存上分配对象  
  16.     b2EdgeShape* clone = new (mem) b2EdgeShape;  
  17.     *clone = *this;  
  18.     return clone;  
  19. }  
  20. //获取形状的孩子元素的数量  
  21. int32 b2EdgeShape::GetChildCount() const  
  22. {  
  23.     return 1;  
  24. }  
  25. //在这个形状中测试这个点的密封性,只适合用于凸的形状  
  26. bool b2EdgeShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const  
  27. {  
  28.     // 消除编译器产生的警告  
  29.     B2_NOT_USED(xf);  
  30.     B2_NOT_USED(p);  
  31.     return false;  
  32. }  
  33. //光线投射  
  34. // p = p1 + t * d  
  35. // v = v1 + s * e  
  36. // p1 + t * d = v1 + s * e  
  37. // s * e - t * d = p1 - v1  
  38. bool b2EdgeShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,  
  39.                             const b2Transform& xf, int32 childIndex) const  
  40. {  
  41.     //消除编译器  
  42.     B2_NOT_USED(childIndex);  
  43.     //把光线投入到边缘框架的参考系中  
  44.     //下面是根据给定的公式在计算,  
  45.     //光线投射最近也在研究中,就不误导大家啦。。。  
  46.     b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p);  
  47.     b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p);  
  48.     b2Vec2 d = p2 - p1;  
  49.   
  50.     b2Vec2 v1 = m_vertex1;  
  51.     b2Vec2 v2 = m_vertex2;  
  52.     b2Vec2 e = v2 - v1;  
  53.     b2Vec2 normal(e.y, -e.x);  
  54.     normal.Normalize();  
  55.   
  56.     // q = p1 + t * d  
  57.     // dot(normal, q - v1) = 0  
  58.     // dot(normal, p1 - v1) + t * dot(normal, d) = 0  
  59.     float32 numerator = b2Dot(normal, v1 - p1);  
  60.     float32 denominator = b2Dot(normal, d);  
  61.   
  62.     if (denominator == 0.0f)  
  63.     {  
  64.         return false;  
  65.     }  
  66.   
  67.     float32 t = numerator / denominator;  
  68.     if (t < 0.0f || input.maxFraction < t)  
  69.     {  
  70.         return false;  
  71.     }  
  72.   
  73.     b2Vec2 q = p1 + t * d;  
  74.   
  75.     // q = v1 + s * r  
  76.     // s = dot(q - v1, r) / dot(r, r)  
  77.     b2Vec2 r = v2 - v1;  
  78.     float32 rr = b2Dot(r, r);  
  79.     if (rr == 0.0f)  
  80.     {  
  81.         return false;  
  82.     }  
  83.   
  84.     float32 s = b2Dot(q - v1, r) / rr;  
  85.     if (s < 0.0f || 1.0f < s)  
  86.     {  
  87.         return false;  
  88.     }  
  89.   
  90.     output->fraction = t;  
  91.     if (numerator > 0.0f)  
  92.     {  
  93.         output->normal = -normal;  
  94.     }  
  95.     else  
  96.     {  
  97.         output->normal = normal;  
  98.     }  
  99.     return true;  
  100. }  
  101. //给出一个变换,计算一个孩子形状的轴对齐包围盒(aabb)  
  102. void b2EdgeShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const  
  103. {  
  104.     //消除编译器产生的警告  
  105.     B2_NOT_USED(childIndex);  
  106.   
  107.     b2Vec2 v1 = b2Mul(xf, m_vertex1);  
  108.     b2Vec2 v2 = b2Mul(xf, m_vertex2);  
  109.   
  110.     b2Vec2 lower = b2Min(v1, v2);  
  111.     b2Vec2 upper = b2Max(v1, v2);  
  112.     //重新设置aabb  
  113.     b2Vec2 r(m_radius, m_radius);  
  114.     aabb->lowerBound = lower - r;  
  115.     aabb->upperBound = upper + r;  
  116. }  
  117. //计算质量  
  118. void b2EdgeShape::ComputeMass(b2MassData* massData, float32 density) const  
  119. {  
  120.     //消除编译器产生的警告  
  121.     B2_NOT_USED(density);  
  122.     //设置用户数据  
  123.     massData->mass = 0.0f;  
  124.     massData->center = 0.5f * (m_vertex1 + m_vertex2);  
  125.     massData->I = 0.0f;  
  126. }  

关于b2EdgeShape的实现,我们先来看下Clone函数,用SOA(小型对象分配器)分配了一块内存后,我们又用new在一块已存在的内存上分配对象,这是new的另外一种用法placement new,如果有童鞋对此不太理解或者想更深入研究的话,可以参照以下链接http://blog.sina.com.cn/s/blog_69e905cd0100k51b.htmlhttp://club.topsage.com/thread-2467284-1-1.html,还有就是RayCast函数,主要就是根据注释上面的公式求解,然后就能获得结果。如果还有童鞋进一步了解的话,可以看CollisionDetection inInteractive 3D Environments这本书。当然我们通过上面代码可以简单的看到,b2EdgeShape是重量为零、密封性为假的形状。

 

2、 链形状,链形状是一个自由形式的序列的线段,链具有双面碰撞,故你可以使用内部或者外部碰撞。链形状提供了一种高效的方法来同时连接多条边,为你的游戏创造静态的游戏世界。链形状同时提供了创建链和环的方法,以便为大家提供想要的形状。链形状不能自身交叉,那样它有可能不能正常的工作。在Box2d中,链形状是通过b2ChainShape实现的。我们就来看看它是怎么做到的。

首先,我们看b2ChainShape.h文件。

[cpp]  view plain  copy
  1. //声明  
  2. class b2EdgeShape;  
  3.   
  4. // 链形状是一个自由形式的序列的线段,链具有双面碰撞,故你可以使用内部和外部碰撞  
  5. // 同时,你可以使用任何缠绕的顺序。尽管可能有很多顶点,不过它们都是通过b2Alloc分配的。  
  6. // 链接信息是用来创建平滑的碰撞  
  7. // 警告:如果他们自身交叉时,有可能不会正确的处理碰撞  
  8. //       即有可能正常工作,也有可能不正常工作  
  9. class b2ChainShape : public b2Shape  
  10. {  
  11. public:  
  12.     /************************************************************************** 
  13.     * 功能描述: 链形状构造函数 
  14.     * 参数说明: (void) 
  15.     * 返 回 值: (void) 
  16.     ***************************************************************************/  
  17.     b2ChainShape();  
  18.     /************************************************************************** 
  19.     * 功能描述: 析构函数,用b2Free释放多个点 
  20.     * 参数说明: (void) 
  21.     * 返 回 值: (void) 
  22.     ***************************************************************************/  
  23.     ~b2ChainShape();  
  24.     /************************************************************************** 
  25.     * 功能描述: 创建一个环。自动调整连接 
  26.     * 参数说明: vertices : 顶点数组,拷贝它们 
  27.                  count    : 顶点的数量 
  28.     * 返 回 值: (void) 
  29.     ***************************************************************************/  
  30.     void CreateLoop(const b2Vec2* vertices, int32 count);  
  31.     /************************************************************************** 
  32.     * 功能描述: 用孤立的点创建一个链 
  33.     * 参数说明: vertices : 顶点数组,拷贝它们 
  34.                  count    : 顶点的数量 
  35.     * 返 回 值: (void) 
  36.     ***************************************************************************/  
  37.     void CreateChain(const b2Vec2* vertices, int32 count);  
  38.     /************************************************************************** 
  39.     * 功能描述: 创建由一个顶点连接到上个顶点的链接 
  40.                  不要在环中调用【即不能调用CreateLoop创建了环之后在调用此函数】 
  41.     * 参数说明: prevVertex : 上一个顶点 
  42.     * 返 回 值: (void) 
  43.     ***************************************************************************/  
  44.     void SetPrevVertex(const b2Vec2& prevVertex);  
  45.     /************************************************************************** 
  46.     * 功能描述: 创建由一个顶点连接到下个顶点的链接 
  47.                  不要在环中调用【即不能调用CreateLoop创建了环之后在调用此函数】 
  48.     * 参数说明: vertices : 下一个顶点 
  49.     * 返 回 值: (void) 
  50.     ***************************************************************************/  
  51.     void SetNextVertex(const b2Vec2& nextVertex);  
  52.     /************************************************************************** 
  53.     * 功能描述: 用b2Alloc克隆所有顶点 
  54.                  不要在环中调用【即不能调用CreateLoop创建了环之后在调用此函数】 
  55.     * 参数说明: allocator : soa对象指针 
  56.     * 返 回 值: 形状对象指针 
  57.     ***************************************************************************/  
  58.     b2Shape* Clone(b2BlockAllocator* allocator) const;  
  59.     /************************************************************************** 
  60.     * 功能描述:获取形状的孩子元素的数量 
  61.     * 参数说明: (void) 
  62.     * 返 回 值: 形状类型 
  63.     ***************************************************************************/  
  64.     int32 GetChildCount() const;  
  65.   
  66.     /************************************************************************** 
  67.     * 功能描述:根据索引值从链中获取指定的边缘形状 
  68.     * 参数说明: edge :b2EdgeShape对象指针 
  69.                  index:索引值 
  70.     * 返 回 值: (void) 
  71.     ***************************************************************************/  
  72.     void GetChildEdge(b2EdgeShape* edge, int32 index) const;  
  73.     /************************************************************************** 
  74.     * 功能描述:在这个形状中测试这个点的密封性,只适合用于凸的形状 
  75.     * 参数说明: xf : 形状的变换 
  76.                  p  : world坐标中的一个点 
  77.     * 返 回 值: true : 密封 
  78.                  false:敞开 
  79.                  总是返回false 
  80.     ***************************************************************************/  
  81.     bool TestPoint(const b2Transform& transform, const b2Vec2& p) const;  
  82.     /************************************************************************** 
  83.     * 功能描述:投射一束光到一个链形状中 
  84.     * 参数说明: output      :输出光线投射的结果 
  85.                  input       :输入光线投射 
  86.                  transform   :变换应用到此形状中 
  87.                  childeIndex :孩子形状索引 
  88.     * 返 回 值: true : 成功 
  89.                  false:失败 
  90.     ***************************************************************************/  
  91.     bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,  
  92.                     const b2Transform& transform, int32 childIndex) const;  
  93.     /************************************************************************** 
  94.     * 功能描述:给出一个变换,计算一个孩子形状的轴对齐包围盒(aabb) 
  95.                 不要在环中调用【即不能调用CreateLoop创建了环之后在调用此函数】 
  96.     * 参数说明: aabb       : 孩子形状的aabb指针 
  97.                  xf         : 一个变换的引用 
  98.                  childIndex : 孩子的索引值 
  99.     * 返 回 值: (void) 
  100.     ***************************************************************************/  
  101.     void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const;  
  102.     /************************************************************************** 
  103.     * 功能描述:用它的大小和密度计算形状的质量 
  104.                 Chains的质量为0 
  105.                 不要在环中调用【即不能调用CreateLoop创建了环之后在调用此函数】 
  106.     * 参数说明: massData   : 计算形状的质量 
  107.                  density    : 密度 
  108.     * 返 回 值: (void) 
  109.     ***************************************************************************/  
  110.     void ComputeMass(b2MassData* massData, float32 density) const;  
  111.     // 顶点数组  
  112.     b2Vec2* m_vertices;  
  113.   
  114.     //顶点个数  
  115.     int32 m_count;  
  116.     //前顶点,后顶点  
  117.     b2Vec2 m_prevVertex, m_nextVertex;  
  118.     //是否拥有前顶点,后顶点  
  119.     bool m_hasPrevVertex, m_hasNextVertex;  
  120. };  
  121. //构造函数  
  122. inline b2ChainShape::b2ChainShape()  
  123. {  
  124.     m_type = e_chain;  
  125.     m_radius = b2_polygonRadius;  
  126.     m_vertices = NULL;  
  127.     m_count = 0;  
  128.     m_hasPrevVertex = NULL;  
  129.     m_hasNextVertex = NULL;  
  130. }  

我们可以看到开始的时候,将b2EdgeShape类声明了一下,作为一个标签放入头文件中,在链接的时候,链接器会做相应的处理。【这里我们知道一下就行,不必深究】。当然,b2ChainShape类也继承了b2Shape类,并对父类的虚方法进行了重新定义和实现【当然是ccp文件啦】。构造函数同样也是初始化相关信息。

[cpp]  view plain  copy
  1. //析构函数  
  2. b2ChainShape::~b2ChainShape()  
  3. {  
  4.     b2Free(m_vertices);  
  5.     m_vertices = NULL;  
  6.     m_count = 0;  
  7. }  
  8. //创建一个循环。自动调整连接  
  9. void b2ChainShape::CreateLoop(const b2Vec2* vertices, int32 count)  
  10. {  
  11.     //验证是否没有顶点  
  12.     b2Assert(m_vertices == NULL && m_count == 0);  
  13.     //验证顶点的个数  
  14.     b2Assert(count >= 3);  
  15.     //在顶点个数基础上加1,  
  16.     //用于将第一个元素放到最后一个空间中,  
  17.     //这样就会形成一个环状,方便操作  
  18.     m_count = count + 1;  
  19.     //申请一个顶点动态数组,并拷贝旧数组中的数据到新空间中  
  20.     m_vertices = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));  
  21.     memcpy(m_vertices, vertices, count * sizeof(b2Vec2));  
  22.     //申请一个  
  23.     m_vertices[count] = m_vertices[0];  
  24.     //前一个顶点、后一个顶点  
  25.     m_prevVertex = m_vertices[m_count - 2];  
  26.     m_nextVertex = m_vertices[1];  
  27.     m_hasPrevVertex = true;  
  28.     m_hasNextVertex = true;  
  29. }  
  30. //用孤立的点创建一个链  
  31. void b2ChainShape::CreateChain(const b2Vec2* vertices, int32 count)  
  32. {  
  33.     //没有顶点  
  34.     b2Assert(m_vertices == NULL && m_count == 0);  
  35.     //顶点数要过大  
  36.     b2Assert(count >= 2);  
  37.     //   
  38.     m_count = count;  
  39.     //申请一个顶点动态数组,并拷贝旧数组中的数据到新空间中  
  40.     m_vertices = (b2Vec2*)b2Alloc(count * sizeof(b2Vec2));  
  41.     memcpy(m_vertices, vertices, m_count * sizeof(b2Vec2));  
  42.     //没有左右节点  
  43.     m_hasPrevVertex = false;  
  44.     m_hasNextVertex = false;  
  45. }  
  46. //创建由一个顶点连接到上个顶点的链接  
  47. void b2ChainShape::SetPrevVertex(const b2Vec2& prevVertex)  
  48. {  
  49.     m_prevVertex = prevVertex;  
  50.     m_hasPrevVertex = true;  
  51. }  
  52. //创建由一个顶点连接到下个顶点的链接  
  53. void b2ChainShape::SetNextVertex(const b2Vec2& nextVertex)  
  54. {  
  55.     m_nextVertex = nextVertex;  
  56.     m_hasNextVertex = true;  
  57. }  
  58. //用b2Alloc克隆所有顶点  
  59. b2Shape* b2ChainShape::Clone(b2BlockAllocator* allocator) const  
  60. {  
  61.     //申请一块内存  
  62.     void* mem = allocator->Allocate(sizeof(b2ChainShape));  
  63.     //在一块已存在的内存上分配对象  
  64.     b2ChainShape* clone = new (mem) b2ChainShape;  
  65.     //创建链  
  66.     clone->CreateChain(m_vertices, m_count);  
  67.     //获取相关信息,并返回  
  68.     clone->m_prevVertex = m_prevVertex;  
  69.     clone->m_nextVertex = m_nextVertex;  
  70.     clone->m_hasPrevVertex = m_hasPrevVertex;  
  71.     clone->m_hasNextVertex = m_hasNextVertex;  
  72.     return clone;  
  73. }  
  74. //获取形状的孩子元素的数量  
  75. int32 b2ChainShape::GetChildCount() const  
  76. {  
  77.     // edge count = vertex count - 1  
  78.     return m_count - 1;  
  79. }  
  80. //根据索引值从链中获取指定的边缘形状  
  81. void b2ChainShape::GetChildEdge(b2EdgeShape* edge, int32 index) const  
  82. {  
  83.     //验证索引值  
  84.     b2Assert(0 <= index && index < m_count - 1);  
  85.     //复制类型,半径  
  86.     edge->m_type = b2Shape::e_edge;  
  87.     edge->m_radius = m_radius;  
  88.     //获取两端坐标  
  89.     edge->m_vertex1 = m_vertices[index + 0];  
  90.     edge->m_vertex2 = m_vertices[index + 1];  
  91.   
  92.     //根据CreateLoop中可以知道,第一个元素和最后一个元素是一样的  
  93.     //所以要单独判断  
  94.     //判断索引值是否是第一个元素  
  95.     if (index > 0)  
  96.     {  
  97.         edge->m_vertex0 = m_vertices[index - 1];  
  98.         edge->m_hasVertex0 = true;  
  99.     }  
  100.     else  
  101.     {  
  102.         edge->m_vertex0 = m_prevVertex;  
  103.         edge->m_hasVertex0 = m_hasPrevVertex;  
  104.     }  
  105.     //判断索引值是否是最后一个元素  
  106.     if (index < m_count - 2)  
  107.     {  
  108.         edge->m_vertex3 = m_vertices[index + 2];  
  109.         edge->m_hasVertex3 = true;  
  110.     }  
  111.     else  
  112.     {  
  113.         edge->m_vertex3 = m_nextVertex;  
  114.         edge->m_hasVertex3 = m_hasNextVertex;  
  115.     }  
  116. }  
  117. //在这个形状中测试这个点的密封性,只适合用于凸的形状  
  118. bool b2ChainShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const  
  119. {  
  120.     B2_NOT_USED(xf);  
  121.     B2_NOT_USED(p);  
  122.     return false;  
  123. }  
  124. //投射一束光到一个链形状中  
  125. bool b2ChainShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,  
  126.                             const b2Transform& xf, int32 childIndex) const  
  127. {  
  128.     //验证孩子形状索引有效性  
  129.     b2Assert(childIndex < m_count);  
  130.   
  131.     b2EdgeShape edgeShape;  
  132.   
  133.     int32 i1 = childIndex;  
  134.     int32 i2 = childIndex + 1;  
  135.     //最后一个元素,单独判断  
  136.     if (i2 == m_count)  
  137.     {  
  138.         i2 = 0;  
  139.     }  
  140.     //初始化edgeShape  
  141.     edgeShape.m_vertex1 = m_vertices[i1];  
  142.     edgeShape.m_vertex2 = m_vertices[i2];  
  143.   
  144.     return edgeShape.RayCast(output, input, xf, 0);  
  145. }  
  146. //计算顶点的上下边界  
  147. void b2ChainShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const  
  148. {  
  149.     //验证孩子形状索引有效性  
  150.     b2Assert(childIndex < m_count);  
  151.     //获取坐标  
  152.     int32 i1 = childIndex;  
  153.     int32 i2 = childIndex + 1;  
  154.     //最一个元素,单独判断  
  155.     if (i2 == m_count)  
  156.     {  
  157.         i2 = 0;  
  158.     }  
  159.     //获取aabb的上下边界  
  160.     b2Vec2 v1 = b2Mul(xf, m_vertices[i1]);  
  161.     b2Vec2 v2 = b2Mul(xf, m_vertices[i2]);  
  162.   
  163.     aabb->lowerBound = b2Min(v1, v2);  
  164.     aabb->upperBound = b2Max(v1, v2);  
  165. }  
  166. //计算质量  
  167. void b2ChainShape::ComputeMass(b2MassData* massData, float32 density) const  
  168. {  
  169.     //消除编译器警告  
  170.     B2_NOT_USED(density);  
  171.     //置空成员变量  
  172.     massData->mass = 0.0f;  
  173.     massData->center.SetZero();  
  174.     massData->I = 0.0f;  
  175. }  

主要来看CreateLoop函数和CreateChain函数,它们的差别是很细微的,但是细微的差别带来的却是本质的变化,在CreateLoop函数中,我们申请了count+1顶点,比我们设置的要多出来一个顶点,这是干什么呢?主要是利用多申请的那个点的空间,放第一个顶点的信息,同时设置这两个点的前后顶点,并设置m_hasPrevVertex = true,和m_hasNextVertex = true,这样就形成了一个环了。而CreateChain函数则是直接申请了Count个顶点,并设置没有前后点。同时b2ChainShape也是零质量、密封性为假的形状。每两个点形成的形状就是边缘形状,我们可以通过GetChildEdge进行获取。其他的和前面的差不多,就不多说了。下一篇我们继续看剩下的两个形状。

 

ps:

 

以上文章仅是一家之言,若有不妥、错误之处,请大家多多指出。同时也希望能与大家多多交流,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值