技术标签: 源码阅读 物理引擎 Box2D-Lite Box2D Box2D-Lite源码阅读
这次来看step函数。
step函数里看起来如下的样子,当然我们只关注一块。
void World::Step(float dt)
{
float inv_dt = dt > 0.0f ? 1.0f / dt : 0.0f;
// 碰撞检测
BroadPhase();
...
}
BroadPhase函数是碰撞碰撞检测函数。具体讲解在代码注释
void World::BroadPhase()
{
//这是一个O(n^2)的循环
for (int i = 0; i < (int)bodies.size(); ++i)
{
//获取一个物体
Body* bi = bodies[i];
for (int j = i + 1; j < (int)bodies.size(); ++j)
{
//获取第二个物体
Body* bj = bodies[j];
//如果两个物体的质量倒数的0,就是两个质量无穷大的物体,不进行碰撞检测了
if (bi->invMass == 0.0f && bj->invMass == 0.0f)
continue;
//这里是创建一个值(val)和一个键(key)
//值中主要存储两个物体的指针和两个物体的碰撞信息
Arbiter newArb(bi, bj);
//键中存放的是两个物体的指针,以便用于哈希表查找的键
//而且为了避免(bi,bj),(bj,bi)不同,构造key的时候将指针值较小的放在前面
ArbiterKey key(bi, bj);
//arbiters里面主要存放两个物体的碰撞信息(存入哈希表中),
//arbiters是一个map,键是ArbiterKey,值是Arbiter
if (newArb.numContacts > 0)//当两个物体bi,bj有碰撞产生时
{
//这里先获取哈希表查找(bi,bj)键后的结果
ArbIter iter = arbiters.find(key);
if (iter == arbiters.end())//如果没找到对应的两个物体已有的碰撞
{
arbiters.insert(ArbPair(key, newArb));//将两个物体新的碰撞信息加入
}
else//如果找到对应的键
{
//更新键中的碰撞结果
iter->second.Update(newArb.contacts, newArb.numContacts);
}
}
else//如果两个物体没有碰撞,则删除哈希表中已有的记录
{
arbiters.erase(key);
}
}
}
}
ArbiterKey就是如下的一个小结构体。
struct ArbiterKey
{
ArbiterKey(Body* b1, Body* b2)
{
//永远让指针值小的在前
if (b1 < b2)
{
body1 = b1; body2 = b2;
}
else
{
body1 = b2; body2 = b1;
}
}
Body* body1;//物体1指针
Body* body2;//物体2指针
};
Arbiter中我有重大发现。其构造函数里有碰撞检测调用过程。
struct Arbiter
{
enum {MAX_POINTS = 2};
Arbiter(Body* b1, Body* b2);//构造函数里有碰撞检测过程
...
Body* body1;//物体1指针
Body* body2;//物体2指针
...
};
走进Arbiter的构造函数。
Arbiter::Arbiter(Body* b1, Body* b2)
{
//指针值较小的存储在body1中,和键中的对应上
//个人觉得这个类完全可以继承ArbiterKey,然后生成键和值的时候就不用
//分别构造两次了,只构造一次就能同时生成基类的键和子类值,body1和body2还可以复用
if (b1 < b2)
{
body1 = b1;
body2 = b2;
}
else
{
body1 = b2;
body2 = b1;
}
//碰撞检测函数,会返回碰撞点个数,contacts进去的指针,最后会获取具体碰撞点的信息
numContacts = Collide(contacts, body1, body2);
//两个物体之前的摩擦系数计算
friction = sqrtf(body1->friction * body2->friction);
}
文章浏览阅读6.8k次,点赞43次,收藏92次。深度学习的定义及原理深度学习是一种基于神经网络、具有多个隐藏层来提取高级抽象特征进行模式识别和决策的机器学习技术。其核心思想与人脑神经元相似,通过逐层的计算和学习,将输入数据转化为具有更高级别的表示,从而实现对复杂数据结构的建模和分析。深度学习中最重要的思想是构建可训练的人工神经网络模型。这些模型是由数十甚至数百个神经元层组成的架构,其中每个层都执行着不同的计算和激活函数以处理和传递信息。传递信号的过程被称为前向传播,相应地,在误差信号返向更新参数的过程被称为反向传播。深度学习的关键特征。_深度学习
文章浏览阅读724次。经理人必看的10个管理网站时间:2005年2月21日9:47 阅读数: 管理这玩艺远远看着如同象牙塔中的佛牙舍利,可观而不可玩。其实身在其中无非就是一张窗户纸,没有什么大不了的……… 管理这玩艺远远看着如同象牙塔中的佛牙舍利,可观而不可玩。其实身在其中无非就是一张窗户纸,没有什么大不了的。网络的发展,就是让我们在充分的分享信息资源的同时,通过基于我们的知识结构的合理性分析,使我们_经理在用什么网站,
文章浏览阅读1.5k次,点赞20次,收藏20次。cpp在vsCode中的编译运行与调试_vscode 编译cpp
文章浏览阅读1.2k次。文中统一用 n 表示机器字长原码无符号数可表示范围:0 —— 2n-1 (即全0到全1)有符号数用机器字长第一位表示符号位,剩下的表示数值位,假设机器字长为8位(下同),可以表示为:+8:[x]原 = 0000 1000-8:[x]原 =1000 1000红色标识符号位,下同整数可表示的范围:-(2n-1) —— 2n-1+0.75:[x]原 = 0110 0000-0.75:[x]原 = 1110 0000小数可表示的范围:-(1-2-n)—— 1-2-n(关于原点对称)_字长n位一个有符号数。表示的范围。
文章浏览阅读982次。针对大对象或者长生命周期对象导致的FGC,可通过jmap-histo命令并结合dump堆内存文件作进一步分析,需要先定位到可疑对象。内存泄漏频繁创建了大量对象,但是无法被回收(比如IO对象使用完后未调用close方法释放资源),先引发FGC,最后导致OOM。了解JVM的参数设置,包括堆空间各个区域的大小设置,新生代和老年代分别采用了哪些垃圾收集器,然后分析JVM参数设置是否合理。JVM参数设置问题包括总内存大小、新生代和老年代的大小、Eden区和S区的大小、元空间大小、垃圾回收算法等等。..._fgc
文章浏览阅读160次。这份报告总结了 InfoQ Java 编辑团队对目前 Java 领域技术采用和新兴趋势的看法。我们关注 Java 及相关的语言(如 Kotlin 和 Scala)、Java 虚拟机(JVM),以及基于 Java 的框架和工具。我们讨论了 Core Java 的趋势,比如新版本 Java 的采用,以及和等框架的演进。这份报告有两个主要目标:帮助技术领导者做出中长期的技术投资决策。帮助个体开发者选择在哪些领域投入宝贵的时间和资源去学习和发展技能。这是我们发布的第五份 Java 趋势报告。
文章浏览阅读836次。问题原因Cannot set headers after they are sent to the client翻译为:发送到客户端后无法设置标头我已经数据处理完了,为啥我还要设置头部呢?,我也没有去重新设置头部…解决步骤在最后send函数前添加await关键词(等待),就没有出现报错register= async (req,res,next)=>{await Login.register(xxx).then( async response=>{ await res.sen_node里面报错can't set header after they are sent
文章浏览阅读974次,点赞24次,收藏21次。如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路,但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢 (O(n)O(logn)不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。于是乎,布隆过滤器便应运而生了。_布隆过滤器java实现
文章浏览阅读264次。量子位智库 发自 凹非寺量子位 | 公众号 QbitAI在前沿科技这个充满创新活力的领域中,量子位智库密切关注着哪些新技术和突破性进展将主导未来科技潮流。区别于其他智库和研究机构,量子位智库基于量子位长期以来对AI及其他前沿科技的追踪报道,积累了数年对前沿科技的深入洞察。《年度十大前沿科技趋势》系列报告准确把握科技前沿趋势、深入了解技术突破的本质、串联技术突破与产业风口、站在前沿科技产学研交汇地带..._近几年的新技术新科技
文章浏览阅读7.2k次,点赞8次,收藏13次。用DIO的代码做一些讲解,帮助大家更好的理解代码_阅读mcal代码
文章浏览阅读4.6k次。Flowplayer支持播放flv、swf等流媒体以及图片文件,能够非常流畅的播放视频文件,支持自定义配置和扩展。1、加载flowplayer.js在要播放视频的页面的head之间加入flowplayer.js。 您可以到flowplyer官网上下载最新版本:http://flowplayer.org/download/index.html2、XHTML在需要加入播放器的_flowplayer 在线
文章浏览阅读3.1k次。一般我们在浏览器输入一个网址访问网站都是GET请求;再FORM表单中,可以通过设置Method指定提交方式为GET或者POST提交方式,默认为GET提交方式。HTTP定义了与服务器交互的不同方法,其中最基本的四种:GET,POST,PUT,DELETE,HEAD,其中GET和HEAD被称为安全方法,因为使用GET和HEAD的HTTP请求不会产生什么动作。不会产生动作意味着GET和HEAD的HTTP请求不会在服务器上产生任何结果。但是安全方法并不是什么动作都不产生,这里的安全方法仅仅指不会修改信息。_http中get和post的区别