第十章 世界类

瑞芯微RK3576上手实测:8nm新U配6TOPS NPU,做AIoT项目选它还是RK3588/RK3568? 本文深度评测瑞芯微RK3576芯片在中高端AIoT项目中的表现,对比RK3588和RK3568的性能差异。RK3576采用8nm工艺,配备6TOPS NPU,在解码能力、AI推理效率和功耗控制方面表现均衡,是中端项目的黄金选择。实测数据显示其在多路视频解码和AI加速性能上优势明显,特别适合智能摄像头和工业HMI设备。 阅读详情

声明:此文章翻译自Box2D v2.2.0用户手册,仅供学习参考。

  • 关于(About)

b2World类包含了物体和连接器。它管理了模拟相关的所有方面并且允许异步需求(像AABB需求和光线投射(ray-casts))。Box2D中的大部分交互将会使用b2World对象。

  • 创建并销毁一个世界(Creatng and Destroying a World)

创建一个世界相当简单。你只要提供一个重力向量和一个是否允许物体有睡眠状态的布尔值(Boolean)。通常你会使用new和delete关键字来创建和销毁一个世界。

1
2
3
b2World* myWorld = new b2World(gravity, doSleep);
...do stuff...
delete myWorld;
  • 使用世界(Using a World)

世界类包含了创建和销毁物体和连接器的方法工厂。稍后会对这些工厂进行介绍。现在给大家介绍一下与b2World其它方面的交互。

  • 模拟(Simulation)

世界类用来驱动模拟。你指定了一个时间步长,速度以及位置迭代次数。比如说:

1
2
3
4
float32 timeStep = 1.0f/60.0f;
int32 velocityIterations = 10;
int32 positionIterations = 8;
myWorld->Step(timeStep, velocityIterations, positionIterations);

执行这次时间步长之后你可以测试一下物体和连接器相关的信息。更多的你可能将会看到物体的移动,这样你就可以不断的更新和重绘它们。你可以在游戏循环的任何位置来执行。比如说,如果你想在某一帧获取新创建物体的碰撞结果,那么你必须在执行此时间步长之前来创建物体。

就像在HelloWorld章节中所提到的,上面的时间步长你应该使用固定值。在低帧率的场景中通过使用一个大的时间步长可以改进性能。但是一般来说你应该使用一个不能大于1/30秒的时间步长。一个1/60秒的时间步长可以产生一个高质量的模拟。

迭代次数控制了约束求解器扫描世界中所有接触和连接器的次数。更多的迭代总是能够产生更高质量的模拟。但是不要为一个小的时间步长设置一个大的迭代数。60Hz搭配10次迭代要远好于30Hz搭配20次迭代。

下一步,你应该清空所有施加在物体上的力。可以使用b2World::ClearForces方法来完成。这可以让你在同一个力场完成多个分步。

1
myWorld->ClearForces();
  • 探索世界(Exploring the World)

世界包括物体,接触以及连接器。你可以获取世界中的物体,接触以及连接器链表并对它们进行遍历。举例来说,下面这段代码唤醒了世界中的所有物体:

1
2
3
4
for(b2Body* b = myWorld->GetBodyList(); b; b = b->GetNext())
{
    b->SetAwake(true);
}

不幸的是真实的程序可能会更复杂。比如说,下面的代码就中断了。

1
2
3
4
5
6
7
8
for(b2Body* b = myWorld->GetBodyList(); b; b = b->GetNext())
{
    GameActor*  myActor = (GameActor*)b->GetUserData();
    if(myActor->IsDead())
    {
        myWorld->DestroyBody(b); //ERROR: now GetNext returns garbage.
    }
}

在碰到一个已经销毁的物体之前一切运行良好。一旦遇到一个被销毁的物体,下一个指针就会是一个错误的指针。所以调用b2Body::GetNext()方法就会返回一个错误指针。解决办法是在获取下一个指针之前先对其进行拷贝操作。

1
2
3
4
5
6
7
8
9
10
11
b2Body* node = myWorld->GetBodyList();
while(node)
{
    b2Body* b = node;
    node = node->GetNext();
    GameActor* myActor = (GameActor*)b->GetUserData();
    if(myActor->IsDead())
    {
        myWorld->DestroyBody(b);
    }
}

这样就可以安全销毁当前的物体。即便如此你也可能会调用一个游戏方法产生销毁多个物体。这种情况你需要非常小心。这是对特定情况下的解决方案,但是为了方便起见,我会向你展示一个解决此问题的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
b2Body* node = myWorld->GetBodyList();
while(node)
{
    b2Body* b = node;
    node = node->GetNext();
    GameActor* myActor = (GameActor*)b->GetUserData();
    if(myActor->IsDead())
    {
        bool otherBodiesDstroyed = GameCrazyBodyDestroyer(b);
        if(otherBodiesDestroyed)
        {
            node = myWorld->GetBodyList();
        }
    }
}

这样做很明显,GameCrazyBodyDestroyer必须对于哪些物体销毁要非常的诚实。

  • AABB查询(AABB Queries)

有时候你需要在一个区域中决定所有的形状。b2World类提供了一个log(N)的快速算法来使用broad-phase数据结构。在世界坐标系内提供了一个AABB(axis-aligned bounding box),之后实现了b2QueryCallback回调。世界将会调用你的类,通过定制器遍历与查询AABB以确定是否有重叠的AABB。返回true继续查询,否则返回false。例如,接下来的代码找出与一个特定AABB有潜在交互的所有定制器并唤醒所有关联的物体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyQueryCallback : public b2QueryCallback
{
    public:
        bool ReportFixture(b2Fixture* fixture)
        {
            b2Body*  body = fixture->GetBody();
            body->WakeUp();
            // Return true to continue the query.
            return true;
        }
};
...
MyQueryCallback callback;
b2AABB aabb;
aabb.lowerBound.Set(-1.0f, -1.0f);
aabb.upperBound.Set(1.0f, 1.0f);
myWorld->Query(&callback, aabb);

关于回调你不能假定回调的顺序。

  • 光线投射(Ray Casts)

你可以使用光线投射来做瞄准线检查(line-of-sight checks),火枪,等等。你可以通过实现一个回调类来实现光线投射的始点和终点。世界类会调用你的类访问射线中碰到的每一个定制器。回调中提供了定制器,交点,单位法向量(unit normal vector),以及沿着射线通过的的分数距离(fractional distance)。关于回调的次序你不能做任何假设。

你可以通过返回的分数来控制光线投射的延伸。返回分数(fraction)为零代表光线投射应该终止。返回分数(fraction)为一,光线好像没有发生碰撞一样一直延伸。如果从参数列表中返回分数,光线将被截断在当前位置和交点之间。所以你可以投射任何形状,甚至是所有形状,或者根据返回的适当分数投射最近的形状。

你可以返回-1分数值来以此过滤定制器。那么光线投射将会继续延伸就像定制器不存在一样。

这里是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//This class captures the closest hit shape
class MyRayCastCallback : public b2RayCastback
{
    public:
        MyRayCastCallback()
        {
            m_fixture = NULL;
        }
        float32 ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction)
        {
            m_fixture = fixture;
            m_point = point;
            m_normal = normal;
            m_fraction = fraction;
            return fraction;
        }
        b2Fixture* m_fixture;
        b2Vec2 m_point;
        b2Vec2 m_normal;
        float32  m_fraction;
};
MyRayCastCallback callback;
b2Vec2 point1(-1.0f, 0.0f);
b2Vec2 point2(3.0f, 1.0f);
myWorld->RayCast(&callback, point1, point2);

警告 
由于误差的原因,在静态环境里,光线投射可能会潜在穿过形状之间的小的裂缝。如果这一点在你应用中不能接受,那么就请略微放大你的形状。

1
2
3
4
void SetLinearVelocity(const b2Vec2& v);
b2Vec2 GetLinearVelocity() const;
void SetAngularVelocity(float32 omega);
float32 GetAngularVelocity() const;
  • 力和冲量(Forces and Impulses)

你可以对一个物体作用力,扭矩和冲量。当你作用一个力或者一个冲量的时候,就在世界坐标下的提供了一个负载点。通常的结果会有一个关于质心的扭矩。

1
2
3
4
void ApplyForce(const b2Vec2& force, const b2Vec2& point);
void ApplyTorque(float32 torque);
void ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point);
void ApplyAngularImpulse(float32 impulse);

应用力,扭矩或者冲量唤醒物体。有时候这是不可取的。举例来说,你可能会作用一个恒定的力同时允许物体进入睡眠状态以此来提高性能。在这个场景中你可以使用下面代码。

1
2
3
4
if(myBody->IsAwake() == true)
{
    myBody->ApplyForce(myForce, myPoint);
}
  • 坐标变换(Coordinate Transformations)

物体类(body class)有一些辅助方法来帮助你对坐标和向量在局部和世界坐标系之间变换。如果你不清楚这些概念,请参阅“Essential Mathematics for Games and Interactive Applications“由Jim Van Verth和Lars Bishop合著。这些方法很高效(当内联使用时(when inlined))。

1
2
3
4
b2Vec2 GetWorldPoint(const b2Vec2& localPoint);
b2Vec2 GetWorldVector(const b2Vec2& localVector);
b2Vec2 GetLocalPoint(const b2Vec2& worldPoint);
b2Vec2 GetLocalVector(const b2Vec2& worldVector);
  • 链表(Lists)

你可以遍历一个物体的定制器。如果你想访问定制器的用户数据(user data)这个很有用。

1
2
3
4
5
for(b2Fixture* f = body->GetFixtureList(); f; f = f ->GetNext())
{
    MyFixtureData*  data = (MyFixtureData*)f->GetUserData();
    ...do something with data...
}

类似的你可以遍历物体的连接器链表。

物体也提供了一个接触相关的链表。你可以获取当前接触的链表。不过要小心,因为接触链表也许并不包括所有接触,因为可能并不包含前一个时间步长存在的接触。

FreeCAD源码分析:Sketcher模块 Sketcher模块基于Part模块功能实现了特征编辑(Feature Editing)建模的功能。这类参数化建模系统主要包括几何表示、约束求解器等两大组成部分。 阅读详情

相关推荐

专治疑难系列 - 解决打印机凭证冲突问题

一、问题描述 二、解决方法 三、问题已解决

Passerby_Wang的博客 2万+

cocos2dx物理引擎和碰撞检测(二)

这篇文章来讲如何创建物理世界

u014096244的专栏 900

docker安装fastdfs+nginx配置

docker安装fastdfs+nginx,实现图片或文件的上传与下载

weixin_47325126的博客 2193

Box2D v2.1.0用户手册翻译 - 第10章 世界(World Class)

内容很多摘自 Aman JIANG(江超宇)翻译的Box2D v2.0.1 用户手册 第10章 世界(World Class) 关于 b2World类包含物体和关节。它管理着模拟的方方面面,并允许异步查询(就像AABB查询和光线投射)。 你与Box2D的大部分交互都将通过 b2World 对象来完成。 创建和摧毁world 创建一个world

complex_ok的专栏 6658

STM32+OpenCV云台PID调参实战:从震荡到丝滑跟踪的进阶之路

本文详细介绍了基于STM32和OpenCV的跟踪云台PID调参实战经验。从硬件搭建、PID控制原理到调参技巧,系统讲解了如何通过调整比例、积分和微分参数解决系统震荡问题,实现从震荡到丝滑跟踪的进阶过程,特别适合电赛和嵌入式视觉控制开发者参考。

tgb3456789的博客 717

anaconda的conda国内加速镜像源(pytorch 快速安装)

最近清华源不太好使了,所以推荐中科大镜像源,如下 1.还原原始通道 conda config --remove-key channels 2.

qq_41719643的博客 2万+

BOX2D 第十章 世界类

第十章 世界类 Dec 2nd, 2012| Comments 声明:此文章翻译自Box2D v2.2.0用户手册,仅供学习参考。 关于(About) b2World类包含了物体和连接器。它管理了模拟相关的所有方面并且允许异步需求(像AABB需求和光线投射(ray-casts))。Box2D中的大部分交互将会使用b2World对象。 创建并销毁一个世界(Crea

u010000785的专栏 516

C语言手写HTTPD网站服务器

零基础手写C语言http网站服务器,快速入门C/C++后端开发、服务器开发。

程序员Rock的博客 1万+

cocos2dx-3.0 中的物理引擎Box2D使用(二)

~~~~我的生活,我的点点滴滴!!

破茧 1433

《QMT量化实战系列》支持自定义筛选与排序的多因子策略,实测年化收益超100% (1)

公众号推出《QMT量化实战》系列,通过多维度、多策略、多场景讲解QMT量化平台应用,每期附代码解读。本期复现《支持自定义筛选与排序的多因子策略》,策略包含三大核心模块:1. 通过Tushare获取30+财务因子数据;2. 提供灵活筛选机制(支持排除ST股、次新股及特定板块);3. 创新性多因子加权排序系统(支持自定义因子权重组合)。交易逻辑包含动态调仓机制,当持仓标的排名低于阈值时触发卖出。该策略具有高度可配置性,适合不同风险偏好的投资者。(149字)

qq_46262068的博客 1732

基于PyTorch的BP神经网络PID控制器动态调参实战

本文详细介绍了基于PyTorch的BP神经网络PID控制器动态调参实战,结合BP神经网络的自适应能力和PID控制算法的经典优势,实现工业控制中的高效参数调整。通过PyTorch实现BP-PID融合架构,包括网络设计、损失函数优化及动态调参技巧,显著提升控制性能,适用于温度控制、电机控制等场景。

weixin_29094775的博客 522

box2d 中文api world类

构造函数与析构函数 b2World::b2World ( const b2Vec2 & gravity,  bool doSleep  )  构造一个世界对象。 参数: gravity 世界重力向量。 doSleep 物体是否可休眠。通过不模拟休眠物体来提高引擎的效率。  b2World::~b2World ( )  摧毁世界。所有的物理学实体被摧毁,而且所有的

qq55008307的专栏 740

【虚拟仿真】Unity3D中实现对大疆无人机遥控器手柄按键响应

最近项目中需要用到大疆无人机遥控器对程序中无人机进行控制,遥控器是下图这一款:博主发现接入手柄这块的可以参考的内容非常少,对于大疆遥控器的控制更是没有。博主经过一番研究,终于理通了这块的遥控器摇杆数据的控制。并且将解决思路分享出来,希望对大家有所帮助。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 2819

我的世界Java版1.21.4的Fabric模组开发教程(十)更多物品交互行为

本教程讲解如何为Minecraft模组创建具有特殊交互效果的自定义物品。

Kim的博客 2056

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

第十章第三题(MyInteger类)(MyInteger class)

第十章第三题(MyInteger类)(MyInteger class) 10.3(MyInteger类) 10.3(MyInteger class) 参考代码: package chapter10; public class Code_03 { public static void main(String[] args) { MyInteger myInteger = new MyInteger(10); System.out.println("Test get

jxh1025_的博客 2403

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

第十章第四题(MyPoint类)(MyPoint class)

第十章第四题(MyPoint类)(MyPoint class) 10.4(MyPoint类) 10.4(MyPoint class) 参考代码: package chapter10; public class Code_04 { public static void main(String[] args) { MyPoint myPoint1 = new MyPoint(); MyPoint myPoint2 = new MyPoint(10,30.5);

jxh1025_的博客 2348

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

第十章第二题(BMI类)(BMI class)

第十章第二题(BMI类)(BMI class) 10.2(BMI类)将下面的新构造方法加入BMI类中: public BMI(String name,int age,double weight,double feet,double inches) 10.2(BMI class)Add the following new construction method to the BMI class: public BMI(String name,int age,double weight,double feet

jxh1025_的博客 3049

第十章 类

class 类名类属性名=属性值...def 函数名(self)self.实例属性名=属性值......如果一个类实现了__iter__()方法,且该方法返回迭代器,那么该类的实例就是可迭代对象。使用iter()函数能够获取可迭代对象的迭代器。如果没有实现方法,但是实现了方法,且该方法的参数是从0开始的索引,那么它的实例也是可迭代的对象。在 Python 中,如果一个类实现了iter() 和next() 这两个特殊方法,那么这个类的实例就可以被视为一个迭代器。

2301_81197800的博客 688

【经典书籍】《代码整洁之道》第十章“类”精华讲解

一个好的类,应当是高内聚、低耦合、职责单一、封装良好、命名清晰的小型模块,它只关注自己该做的事,不干涉他人,也不让他人随意干涉自己。原书作者“类的设计应当遵循单一职责原则,保持内聚性,控制其可见性,让代码更加模块化、清晰和可维护。“类的大小不重要,重要的是它做了多少事,以及它是怎么组织的。特质说明好处单一职责(SRP)一个类只做一件事,只管一个职责逻辑清晰、职责分明、易维护高内聚类内方法与字段紧密相关,都围绕一个目标模块紧凑、功能专注、易理解低耦合类之间尽量减少依赖,通过接口交互。

chenningpocom的博客 874

C primer plus(第六版) 第十章答案

C primer plus(第六版) 第十章答案 /* First */ #include<stdio.h> #define MONTHS 12 #define YEARS 5 int main(void) { const float rain[YEARS][MONTHS] = { { 4.3, 4.3, 4.3, 3.0, 2.0, 1.2,...

weixin_45638291的博客 4492

数据库系统概论 第十章课后习题(部分)

本文是《数据库系统概论》的第十章(数据库恢复技术)的部分课后习题,题目来源:【2019-2020春学期】数据库作业20:第十章:数据库恢复技术 ????不加目录啦,比较少,直接开始~ ✍我的手写解答: ????注意:已经提交了的需要重做,已经开始但未结束的需要回滚,其他情况不用care~ ✍我的手写解答: ????系统恢复后值的变化只与需要重做的事务(即已经提交了的事务)有关系! 那 这两个习题就完成啦~ 注意一下总结的两个点就行,习题难度较简单,不过学了以后真正地运用了才能记得更牢????

Henry_626的博客 1万+

第十章

第十章 载营魄抱一,能毋离乎?抟(tuán)气致柔,能如婴儿乎?修除玄监,能无疵乎?爱民活国,能毋以智乎?天门启合,能为雌乎?明白四达,能毋以知乎?生之、畜之,生而弗有,长而弗宰也。是谓玄德。 第十章1 吃饭要专心啦|解读经典 各位朋友大家好,今天接着聊《道德经》。我聊了大约两个月的《道德经》了,不知道对大家的启发大不大,我看《道德经》越看越有启发,我觉得这里边都是大的智慧,都是可...

aohuang8877的博客 603

《代码整洁之道》第十章 类

第十章 类概述1. 类的组织2. 类应该短小2.1 单一权责原则(单一原则)2.2 内聚3.为了修改而组织最后的话 概述 到目前为止一直在讨论如何编写良好的代码行和代码块。我们深入研究了函数的恰当构成,以及函数之间如何互相关联。不过,尽管讨论了这么多关于代码语句及由代码语句构成的函数的表达力,除非我们将注意力放到代码组织的更高层面,就始终不能得到整洁的代码。 本章将展开讨论如何编写一个整洁的类 1. 类的组织 遵循标准的Java约定: 类应该从一组变量列表开始。如果有公共静态常量,应该先出现然后是私有静

zhangxiaoxiao9527的博客 471

java语言程序设计基础篇习题_复习题_第十章

java语言程序设计基础篇习题_复习题_第十章10.1 习题如果重新定义程序清单 10-2中的2中的 Loan类,去掉其中的设置方法,这个类是不可改变的吗?10.3 类之间的常用关系是什么?10.4 什么是关联?什么是聚集?什么是组合?10.5 聚集和组合的UML图标识是什么?10.7 描述基本类型的包装类10.9 如何将一个整数转换为一个字符串?如何将一个数值字符串转换为一个整数?如何将一个do...

guijiao1243的博客 8564

【Java基础笔记】第十章 对象与类

目录前言第十章 对象与类8.1 设计对象并使用8.1.1 类的定义8.1.2 获得类的对象8.1.3 使用对象8.1.4 定义类的注意事项8.1.5 成员变量的默认值8.2 对象内存图8.2.1 两个对象的内存图8.2.2 两个变量指向同一个对象的内存图8.3 垃圾回收8.4 构造器8.4.1 构造器的作用8.4.2 构造器的定义格式8.4.3 构造器的分类8.4.4 初始化对象的格式8.5 this关键字8.5.1 this出现在有参数构造器中的用法8.5.2 this出现在成员方法中的方法8.6 封装8

Silence的学习小站 682

abstract类_第十章 类

第十章 类10.1 类概述现实生活中,人就是一个类,但是人只是一个抽象的概念,它指的是所有人。如果我们想找人聊天,此时我们就需要具体的人,比如张三。人是这个类别中的个体,具有一些公共的特征(姓名,性别,年龄)和行为(吃饭,工作,思考和睡觉)。所以,类代笔具有公共属性和行为的对象。 C#中如何定义一个类? 我们在C#中定义一个类很简单,只需要使用class关键字并且按照格式定义即可。具体方法如下所示...

weixin_39722917的博客 82
上一篇: 第九章 接触
下一篇: 第十一章 其它
箭已离弓
博客等级 码龄14年 37粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值