Box2D v2.3.0 用户指南(第四章)

2023-11-05



第四章 碰撞模块(Collision Module)

4.1简介

碰撞模块包含形状(shape)以及操作它们的函数。此外,碰撞模块还包括dynamictree和broad-phase来加快大型系统的碰撞处理速度。

碰撞模块被设计为可独立于动态系统(dynamicsystem)工作,例如,你可以用dynamic tree来处理你游戏中除了物理计算之外的其他部分。

当然了,Box2D主要还是作为一款刚体物理引擎,所以单独使用碰撞模块可能会让人觉得受限制,因此,我不会花很多时间来针对碰撞模块写详细的文档或是去修饰API。

 

4.2形状

形状描绘了碰撞几何形状(collisiongeometry),除了在物理模拟中使用外也可以单独使用,你至少需要理解如何创建形状,以及如何将形状附加到刚体上。

Box2D形状的基类为b2Shape,基类提供了下面几类方法:

·  测试一个点是否和形状重叠(点在形状上)

·  对形状做射线投射(ray cast)

·  计算形状的AABB(axis aligned boundingbox,能够恰好包住形状并且各个边均与坐标轴(之一)平行的四边形)

·  计算形状的质量

此外,每个形状还有一个类型(type)和一个半径(radius)成员变量,即使是多边形类,也包含半径这个成员变量,我们下面会讨论到。

记住一个形状并不知道物体(body)的存在,它存在于动态系统之外,形状的大小和效率经过优化以简洁的形式存储起来。同样的,想要移动一个形状并不容易。你需要手动的设置形状的顶点位置来移动它。然而,当一个形状通过装置被附加到物体上,形状就牢牢地固定在物体上随物体一起移动了。简单概括如下:

·  当一个形状没有附加到物体上时,你可以看到它的顶点在世界坐标系中。

·  当一个形状附加到物体上以后,你可以看到它的顶点在本地坐标系中了。

 

圆形状(circle shape)

圆形状具有一个位置和半径。圆形状是实心的,你不能创建一个空心圆。

b2CircleShape circle;

circle.m_p.Set(2.0f, 3.0f);

circle.m_radius = 0.5f;

 

多边形状(polygon shape)

多边形状是实心的凸多边形,一个凸多边形满足多边形内任意两点之间的线段都不与多边形的边相交。Box2D中的多边形是实心的,不能是凹多边形,一个多边形有3个或3个以上顶点。


多边形的顶点是按逆时针排列(counter clockwisewinding,CCW)存储的,我们需要对CCW的概念小心一些,因为CCW是按照右手坐标系统定义的(z轴由里面指向外面),相对于你的屏幕,有可能就变成顺时针了,取决于你的坐标系统的定义。


多边形的成员是公有的(public),但是我们最好还是通过初始化函数来创建一个多边形。初始化函数创建法向量(normalvector)并且检查初始化参数是否合法(validation)。

你可以通过传入一个顶点数组来创建多边形,数组的最大容量由b2_maxPolygonVertices来控制,默认值为8。对于大多数凸多边形来说,这个值足够了。

方法b2PolygonShape::Set自动计算出凸多边形的外边界并建立恰当的缠绕顺序(边的顺序)。当点数较少的时候,方法执行效率非常高。如果你增大b2_maxPolygonVertices,这个计算的执行效率有可能变得很低,同时需要我们注意的是,这个计算函数有可能会移除我们提供的顶点或者对其重新排序,当顶点之间的距离小于b2_linearSlop这个常量时,它们就会被合并。

//This defines a triangle in CCW order

b2Vec2 vertices[3];

vertices[0].Set(0.0f, 0.0f);

vertices[1].Set(1.0f, 0.0f);

vertices[2].Set(0.0f, 0.1f);

int32 count = 3;

b2PolygonShape polygon;

polygon.Set(vertices, count);

多边形类提供了一些方便的方法来创建矩形。

void SetAsBox(float32 hx, float hy);

void SetAsBox(float32 hx, float hy, const b2Vec2& center,float32 angle);

多边形类从b2Shape继承了一个半径(radius)属性,半径属性在多边形外面创建了一个外层(skin),外层用来在堆叠场景中让多边形彼此分离。这样就能够对核心多边形(corepolygon)模拟连续碰撞(continuouscollision,Box2D中解决高速物体穿透的一种算法,由于Box2D中使用时间片来模拟,因此当物体处于高速运动时,一个时间片内的位移可能非常大,导致物体穿过在位移路径上的刚体而没有发生碰撞,Box2D中采用连续碰撞来牺牲一定的效率处理高速物体,以避免这种情况发生,译者注)。


多边形皮肤通过将多边形彼此分离来防止穿透(tunneling),这导致了形状之间有一点点的间隙。不过,你实际上看到的多边形相比于他们之间的间隙来说要大得多。


 

边形状(edge shape)

边形状即线段,用来帮助我们在游戏中创建自由的静态(static)环境。使用边形状的一个主要限制是,他们能够和圆形状、多边形发生碰撞,但是边形状之间不能发生碰撞。Box2D中在计算碰撞时要求碰撞的两个物体至少一个具有面积,边形状没有面积,所以他们之间不可能发生碰撞。

//This an edge shape

b2Vec2 v1(0.0f, 0.0f);

b2Vec2 v2(1.0f, 0.0f);

b2EdgeShape edge;

edge.Set(v1, v2);

很多游戏中的场景都是由多个线段首尾相连创建而成的,当一个多边形沿着线段链(chain)移动的时候,就有可能出现意想不到的问题。在下面图中我们看到,一个四边形和一个内部顶点(internalvertex)碰撞了,这种“鬼打墙”(ghost collision)现象的产生是由多边形和内部顶点生成的内部碰撞法线(internal collisionnormal)发生了碰撞而产生的。


如果edge1不存在,那么这个碰撞看起来很合理(box和edge2理应发生碰撞),但是由于edge1的存在,就导致这种碰撞看起来像是一个漏洞(bug)。但是通常情况下,在Box2D中处理物体碰撞的时候,会将它们视为孤立的(这也就是为什么有这个例子了)。

好消息是,边形状提供了一种机制用来消除这种“鬼打墙”的现象,如下图,Box2D中,通过存储相邻的节点,将它们视为影子顶点(ghostvertice),这样就能够防止内部碰撞了。


//This is an edge shape with ghost vertices.

b2Vec2 v0(1.7f, 0.0f);

b2Vec2 v1(1.0f, 0.25f);

b2Vec2 v2(0.0f, 0.0f);

b2Vec2 v3(-1.7f, 0.4f);

 

b2EdgeShape edge;

edge.Set(v1, v2);

edge.m_hasVertex0 = true;

edge.m_hasVertex3 = true;

edge.m_vertex0 = v0;

edge.m_vertex3 = v3;

整体看来,这种缝合的方式看起来有些费力不讨好,所以我们引出链形状(chainshape)。

 

链形状(chain shape)

链形状提供了方便的方法让我们通过连接线段来创建静态世界。连形状自动消除我们之前遇到的“鬼打墙”现象,并且链形状能够提供双向的碰撞模拟(链的两侧都可以发生碰撞)。


//This is a chain shape with isolated vertices

b2Vec2 vs[4];

vs[0].Set(1.7f, 0.0f);

vs[1].Set(1.0f, 0.25f);

vs[2].Set(0.0f, 0.0f);

vs[3].Set(-1.7f, 0.4f);

b2ChainShape chain;

chain.CreateChain(vs, 4);

你也许有一个卷动的游戏世界需要将多组链形状连接到一起,你可以像连接线形状(b2EdgeShape)一样,使用上面提到的影子顶点将链形状进行连接。

//Install ghost vertices

chain.SetPrevVertex(b2Vec2(3.0f, 1.0f));

chain.SetNextVertex(b2Vec2(-2.0f, 0.0f));

下面的方法可以用来创建一个环(loop):

//Create a loop. The first and last vertices are connected.

b2ChainShape chain;

chain.CreateLoop(vs, 4);

自相交(self-intersection)的链形状(如图)是不支持的,如果你真的在游戏中创建出自相交的链形状,它有可能会好用也有可能不好用,用来处理“鬼打墙”现象的代码会假定没有自相交的链。此外,如果顶点距离太近,也可能产生问题,因此请确保所有的边长度都大于b2_linearSlop(默认定义是5mm)。


链形状的每一条边都被当做一个子形状处理,你可以通过索引(index)来访问这些边。当一个链形状被连接到一个物体(body)上时,在broad-phase碰撞树中,每一条边都有自己的外轮廓(boundingbox,见第三章中我们提到的AABB的解释)。

//Visit each child edge

for (int32 i = 0; i < chain.GetChildCount(); ++i)

{

b2EdgeShape edge;

chain.GetChildEdge(&edge, i);

}

 

4.3一元的几何查询(unarygeometric queries)

你可以对一个图形执行一系列的几何查询。

 

形状-点 测试(shape point test)

你可以测试一个点是否与形状有交叠(即点落在形状内)。通过提供一个图形变换(transformfor the shape)和一个世界中的点:

b2Transform transform;

transform.SetIdentity();

b2Vec2 point(5.0f, 2.0f);

bool hit = shape->TestPoint(transform, point);

如果形状是边形状(edge)或链形状(chain),则始终返回false,即使是闭合的链形状(loop)。

 

形状射线投射(shape ray cast)

你可以向形状投过一道射线,然后得到射线射入形状的入射点和法线向量。如果射线从形状内部射出,则不会得到任何入射点。下面代码中我们用到了一个子索引(child index),因为射线投射一次只能作用于一个边(对于其他形状,这个参数会被忽略)。

b2Transform transform;

transform.SetIdentity();

b2RayCastInput input;

input.p1.Set(0.0f, 0.0f, 0.0f);

input.p2.Set(1.0f, 0.0f, 0.0f);

input.maxFraction = 1.0f;

int32 childIndex = 0;

b2RayCastOutput = output;

bool hit = shape->RayCast(&output, input, transform,childIndex);

if (hit)

{

b2Vec2 hitPoint = input.p1 +output.fraction * (input.p2–input.p1);

}

(注:input参数中,p1和p2点定义了射线的方向,maxFraction则决定了射线段的长度,也就是定义了在这个射线上多长的范围内来进行射线投射,如果这个值设置的较小,有可能得不到任何交点,如下图所示)


 

4.4二元方法

碰撞模块提供了一些对等函数来对一对形状进行一些运算,包括:

·  重叠(overlap)

·  接触取样(contact manifold)

·  距离(distance)

·  碰撞时间(time of impact)

 

重叠

你可以用下面的方法来测试两个形状是否重合:

b2Transform xfA = …, xfB = …;

bool overlap = b2TestOverlap(shapeA, indexA, shapeB, indexB, xfA,xfB);

上面的indexA和indexB参数也是为了链形状提供的(链形状需要对每条边做检测)。

 

接触取样

Box2D提供了用于计算重叠对象的接触点(contactpoint)的方法,如果我们圆形-圆形或者圆形-多边形接触,我们只能够得到一个接触点和法线。当多边形和多边形接触时,我们计算得到2个接触点,这些点具有相同的法向量,因此Box2D将他们用一个结构体组装起来。接触解析器(contactsolver)利用可以利用这个方法保证堆叠对象的稳定性。


通常我们不需要去直接计算接触点,我们仅仅需要得到的模拟效果就可以了。

b2Manifold结构体定义了一个法向量和至多两个接触点,法向量和接触点使用的是本地坐标,为了给接触解析器提供方便,每个接触点都存储了法向和切向(摩擦)冲量。

b2Manifold中的数据被优化以便内部使用,如果你需要使用这些数据,最好是使用b2WorldManifold结构体来生成符合世界坐标系的法向量和接触点。你需要提供一个b2Manifold结构体,一个形状和变换(transform)和半径。

b2WorldManifold worldManifold;

worldManifold.Initialize(&manifold, transformA, shapeA.m_radius,transform, shapeB.m_radius);

for (int32 i = 0; i < manifold.pointCount; i++)

{

b2Vec2 point = worldManifold.points[i];

}

注意循环中使用的pointCount是原始的b2Manifold的pointCount,原因是b2WorldManifold结构体中并没有定义这个值。

在模拟过程中,形状会发生移动导致取样发生变化,接触点的数量会发生变化(增加或减少),你可以通过b2GetPointState来检测变化。

b2PointState state1[2], state2[2];

b2GetPointStates(state1, state2, &manifold1, &manifold2);

if (state1[0] == b2_removeState)

{

//process event

}

 

距离

b2Distance方法可以用来计算两个形状之间的距离。这个方法要求两个形状都转换为b2DistanceProxy类,对于大量的计算,在计算之前还需要初始化一些缓存对象,具体的细节请参阅b2Distance.h文件。


 

碰撞时间

如果两个形状都以高速运动,就会发生穿透(tunnel)现象。


b2TimeOfImpact方法用来计算两个形状的碰撞时间,称为timeof impact(TOI),b2TimeOfImpact主要是用来防止穿透现象的产生,尤其是防止运动物体穿出静态的几何体跑到外面去。

这个计算方法考虑两个形状的旋转和平移,然而如果旋转非常大的话,还是可能导致漏掉碰撞。但是函数仍然会跑高一个非重叠的时间,并且会捕捉到所有的平移碰撞。

碰撞时间函数定义了一个初始的分离轴(separatingaxis),并保证形状无法穿过这条轴。这可能会导致在结束位置附近漏掉一些碰撞,尽管如此,这是最快的也是最适合的解决碰撞的方法了。


(解释一下两幅图:上面一幅图中,第一幅图t=0的时候,物体要向t=1的位置旋转,由于t=1时发生了碰撞,因此,碰撞被检测到了,下面的一幅图,t=0和t=1时刻均没有发生碰撞,导致碰撞没有被检测到)

很难对于旋转幅度做一个严格的限制,有时候甚至是很小的旋转幅度都会导致碰撞被错过检测,一般来说,这些没有被检测到的碰撞不会影响游戏性,它们只是一闪而过而已。

碰撞时间函数需要两个形状参数(转换为b2DistanceProxy)和两个b2Sweep结构体参数,sweep结构体定义了形状初始和结束的变换。

你可以使用固定的旋转幅度去执行一次函数,在这种情况下,碰撞时间函数不会漏掉任何碰撞。

 

4.5动态树(dynamictree)

Box2D中用b2DynamicTree类来有效地组织大量的形状。这个类并不知道任何形状,它只是通过用户指针来操作形状的AABB(axis-alignedbounding box,前面做了解释)。

动态树是一个分层次的AABB树,每一个内部节点都有两个孩子节点,每个叶子节点都是一个单独的用户AABB。整棵树使用旋转来保持平衡,即使是在衰减的时候。

树的结构支持高效的射线投射和区域查询。例如,你的场景中可能会有上百个形状,你如果用蛮力对场景中的各个形状进行射线投射,效率会非常低,因为这个过程并没有利用形状的分布。相反的,我们可以维护一个动态树,接着对动态树进行射线投射,这样可以略过树中大量的形状。

一次区域查询使用树来找到所有与查询AABB(queryAABB)重叠的AABB,这比暴力计算高效的多,因为很多形状都会被跳过。


一般情况下,你不需要直接使用动态树,你只需要通过b2World来调用射线投射和区域查询的方法就可以了。如果你需要实例化你自己的动态树,你可以通过查看Box2D中的调用方法来学习如何使用它。

 

4.6 Broad-phase

在一个时间间隔(timestep)内发生的碰撞处理过程可以被分成narrow-phase和broad-phase两个阶段,在narrow-phase阶段我们计算形状之间的接触点,假设我们有N个形状,如果用遍历的方法,我们需要为N*N/2对形状执行narrow-phase。b2BroadPhase使用动态树来管理这些形状,显著地减少了narrow-phase的调用次数。

通常情况下你不会跟broad-phase直接打交道,Box2D内部会创建和维护一个broad-phase,同时,b2BroadPhase是为Box2D模拟循环而设计的,所以它可能不适合在其他情形中被使用。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Box2D v2.3.0 用户指南(第四章) 的相关文章

  • 如何恢复消耗品应用内购买?

    我正在开发一款 iOS 游戏 用户可以通过应用内消耗品购买一定数量的内部货币 比如 1000 金币 如果用户想将余额从一台设备转移到另一台设备 如何恢复消耗品购买 在苹果的文档中 它说我们必须使用我们自己的服务器 但是如何获取用户的Appl
  • iOS:提高图像绘制速度

    我有一系列想要制作动画的图像 UIImageView支持一些基本的动画 但不足以满足我的需求 我的第一个方法是使用UIImageView并设置image当图像属性 这太慢了 速度慢的原因是图像的绘制 这让我感到惊讶 我以为瓶颈会加载图像 我
  • 我怎样才能勾勒出文本字体?

    我想在边框 轮廓 中显示另一种颜色的文本 我正在尝试使用在 MapOverlayView 中显示文本 text drawAtPoint CGPointMake 0 30 withFont UIFont fontWithName Helvet
  • UICollectionView 拖放文件夹创建

    我正在使用 UICollectionView 创建 iOS 画廊应用程序 我希望用户能够拖放图像来重新排序图库并创建文件夹 类似于 iPhone 上的主屏幕 我发现了以下内容tutorial http nshint io blog 2015
  • 频繁绘制 CGPath 时的性能

    我正在开发一个将数据可视化为折线图的 iOS 应用程序 该图被绘制为CGPath在全屏自定义中UIView最多包含 320 个数据点 数据经常更新 图表需要相应地重新绘制 刷新率为 10 秒就很好了 到目前为止很容易 然而 我的方法似乎需要
  • NVActivityIndi​​catorView 仅适用于特定视图

    我正在使用这个库https github com ninjaprox NVActivityIndi catorView https github com ninjaprox NVActivityIndicatorView用于显示加载指示器
  • WhatsApp 显示警告“此项目无法共享。请选择其他项目。”对于 iOS 应用程序。

    我正在开发一个 iOS 应用程序 在该应用程序中 我有社交共享功能 并且社交共享功能使用深度链接来共享 URL 该网址共享对于所有应用程序都运行良好 除了WhatsApp 它会显示一个警报弹出窗口 此项目无法共享 请选择其他项目 以下是我的
  • Swift 中的 UIAlert 自动消失?

    我有以下代码 Creates Alerts on screen for user func notifyUser title String message String gt Void let alert UIAlertController
  • 苹果推送通知在生产中不起作用

    我们完全陷入困境 请帮忙 我和我的团队制作了一个 iPhone 应用程序 这是我们第一次在 iOS 上尝试 一切都很好 直到我们提交应用程序并在应用程序商店上可用为止 推送通知服务无法正常工作 我在网上搜索并尝试根据人们的建议仔细检查我们的
  • 在 swift3 中结合平移、alpha 和缩放动画

    我是 iOS Swift 开发的新手 我尝试将三个参数组合在一个动画中 但没有成功 我认为解决方案就在这里 Apple Dev Core 动画编程指南 https developer apple com library content do
  • Xcode 存档上传失败并出现错误

    我正在尝试从 xCode 将新版本上传到 iTunesConnect 但每次我都会遇到此问题 问题是什么 我该如何解决这个问题 最近 我开始在上传过程中遇到问题 Xcode 经常卡住 最终会因您看到的第二个错误而失败 受够了一段时间后 我转
  • 仅将 UIImage 移动到另一个 UIImage 内部

    I have an UIImage which is shown in an UIImageView I also have another image in an UIImageView which lays above the firs
  • 在 Xcode 5.1 中构建时,“您必须提供 5.5 英寸 Retina 显示屏的屏幕截图,因为您的应用程序二进制文件支持 5.5 英寸 Retina 显示屏”

    我更新了一个旧应用程序并修复了一些小错误 该应用程序是使用 Xcode 5 1 编译的 无法使用资产目录或添加 iPhone 6 和 6 Plus 图像 但当我尝试提交它进行审查时 我仍然收到此错误 您必须提供 4 7 英寸 Retina
  • 在 iOS5 中使用 UISegmentedControl 切换 ViewController

    我正在尝试一些非常简单的事情 但不知何故我无法让它发挥作用 我尝试做的就是使用 UISegmentedControl 在 2 个视图控制器之间切换 就像您可以在 App Store 应用程序的 突出显示 选项卡中看到的那样 我正在使用 iO
  • 我可以更改键盘方向吗?

    例如我用这段代码关闭自动旋转 BOOL shouldAutorotateToInterfaceOrientation UIInterfaceOrientation interfaceOrientation return NO BOOL sh
  • 使用 iPhone 摄像头检测心率 [重复]

    这个问题在这里已经有答案了 可能的重复 使用摄像头检测心率 https stackoverflow com questions 9274027 detecting heart rate using the camera 我正在研究 iOS
  • 将子视图控制器的视图添加到父视图控制器的子视图

    我想添加一个表视图控制器作为容器视图控制器的子视图控制器 如下所示 根据苹果公司的查看控制器编程指南 http developer apple com library ios featuredarticles ViewControllerP
  • Swift 闭包作为 AnyObject

    我尝试使用这个方法 class addMethod 在 Obj c 中使用如下 class addMethod self class selector eventHandler imp implementationWithBlock han
  • CBPeripheral 名称有时为 null

    我正在开发一个应用程序来与蓝牙 LE 外围设备进行通信 我目前正在测试的外围设备是其中之一these http www ti com tool cc2540dk mini 有趣的是 有时当我发现它时 我会得到它的正确名称 SimpleBLE
  • 是什么导致了这个 iPhone 崩溃日志?

    我有点卡住了 需要解决这个问题 因为我的一个应用程序出现了随机崩溃 而这些崩溃并不总是能够重现 这是崩溃日志之一 Incident Identifier 59865612 9F00 44EA 9474 2BF607AD662E CrashR

随机推荐

  • 挂载VMware esxi服务器文件夹到本地ubuntu

    概述 开发安卓项目 需要在公司服务器搭建的环境 VMware esxi 上编译代码 可以将服务器上的文件挂载到本地 在本地编辑好代码后再去服务器上编译 登录服务器 使用ssh user host方式登录 例如ssh rk3566 192 1
  • 深入理解Solidity——独立汇编

    独立汇编 Standalone Assembly 上面介绍的在Solidity中嵌入的内联汇编语言也可以单独使用 实际上 它是被计划用来作为编译器的一种中间语言 在这个目的下 它尝试达到下述的目标 使用它编写的代码要可读 即使代码是从Sol
  • 图像处理(1) : 图像增强

    图像增强就是指通过某种图像处理方法对退化的某些图像特征 如边缘 轮廓 对比度等进行处理 以改善图像的视觉效果 提高图像的清晰度 或是突出图像中的某些 有用 压缩其他 无用 信息 将图像转换为更适合人或计算机分析处理的形式 图像增强可以分为两
  • Apache Beam适时有状态计算

    在先前的Apache Beam中的有状态计算中 介绍了Apache Beam中有状态计算的基础知识 重点介绍了对每个元素的处理中添加的状态特性 所谓的适时处理 是有状态计算的补充 是通过设置定时器来 在将来某个时间点上的 有状态的 进行回调
  • 编写一个Vue插件,上传NPM官网开源使用

    插件开发及上传NPM流程 完成组件封装 组件完成统一封装成插件 插件入口文件配置 src main js 中引入口文件 安装插件 配置 package json 文件 npm run lib 打包 umd min js 配置到 packag
  • JavaFX与后台交互

    目前JavaFX相关的资料都是基本语法 以及界面相关 而JavaFX面向的是RIA RIA就肯定需要和后台交互 个人研究了一下 遇到了不少问题 共享给大家 D 首先先看看JavaFX的api 一眼就能看到javafx io http包 包里
  • unity踩坑日记

    花费了一天时间一直在找bug unity打包出来的程序 我勾选了调试模式 因为的确在调试 关闭时就会停止工作 因为涉及到线程一直怀疑自己写退出时候关闭线程的有问题 但是看来看去没找到问题 就去看错误日志 Mono path 0 E Proj
  • 服务器双机热备系统,双机热备

    1 集群技术 在了解双机热备之前 我们先了解什么是集群技术 集群 Cluster 技术是指一组相互独立的计算机 利用高速通信网络组成一个计算机系统 每个群集节点 即集群中的每台计算机 都是运行其自己进程的一个独立服务器 这些进程可以彼此通信
  • Keil 5使用ST-LINK调试STM32程序

    1 下载并安装STM32 ST LINK Utility 含有驱动 2 启动STM32 ST LINK Utility 点击菜单 ST LINK Firmware 更新固件 3 打开Keil工程 设置Debug 4 开始调试
  • C语言的可变参数

    C语言可变参数原理与使用 1 原理与实现 我们定义C语言的几个宏定义来表达这个想法 使用这几个宏定义来实现可变参数函数 2 调用库函数实现 3 可变参函数的封装 1 原理与实现 C语言可变参数 void func char fmt C语言的
  • 《C#入门到精通》学习笔记 -- Console类

    第1章 知识点扩展 1 Main必须是静态 static 方法 指定了程序的唯一入口 2 Console类是内建类 通过其方法 可以在屏幕上显示消息或者从键盘获取输入 表示控制台应用程序的标准输入流 输出流和错误流 Console类继承于S
  • 网络安全毕业设计选题推荐

    0 简介 毕业季马上就要开始了 不少同学询问学长网安专业选题以及开题相关的问题 今天跟大家分享信息安全毕设选题 最新的信息安全 网络安全 专业毕设选题 难度适中 适合作为毕业设计 大家参考 学长整理的题目标准 相对容易 工作量达标 题目新颖
  • ue4 unreal NDisplay插件 简易使用 三折幕 详细...

    仅支持4 27版本 NDisplay文档 https docs unrealengine com 4 27 en US WorkingWithMedia IntegratingMedia nDisplay Overview Switchbo
  • 2020-04-09

    每日书单 每日书单 1 There is only one time in a person s life when he can make a difference That is the moment 2 Can coral be ke
  • Tracy vue3 小笔记 2 - 和 Vue 2 的区别汇总

    1 可以有多个根元素 2 子传父的 emit 多了一步在default 里预定义
  • 什么是java句柄_JAVA中的术语:句柄是啥意思

    句柄的本质 一个唯一的整数 作为对象的身份id 区分不同的对象 和同类中的不同实例 程序可以通过句柄访问对象的部分信息 句柄不代表对象的内存地址 句柄和指针的区别 程序不能通过句柄直接阅读文件中的信息 指针是可以的 从所起的作用这点来说 句
  • IDEA整合Tomcat服务器(IDEA没有Application Server选项)

    IDEA整合Tomcat服务器 IDEA没有Application Server选项 我使用的IDEA创建Java Enterprise的界面如下 没有Application Server选项 不要慌 在Settings中设置Applica
  • LOAM误差函数、代价函数的雅克比矩阵详细推导,点到线和点到面误差函数求导

    LOAM误差函数的导数详细推导 前言 LOAM对于激光SLAM的发展起到了举足轻重的作用 他提出了点到线和点到面的误差函数 通过优化的方法 得到了非常不错的激光里程计效果 我猜测作者Zhang Ji很可能是从点到线和点到面的ICP算法中找到
  • HTML入门学习笔记

    我是目录 1 标题 段落标签 2 文本格式化标签 3 布局标签 div span 4 图像标签 5 相对路径 绝对路径 6 链接标签 锚点标签 7 表格标签 显示数据 8 列表标签 布局页面 9 表单标签 为了收集用户信息 1 标题 段落标
  • Box2D v2.3.0 用户指南(第四章)

    第四章 碰撞模块 Collision Module 4 1简介 碰撞模块包含形状 shape 以及操作它们的函数 此外 碰撞模块还包括dynamictree和broad phase来加快大型系统的碰撞处理速度 碰撞模块被设计为可独立于动态系