当前位置:  编程技术>移动开发
本页文章导读:
    ▪应用程序系统签字        应用程序系统签名tag:涉及系统功能、系统签名、签名文件、INSTALL_FAILED_SHARED_USER_INCOMPATIBLE、INSTALL_FAILED_UPDATE_INCOMPATIBLE 在开发中涉及到调用系统核心功能,必须将程序Androidmanifest.xml里面的sh.........
    ▪ Box2d源码学习<十二>b2Collision之碰撞(下)公共部分的实现        Box2d源码学习<十二>b2Collision之碰撞(上)公共部分的实现本系列博客是由扭曲45原创,欢迎转载,转载时注明出处,http://blog.csdn.net/cg0206/article/details/8390560 Box2d中将碰撞部分单独放到几个文.........
    ▪ 小弟我被大学下了吗       我被大学上了吗?现在是2012年12月20日凌晨零点39分,地点是国立西安大学二号公寓212室。发牢骚的就是我喽。......

[1]应用程序系统签字
    来源: 互联网  发布时间: 2014-02-18
应用程序系统签名

tag:涉及系统功能、系统签名、签名文件、INSTALL_FAILED_SHARED_USER_INCOMPATIBLE、INSTALL_FAILED_UPDATE_INCOMPATIBLE

在开发中涉及到调用系统核心功能,必须将程序Androidmanifest.xml里面的sharedUserid赋值为android.uid.systemui才行。这些应用程序必须签名成系统应用才行,否则在安装的时候会提示INSTALL_FAILED_SHARED_USER_INCOMPATIBLE或者INSTALL_FAILED_UPDATE_INCOMPATIBLE错误。还有可能在调用系统api的时候提示“java.lang.SecurityException: Neither user 10055 nor current process has android.permission.INSTALL_PACKAGES”错误。

将Eclipse里面开发出的apk应用进行系统签名将避免这些问题。签名之后的应用可以直接在手机上面安装和卸载。签名方法有两种,下面将分别讲述。

1. 如果你有系统源码,最简单的就是将eclipse里面的应用拷贝到系统里面,然后编译系统,会生成out/target/product/project_name/system/app/abc.apk,这个应用就是经过系统签名了。具体方法如下:

将应用文件夹复制到package/app里面,并且只保留src、res、libs、androidmanifest.xml这三个文件,里面新建一个Android.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := abc
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)

注意红色字体表示在编译过程中将对这个模块进行系统签名。同时修改build/target/product/common.mk,在里面的PRODUCT_PACKAGES := \添加abc(即模块名称)即可。重新编译一下整个代码,就会在out目录下面生成这个apk了。

2. 上面的方法就是你需要整个android系统的源代码,比较非常麻烦。这个方法就是取出手机所用系统的签名文件,对eclipse编译出来的abc.apk文件进行签名。优点就是方便快捷。步骤包含下面几步:

a. 取得签名文件。在build/target/product/security这个目录下面一般就会有签名文件了。但是不忙,该目录下面也可能有common、project_name等目录。先看看你这套代码是那个工程目录下面。取错了签名文件,最后签名出的文件一样不行。由于本机是project_name工程,所以取 build/target/product/security/project_name/下面的platform.x509.pemplatform.pk8这两个签名文件。

b.去的签名工具。在alps\vendor\mediatek\konka75_cu_ics\artifacts\out\host\linux-x86\framework即可找到signapk.jar这个文件。该文件的源码在build/tools/signapk下面,如果有兴趣可以研究一下。

c.对apk文件进行签名。将对应的四个文件拷贝到某盘某文件下面(嘿嘿,这个不用举例了吧),然后在cmd下面进入该目录,运行命令java-jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk。生成的output.apk就是我们最终签名成功的应用了。

该应用跟上面第一种方式拿到的应用大小是不一样的,但是一样可用。


参考文献:

1.http://blog.csdn.net/happyhell/article/details/5903389

2.http://www.cnblogs.com/TerryBlog/archive/2010/09/10/1823103.html


    
[2] Box2d源码学习<十二>b2Collision之碰撞(下)公共部分的实现
    来源: 互联网  发布时间: 2014-02-18
Box2d源码学习<十二>b2Collision之碰撞(上)公共部分的实现

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

Box2d中将碰撞部分单独放到几个文件中去实现的,它的结构和函数用于计算接触点,距离查询和TOI查询。我们根据这些文件实现功能的不同,我们将该部分分成两个小的部分。它们是:

1、  公共部分的实现

2、  具体形状间的碰撞的实现

 

我们今天就来看第一部分。关于公共部分,主要包括相关结构体的定义和公共函数的实现。

对于b2Collision.h文件,我们也将它分成以下几个部分:

a)、外部类和常量在头文件的声明

b)、结构体的定义

c)、全局函数的声明

d)、内联函数的实现

好了,我们就依次来看看相关源码。

1、外部类和常量在头文件的声明

//声明类
class b2Shape;
class b2CircleShape;
class b2EdgeShape;
class b2PolygonShape;
//定义特征的无效值
const uint8 b2_nullFeature = UCHAR_MAX;

不多说了,看注释。

2、  结构体的定义

//特征,交叉形成的接触点
// 必须是4字节或者更少
struct b2ContactFeature
{
	enum Type
	{
		e_vertex = 0,
		e_face = 1
	};

	uint8 indexA;		// shapeA的特征索引
	uint8 indexB;		// shapeB的特征索引
	uint8 typeA;		// shapeA的特征类型
	uint8 typeB;		// shapeB的特征类型
};

//接触id
union b2ContactID
{
	b2ContactFeature cf;        //特征对象变量
	uint32 key;					//特征id,用于快速比较
};
//流形点属于接触流形的一个接触点。它具有的细节涉及到接触点的几何学和力学
// 局部点的求解依赖于流形的类型:
// e_circles:circleB的局部中心
// e_faceA  :circleB的局部中心 或者polygonB的夹点
// e_faceB  :polygonA的夹点
// 这个结构存储在时间步内,所以我们保持它小一些。
// 注意:这个冲量用来作为内部缓冲,很可能无法提供可靠的接触的力,尤其在高速碰撞的时候
struct b2ManifoldPoint
{
	b2Vec2 localPoint;		//局部点,求解依赖于流形类型
	float32 normalImpulse;	//法向冲量,用于防止形状的穿透
	float32 tangentImpulse;	//切向冲量,用于模拟摩擦
	b2ContactID id;			//唯一地标识一个在两个形状之间的接触点
};
// 流形(注:也有人译为‘取样’,在物理和数学中均使用‘流形’,参照http://zh.wikipedia.org/wiki/流形 )
// 流形是两个凸形状的接触部分。
// Box2D支持多种类型的接触:
// 夹点与平面半径
// 点与点半径(圆)
// 局部的点求解取决于流形的类型:
// e_circles:circleA的中心
// e_faceA  : faceA的中心
// e_faceB  :faceB的重心
// 同样局部法向量的求解:
// e_circles:不用
// e_faceA  : faceA的法向量
// e_faceB  :faceB的法向量
// 我们用这种方式存储联系,以便移动时位置被更正。
//所有接触场景必须表述为这些类型中的一个。
//这个结构存储在时间步内,所以我们保持它小一些。
struct b2Manifold
{
	//流形的类型
	enum Type
	{
		e_circles,                                  //圆
		e_faceA,                                    //面A
		e_faceB                                     //面B
	};

	b2ManifoldPoint points[b2_maxManifoldPoints];	// 接触点数组
	b2Vec2 localNormal;								// 局部法向量,对Type::e_points没用
	b2Vec2 localPoint;								// 求解依赖流形类型
	Type type;                                      // 类型
	int32 pointCount;								// 流形的点的总数
};
//  这是用于求解当前状态下的接触流形
struct b2WorldManifold
{
	/**************************************************************************
	* 功能描述:根据流形和提供的变换初始化此结构体。假设适度移动从原始状态开始的。
	            这不能改变点的数量、冲量等等。半径必须来着与产生流形的形状。
	* 参数说明: manifold:流形的指针,用于初始化结构体
	             xfA     :变换A的引用
				 radiusA :形状A的半径
				 xfB     :变化B的引用
				 radiusB :形状B的半径
	* 返 回 值: (void)
	***************************************************************************/
	void Initialize(const b2Manifold* manifold,
					const b2Transform& xfA, float32 radiusA,
					const b2Transform& xfB, float32 radiusB);

	b2Vec2 normal;							//世界向量方向从A到B
	b2Vec2 points[b2_maxManifoldPoints];	//世界接触点(交点)
};
//接触点的状态
enum b2PointState
{
	b2_nullState,		//点不存在
	b2_addState,		//在update中添加点
	b2_persistState,	//点在update中持续存在
	b2_removeState		//点移除update
};

//裁剪顶点结构体,用于接触流形的求解
struct b2ClipVertex
{
	b2Vec2 v;        //接触点
	b2ContactID id;  //接触id
};

//光线输入数据。光线从p1扩展到到p1 + maxFraction * (p2 - p1)
struct b2RayCastInput
{
	b2Vec2 p1, p2;             //光线(或射线)上的两个点,其中p1是起始点
	float32 maxFraction;       //需要检测的光线范围
};

//光线输出数据。光线达到p1 + fraction * (p2 - p1),其中p1和 p2来自b2RayCastInput
struct b2RayCastOutput
{
	b2Vec2 normal;            //法向量
	float32 fraction;         //碰撞点位置的参数值
};
///轴对齐包围盒
struct b2AABB
{
	/**************************************************************************
	* 功能描述:验证边界排序是否有效
	* 参数说明: (void)
	* 返 回 值: (void)
	***************************************************************************/
	bool IsValid() const;
	/**************************************************************************
	* 功能描述:获取AABB的中心点
	* 参数说明: (void)
	* 返 回 值: 中心点坐标
	***************************************************************************/
	b2Vec2 GetCenter() const
	{
		return 0.5f * (lowerBound + upperBound);
	}
	/**************************************************************************
	* 功能描述:获取AABB的区段(宽高的一半)
	* 参数说明: (void)
	* 返 回 值: aabb的区段
	***************************************************************************/
	b2Vec2 GetExtents() const
	{
		return 0.5f * (upperBound - lowerBound);
	}
	/**************************************************************************
	* 功能描述:获取AABB的周长
	* 参数说明: (void)
	* 返 回 值: AABB的周长
	***************************************************************************/
	float32 GetPerimeter() const
	{
		float32 wx = upperBound.x - lowerBound.x;
		float32 wy = upperBound.y - lowerBound.y;
		return 2.0f * (wx + wy);
	}
	/**************************************************************************
	* 功能描述:合并AABB
	* 参数说明: aabb:aabb的引用
	* 返 回 值: (void)
	***************************************************************************/
	void Combine(const b2AABB& aabb)
	{
		lowerBound = b2Min(lowerBound, aabb.lowerBound);
		upperBound = b2Max(upperBound, aabb.upperBound);
	}
	/**************************************************************************
	* 功能描述:合并两个AABB,为对象的aabb赋值
	* 参数说明: aabb1:一个AABB的引用
	             aabb2:一个AABB的引用
	* 返 回 值: (void)
	***************************************************************************/
	void Combine(const b2AABB& aabb1, const b2AABB& aabb2)
	{
		lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound);
		upperBound = b2Max(aabb1.upperBound, aabb2.upperBound);
	}
	/**************************************************************************
	* 功能描述:当前aabb是否包含提供的AABB
	* 参数说明: aabb1:提供的AABB的引用
	* 返 回 值: true :包含
	             false:不包含
	***************************************************************************/
	bool Contains(const b2AABB& aabb) const
	{
		bool result = true;
		result = result && lowerBound.x <= aabb.lowerBound.x;
		result = result && lowerBound.y <= aabb.lowerBound.y;
		result = result && aabb.upperBound.x <= upperBound.x;
		result = result && aabb.upperBound.y <= upperBound.y;
		return result;
	}
	/**************************************************************************
	* 功能描述:光线投射
	* 参数说明: output:光线输出数据引用
	             input :光线输入数据引用
	* 返 回 值: true :碰撞
	             false:不碰撞
	***************************************************************************/
	bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const;

	b2Vec2 lowerBound;	//lower顶点
	b2Vec2 upperBound;	//upper顶点
};

对于b2ContactFeature和b2ContactID来说主要是和接触相关的结构体,用于保存两形状碰撞时产生的碰撞点的相关信息。对于b2ManifoldPoint、b2Manifold、b2WorldManifold、b2PointState、b2ClipVertex主要用于流形(关于流形 参照 http://zh.wikipedia.org/wiki/流形)相关的结构体,关于具体信息,请看上面的注释。对于b2RayCastInput和b2RayCastOutput结构,这个大家应该很眼熟吧,主要是在光线投射下,保存光线输入和输出数据的。再看看我们更眼熟的b2AABB结构体(小样,原来你的家在这儿,这下你跑不了了吧,嘿嘿),这里有些功能函数的实现,在此也不多说了。


3、全局函数的声明

/**************************************************************************
* 功能描述:通过两个流形计算点的状态。这些状态与从manifold1到maniflod2的过渡有关
            所以state1要么是持续更新要么就是删除
            state2要么是添加要么是持续更新
* 参数说明: state1   :状态1,用于保存mainfold1中接触点的状态
             state2   :状态2,用于保存mainfold2中接触点的状态
			 manifold1:流形1
			 manifold2:流形2
* 返 回 值: (void)
***************************************************************************/
void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],
					  const b2Manifold* manifold1, const b2Manifold* manifold2);
/**************************************************************************
* 功能描述:求两个圆形成的碰撞流形
* 参数说明: manifold :流形对象的指针
             circleA  :圆形A对象指针
			 xfA      :变换A对象引用
			 circleB  :圆形B对象指针
			 xfB      :变换B对象引用
* 返 回 值: (void)
***************************************************************************/
void b2CollideCircles(b2Manifold* manifold,
					  const b2CircleShape* circleA, const b2Transform& xfA,
					  const b2CircleShape* circleB, const b2Transform& xfB);

/**************************************************************************
* 功能描述:求一个多边形和一个圆形成的碰撞流形
* 参数说明: manifold :流形对象的指针
             polygonA :多边形A对象指针
			 xfA      :变换A对象引用
			 circleB  :圆形B对象指针
			 xfB      :变换B对象引用
* 返 回 值: (void)
***************************************************************************/
void b2CollidePolygonAndCircle(b2Manifold* manifold,
							   const b2PolygonShape* polygonA, const b2Transform& xfA,
							   const b2CircleShape* circleB, const b2Transform& xfB);

/**************************************************************************
* 功能描述:求解两个多边形碰撞产生的流形
* 参数说明: manifold:碰撞流形指针,用于保存两个圆产生的流形
             polygonA:多边形A指针
			 xfA     :变换A
			 polygonB:多边形B指针
			 xfB     :变换B
* 返 回 值: (void)
***************************************************************************/
void b2CollidePolygons(b2Manifold* manifold,
					   const b2PolygonShape* polygonA, const b2Transform& xfA,
					   const b2PolygonShape* polygonB, const b2Transform& xfB);
/**************************************************************************
* 功能描述:求解一个边缘形状和一个圆碰撞产生的流形
* 参数说明: manifold:碰撞流形指针,用于保存两个圆产生的流形
             polygonA:多边形A指针
			 xfA     :变换A
			 polygonB:多边形B指针
			 xfB     :变换B
* 返 回 值: (void)
***************************************************************************/
void b2CollideEdgeAndCircle(b2Manifold* manifold,
							   const b2EdgeShape* polygonA, const b2Transform& xfA,
							   const b2CircleShape* circleB, const b2Transform& xfB);
/**************************************************************************
* 功能描述:求解一个边缘形状和一个多边形碰撞产生的流形
* 参数说明: manifold:碰撞流形指针,用于保存两个圆产生的流形
             edgeA   :边缘形状A指针
			 xfA     :变换A
			 polygonB:多边形B指针
			 xfB     :变换B
* 返 回 值: (void)
***************************************************************************/
void b2CollideEdgeAndPolygon(b2Manifold* manifold,
							   const b2EdgeShape* edgeA, const b2Transform& xfA,
							   const b2PolygonShape* circleB, const b2Transform& xfB);


/**************************************************************************
* 功能描述:裁剪碰撞流形
* 参数说明: vOut        :裁剪顶点输出数组
             vIn         :裁剪顶点输入数组
			 normal      :法向量
			 offset      :偏移量
			 vertexIndexA:顶点索引
* 返 回 值: 输出顶点的个数
***************************************************************************/
int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],
							const b2Vec2& normal, float32 offset, int32 vertexIndexA);
/**************************************************************************
* 功能描述:测试两个通用的形状是否重叠。
            通过距离【Distance】判断是否重叠
* 参数说明: shapeA :形状A
             indexA :索引A
			 shapeB :形状B
			 indexB :索引B
			 xfA    :变换A
			 xfB    : 变换B
* 返 回 值:true    :重叠
            false   :不重叠
***************************************************************************/
bool b2TestOverlap(	const b2Shape* shapeA, int32 indexA,
					const b2Shape* shapeB, int32 indexB,
					const b2Transform& xfA, const b2Transform& xfB);

此部分,注释已经说的很清楚了,在此也不赘述了。

 

4、内联函数的实现

//验证边界排序是否有效
inline bool b2AABB::IsValid() const
{
	b2Vec2 d = upperBound - lowerBound;
	bool valid = d.x >= 0.0f && d.y >= 0.0f;
	valid = valid && lowerBound.IsValid() && upperBound.IsValid();
	return valid;
}
/**************************************************************************
* 功能描述:测试两个通用的形状是否重叠。
            通过aabb判断是否重叠
* 参数说明: a :AABB对象的引用
             b :AABB对象的引用
* 返 回 值: true :重叠
             false:不重叠
***************************************************************************/
inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b)
{
	b2Vec2 d1, d2;
	d1 = b.lowerBound - a.upperBound;
	d2 = a.lowerBound - b.upperBound;

	if (d1.x > 0.0f || d1.y > 0.0f)
		return false;

	if (d2.x > 0.0f || d2.y > 0.0f)
		return false;

	return true;
}

对于b2TestOverlap函数,我们可以看到此处进行了函数的重载,对于上一个TestOverlap函数是通过距离【Distance】判断是否重叠的,而这个函数则是通过通过aabb判断是否重叠。两者用不同的方法,却实现了相同的效果,但是从某些方面来说通过距离判断是否重叠的话更加精确一点,但效率方面却要第一点。为此,我们可以根据用户的不同要求让用户选择不同的函数,如用户要求精确度高,同时效率方面不是太在乎的我们可以选择通过距离判断的那种,相反,我们可以选择通过aabb判断的那种。

 

我们再来看看b2Collision.cpp文件,还是上源码:

//根据流形和提供的变换初始化此结构体。
void b2WorldManifold::Initialize(const b2Manifold* manifold,
						  const b2Transform& xfA, float32 radiusA,
						  const b2Transform& xfB, float32 radiusB)
{
	//判断流形的点
	if (manifold->pointCount == 0)
	{
		return;
	}
	//获取流形的类型
	switch (manifold->type)
	{
	case b2Manifold::e_circles:                                   //圆形
		{
			//设置法向量
			normal.Set(1.0f, 0.0f);
			b2Vec2 pointA = b2Mul(xfA, manifold->localPoint);
			b2Vec2 pointB = b2Mul(xfB, manifold->points[0].localPoint);
			//判断两点是否重合
			if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon)
			{
				//获取法向量,并标准化
				normal = pointB - pointA;
				normal.Normalize();
			}
			//获取世界接触点
			b2Vec2 cA = pointA + radiusA * normal;
			b2Vec2 cB = pointB - radiusB * normal;
			points[0] = 0.5f * (cA + cB);
		}
		break;

	case b2Manifold::e_faceA:                                   //面A
		{
			//
			normal = b2Mul(xfA.q, manifold->localNormal);
			b2Vec2 planePoint = b2Mul(xfA, manifold->localPoint);
			//获取世界接触点
			for (int32 i = 0; i < manifold->pointCount; ++i)
			{
				b2Vec2 clipPoint = b2Mul(xfB, manifold->points[i].localPoint);
				b2Vec2 cA = clipPoint + (radiusA - b2Dot(clipPoint - planePoint, normal)) * normal;
				b2Vec2 cB = clipPoint - radiusB * normal;
				points[i] = 0.5f * (cA + cB);
			}
		}
		break;

	case b2Manifold::e_faceB:                                 //面B
		{
			normal = b2Mul(xfB.q, manifold->localNormal);
			b2Vec2 planePoint = b2Mul(xfB, manifold->localPoint);
			//获取世界接触点
			for (int32 i = 0; i < manifold->pointCount; ++i)
			{
				b2Vec2 clipPoint = b2Mul(xfA, manifold->points[i].localPoint);
				b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal;
				b2Vec2 cA = clipPoint - radiusA * normal;
				points[i] = 0.5f * (cA + cB);
			}
			// 保证法向量的顶点是A到B的
			normal = -normal;
		}
		break;
	}
}
//通过给定的两个流形计算点的状态。
void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],
					  const b2Manifold* manifold1, const b2Manifold* manifold2)
{
	//置空初始状态
	for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
	{
		state1[i] = b2_nullState;
		state2[i] = b2_nullState;
	}
	//遍历maifold1检测状态的持续和删除
	for (int32 i = 0; i < manifold1->pointCount; ++i)
	{
		//获取mainfold1的接触id
		b2ContactID id = manifold1->points[i].id;
		//将状态置为删除状态
		state1[i] = b2_removeState;
		//遍历manifold2检测是否有接触存在
		//若有则修改当前状态为持续
		for (int32 j = 0; j < manifold2->pointCount; ++j)
		{
			//接触点是否相等
			if (manifold2->points[j].id.key == id.key)
			{
				//改变接触状态
				state1[i] = b2_persistState;
				break;
			}
		}
	}

	//遍历maifold1检测状态的持续和添加
	for (int32 i = 0; i < manifold2->pointCount; ++i)
	{
		//获取mainfold2的接触id
		b2ContactID id = manifold2->points[i].id;
		//将状态置为添加状态
		state2[i] = b2_addState;
		//遍历manifold1检测是否有接触存在
		//若有则修改当前状态为持续
		for (int32 j = 0; j < manifold1->pointCount; ++j)
		{
			//接触点是否相等
			if (manifold1->points[j].id.key == id.key)
			{
				//改变接触状态
				state2[i] = b2_persistState;
				break;
			}
		}
	}
}
//光线投射
bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const
{
	//获取float的边值
	float32 tmin = -b2_maxFloat;
	float32 tmax = b2_maxFloat;
	//获取差值并用b2Abs取它的绝对值
	b2Vec2 p = input.p1;
	b2Vec2 d = input.p2 - input.p1;
	b2Vec2 absD = b2Abs(d);
	//平面的法线
	b2Vec2 normal;

	for (int32 i = 0; i < 2; ++i)
	{
		if (absD(i) < b2_epsilon)
		{
			// 平行
			if (p(i) < lowerBound(i) || upperBound(i) < p(i))
			{
				return false;
			}
		}
		else
		{
			float32 inv_d = 1.0f / d(i);
			float32 t1 = (lowerBound(i) - p(i)) * inv_d;
			float32 t2 = (upperBound(i) - p(i)) * inv_d;

			//法向量方向
			float32 s = -1.0f;

			if (t1 > t2)
			{
				b2Swap(t1, t2);
				s = 1.0f;
			}
			// 提升最小值
			if (t1 > tmin)
			{
				normal.SetZero();
				normal(i) = s;
				tmin = t1;
			}
			// 下降最大值
			tmax = b2Min(tmax, t2);

			if (tmin > tmax)
			{
				return false;
			}
		}
	}
	//验证tmin的有效值
	//光线的起始点在盒子内部
	//或者光线的相交不在maxfraction范围之内
	if (tmin < 0.0f || input.maxFraction < tmin)
	{
		return false;
	}
	//保存交点信息
	output->fraction = tmin;
	output->normal = normal;
	return true;
}

// Sutherland-Hodgman裁剪. 参见 http://en.wikipedia.org/wiki/Sutherland-Hodgman
int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],
						const b2Vec2& normal, float32 offset, int32 vertexIndexA)
{
	// 开始时没有输出点
	int32 numOut = 0;
	//计算线与末尾点的距离
	float32 distance0 = b2Dot(normal, vIn[0].v) - offset;
	float32 distance1 = b2Dot(normal, vIn[1].v) - offset;
	// 点都在平面的一边
	if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
	if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];

	// 点在平面的两边
	if (distance0 * distance1 < 0.0f)
	{
		// 查找边缘与平面的交叉点
		float32 interp = distance0 / (distance0 - distance1);
		vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
		// VertexA 触碰到edgeB
		vOut[numOut].id.cf.indexA = vertexIndexA;
		vOut[numOut].id.cf.indexB = vIn[0].id.cf.indexB;
		vOut[numOut].id.cf.typeA = b2ContactFeature::e_vertex;
		vOut[numOut].id.cf.typeB = b2ContactFeature::e_face;
		++numOut;
	}
	//输出点个数
	return numOut;
}
//测试两个通用的形状是否重叠。
bool b2TestOverlap(	const b2Shape* shapeA, int32 indexA,
					const b2Shape* shapeB, int32 indexB,
					const b2Transform& xfA, const b2Transform& xfB)
{
	//初始化input变量
	b2DistanceInput input;
	input.proxyA.Set(shapeA, indexA);
	input.proxyB.Set(shapeB, indexB);
	input.transformA = xfA;
	input.transformB = xfB;
	input.useRadii = true;
	//声明cache对象
	b2SimplexCache cache;
	cache.count = 0;
	//声明output变量,并获取output
	b2DistanceOutput output;

	b2Distance(&output, &cache, &input);
	//判断是否重叠,并返回
	return output.distance < 10.0f * b2_epsilon;
}

本部分主要4个函数,Initialize函数初始化世界流形(当前状态下的流形)。


b2GetPointStates函数则是重新更新接触点的状态,这个函数是到程序员要用的时候自己手动调用的。


RayCast函数则用于光线投射,在这里,我们注意下那个for循环,有个问题,大家先思考一下,为什么i的终止值小于2呢?那个2究竟是干什么的?


b2ClipSegmentToLine函数是裁剪碰撞流形,这里用到了Sutherland-Hodgman裁剪,(参见 http://en.wikipedia.org/wiki/Sutherland-Hodgman),关于Sutherland-Hodgman裁剪算法,我们简单的说一下,这种方法也叫逐边裁减法,主要思想是:将多边形的各边先相对于窗口的某一条边界进行裁剪,然后将裁剪结果再与另一条边界进行裁剪,如此重复多次,便可得到最终结果。再来说说我们是怎么做的:

  • 由函数传入相对与法线的偏移量offset,将法线加偏移量作为边界,将平面分成两部分:可见部分和不可见部分。
  • 在获取两个输入点向量在法线方向上的长度,并和边界做比较相减,获取结果。
  • 然后判断结果和是否有交点,并保存到数组中。
  • 因为此处我们只有两个点,故不需要多次重复裁剪。

     

    b2TestOverlap函数主要是通过判断距离来实现是否重叠的,在此就不多说了。


    大家知道上面那个问题的答案了吗?

    知道了?!太好了,那我就不说了。嘿嘿。。。


    ps:

     

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








    1楼ybi123昨天 14:2545477714

        
    [3] 小弟我被大学下了吗
        来源: 互联网  发布时间: 2014-02-18
    我被大学上了吗?
    现在是2012年12月20日凌晨零点39分,地点是国立西安大学二号公寓212室。发牢骚的就是我喽。
           其实并没有什么特别的意思,尤其是选在了这么一个深夜。我并没有悟透了什么大道理然后写下来感化众人。我没那么高尚,也没那哲学家的本事。这么晚了还不睡知识因为白天睡的太多了晚上不是特别困。写些什么呢??我也没有准确的中心思想,那就写写我大学三年来我对未来的看法。
           大家对未来都有着不同的态度。有些人觉得自己的未来很渺茫,因为文理并不是一个211,985学校,再加上现在的社会风气都在宣扬一个准则:只有高学历才能找到好工作,像文理这样的学校别指望他能给你多好的工作机会,出去了一切从头再来,反正学校就这个样。还有一些人,把考研当做唯一的出路。拼命的学习,拼命的学习,但是问问他为什么考研?他说就是为了能找一个“体面”的工作。为了以后生活能过的好一点。还又的人他对自己的专业一点兴趣都没有,别说学习了,他连自己的专业书都不愿意看一眼。反正现在的大学跟我高中时候想象的不一样。
          大学里面除了好多怪想象,整天爱学习的人大多被孤立了,但是每到学期末却深受欢迎。女孩子们学的最快的不是只是,而是怎样打扮。这点我深信不疑。大学生们的作业写的很多很多,但是我写的作业我都不知道我写过什么。实验课是一群人看着一个人连电路,然后做实验的人都不知道为什么是这样做。反正结果是出来了。至于对不对。。。。。。。。。看吧!到最后每个人的实验报告都写的很工整。然而这几十份实验报告最多也就几种版本吧。上课我们什么都可以不带就是不能不带我们的手机。晚上我们是睡不着的,上课我们是睡不醒的。这一段你们千万别对号入座,我也有好多可以入座的地方,要不我怎么能写的这么详细呢,自嘲自嘲。
            其实大学让我们上的这么失败有很多因素在里面。我们不必去计较这些。以内不管你把责任推给谁反正你是上了!而且被大学上的那么彻彻底底。也是昂。当我们迈进大学的第一步有是有我们已经彻彻底底的错了。我们的教育就有着这个软肋。我们入大学之前的教育是失败的。彻彻底底的。我们之前的学习就是为了能考上大学,至于我们为什么考大学???谁想过??我到大学里想要什么??我们小学,初中,高中,高考,然后就面临一个高考志愿。。我报考什么呢??好多人说:孩子!报热门吧!以后好找工作!我只想给说这话的人说一句:去他娘的狗屁!!!!你知道我喜欢吗?你知道我适合吗?以后我工作了我快乐吗?我的生活就是为了吃饭是吗?我为的就是能多挣点钱,然后可以买房,出得起丈母娘要的彩礼,买得起奶粉纸尿裤,能养家糊口。这让我想起一个故事:一个记者去贫困山区采访遇到一个放羊的小男孩,然后记者问他:“你为什么放羊呀?”男孩回答:“挣钱。”记者又问:挣钱了干什么呀?男孩回答:“娶媳妇.。”那娶媳妇了干什么呀?生儿子。有了儿子干什么呀?放羊。你会笑???其实想想如果我们就是为了找个好工作我们和那个男孩有什么区别?
           还有一些人,他们报考专业时茫然失措,据我了解这样的人不在少数。为什么呢??因为他们根本就不知道他们喜欢什么专业,也无法从简简单单的几个字的专业名称上知道这个专业是不是自己喜欢的。更有甚者即使他知道每个专业是干什么的他也不知道报哪个专业。为什么??因为之前的十二年寒窗苦读没有一个老师告诉我们要有自己的爱好呀!他们只会告诉我们要考高分,不要偏科。坦白说我就是一个偏科严重的人。。。。。。。。。
    太晚了,
    困了,
    明天继续吧,
    或许后天吧,
    或许大后天吧
    看心情吧。最紧要忙呀 4楼honesty2008昨天 23:40都是社会风气惹的货!!!3楼Brave_ly昨天 23:17赞一个,我也一个苦逼的大三工科男,跟你情况差不多,引起共鸣了吧,现在大三了基本忙忙碌碌的走走停停,未来应该是有点迷茫吧!!!2楼cometwo昨天 19:36对1楼hbykdx2010昨天 18:55都是社会风气惹的货!!!

        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    php开源软件 iis7站长之家
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3