首页| 行业资讯| 企业名录| 周边产品| 数字城市| 增强现实| 工业仿真| 解决方案| 虚拟医疗| 行业仿真| 图形处理| 军事战场
用户登录/注册 ×
资讯首页
行业资讯 >> 学习教程
Unigine2.0教程十二《动态刚体物理碰撞》
时间:2019-10-14    评论:0
    来源:友擎(上海)软件科技有限公司
          参考脚本例子:Sample -> UnigineScript -> PHYSICS

          Unigine 实时物理整合了碰撞检测 (collision detection),断裂 (fracturing),浮力 (buoyancy) ,关节 (joints) 以及其它的外部力来进行真实物理模拟。它使用刚体动力学来计算动态物体。动态物体区别于静态物体如下:

          1)动态物体具有body

          2)动态物体具有shape

          因此动态物体的物理模拟的前提是设置好body和shape。

          本文讲解如何通过Unigine来模拟一个人推箱子的过程,用两种方法(Editor,脚本代码)为箱子加上body和shape。描述如下:

          1)人附着在箱子上,箱子具有物理(可以在代码中加,也可以在编辑器中加),而人会随着箱子的移动而移动(可以使用node Reference,在Editor中完成)

          2)当按下m键时,人会做出推箱子的动作(如果有这个动画的话),此时施加一个力F在箱子上(这个力必须大于摩擦力)。

          在Editor中加body和shape

          1、创建Physics工程


          2、资源文件

          超链接:[ ./Resource/Res_0004];

          下面教程会指导如何创建model.node和model_no_physical.nodel。可以不拷贝这两个文件。

          这里建议工程名设置为Physical,如果你需要使用资源链接里面的.node文件。

          3、创建model.node文件

          2.1 将资源文件people.mesh拷贝至meshes文件夹下

          2.2   在Editor中创建箱子,并改名为box, box的size设置为 (1,1,2)


          修改box的大小可以在下面两个界面完成(不能同时在这两个界面都修改):

          1)创建的时候设置


          推荐使用方法1

          2)创建完成以后进入Node窗口进行设置

 
          2.3   给该箱子添加body


 
          2.4给该箱子添加shape


 
          注:当质量设置为0时,box将处于稳定的状态。

          2.5 创建people.mesh的ObjectStaticMesh,将该node改名为people,设置好方向


          2.6 创建model.node,注意box与people的相对位置关系

 
          参考: [06、Nodes介绍]关于NodeReference的创建

          4、代码如下:

          代码链接:[./Code/code_0001.cpp]
#include <core/unigine.h>
#include <core/scripts/primitives.h>

Model model = NULL;
class Model
{
private:
ObjectMeshDynamic box;
ObjectMeshSkinned  people;
Controller controller;
vec3 force;
int bAddFlag;
NodeReference node_ref;
//嵌套类
class Controller
{
private:
Model model;
public:
Controller(Model m = NULL)
{
model = m;
engine.controls.setStateKey(CONTROLS_STATE_AUX_0, ’m’);//’m’
}
void update(float ifps)
{
//Controller类将按键信息传递给Model
if (engine.controls.getState(CONTROLS_STATE_AUX_0))//当按下’m’时
{
//设置model的加力标识 
model.add_force();
}
else
{
//设置model的不加力标识 
model.remove_force();
}
}
};
public:
Model()
{
//从.node文件中读取所需要的东西
node_ref = new NodeReference("model.node");
Node base = node_ref.getNode();
Node node_box = base.getChild(base.findChild("box"));
box = node_cast(node_box);

Node node_people = node_box.getChild(node_box.findChild("people"));
people = node_cast(node_people);
box.setPosition(vec3(-2, 0, 2.1f));

//force应该大于摩擦力,否则不会动
force = vec3(-5, 0, 0);
bAddFlag = 0;
//初始化controller
controller = new Controller(this);
}
~Model()
{
delete node_ref;
delete controller;
}
void add_force()
{
bAddFlag = 1;
}
void remove_force()
{
bAddFlag = 0;
}
void addForceFlush()//在flush()函数中被调用
{
if (bAddFlag == 1)
{
BodyRigid b = box.getBodyRigid();
b.addForce(force);
}
}
void update(float ifps)
{
controller.update(ifps);
if(bAddFlag == 1)
{
people.setFrame(0, 40*engine.game.getTime());
}
}
int isReverse()
{
vec3 location1 = box.getWorldPosition();
vec3 location2 = people.getWorldPosition();
if(location1.z <= 0.6 || location1.x >=  location2.x)
return 1;
else
return 0;
}
};
int init() {
//照相机初始化
PlayerSpectator camera = new PlayerSpectator();
camera.setPosition(Vec3(20.0f, 0.0f, 15.0f));
camera.setDirection(Vec3(-1.0f, 0.0f, -0.5f));
engine.game.setPlayer(camera);
//参照物初始化
{
{
Object mesh = Unigine::createBox(vec3(40, 0.1, 4));
mesh.setWorldPosition(vec3(0, 20, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
{
Object mesh = Unigine::createBox(vec3(40, 0.1, 4));
mesh.setWorldPosition(vec3(0, -20, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
{
Object mesh = Unigine::createBox(vec3(0.1, 40, 4));
mesh.setWorldPosition(vec3(20, 0, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
{
Object mesh = Unigine::createBox(vec3(0.1, 40, 4));
mesh.setWorldPosition(vec3(-20, 0, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
}
//初始化model
model = new Model();
return 1;
}

int shutdown() {
return 1;
}

int update()
{
//ifps: 得到上一帧的时间, 作为时间参考
float ifps = engine.game.getIFps();
if(model != NULL)
{
model.update(ifps);
if(model.isReverse())//当模型翻转的时候,游戏结束,模型从场景里面删除,人和box从场景中消失
{
delete model;
model = NULL;
}
}
return 1;
}
int flush()
{
//需要在worldscript中的flush()函数中加力
if(model != NULL)
model.addForceFlush();
return 1;
}

          在代码中加body和shape

          1、编辑器操作改动

          和上面的步骤一样(忽略2.2和2.3即可),创建一个Physical工程,在该工程下创建一个model_no_physical.node (对应于上面的model.node)。

          资源超链接:[ ./Resource/Res_0004];

          2、代码改动

          在上面的基础上,我们只需要修改Model类的构造函数( Model()),用代码给box加上shape和body

 
          代码链接:[./Code/code_0002.cpp]
#include <core/unigine.h>
#include <core/scripts/primitives.h>

Model model = NULL;
class Model
{
private:
ObjectMeshDynamic box;
ObjectMeshSkinned  people;
Controller controller;
vec3 force;
int bAddFlag;
NodeReference node_ref;
//嵌套类
class Controller
{
private:
Model model;
public:
Controller(Model m = NULL)
{
model = m;
engine.controls.setStateKey(CONTROLS_STATE_AUX_0, ’m’);//’m’
}
void update(float ifps)
{
//Controller类将按键信息传递给Model
if (engine.controls.getState(CONTROLS_STATE_AUX_0))//当按下’m’时
{
//设置model的加力标识 
model.add_force();
}
else
{
//设置model的不加力标识 
model.remove_force();
}
}
};
public:
Model()
{
//从.node文件中读取所需要的东西
node_ref = new NodeReference("model_no_physical.node");
Node base = node_ref.getNode();
Node node_box = base.getChild(base.findChild("box"));
box = node_cast(node_box);

/*
加class_remove的原因: 当为box设置body后,如果某刻要清除box,那么在清除box之前,会先清除body。
此时如果当前脚本还管理着body的删除,就会发生重复清除body的情况,一个指针被重复删除两遍的后果是Crash.
class_remove就是剥夺当前脚本单独对body的删除权
*/
//为box加body
Body body = class_remove(new BodyRigid(box));
//为box加shape
ShapeBox shape = class_remove(new ShapeBox(body, vec3(1, 1, 2)));//class_remove使用的原因见上。
shape.setMass(1);//质量
shape.setFriction(0.5);//摩擦力
shape.setRestitution(0.5);//恢复系数

Node node_people = node_box.getChild(node_box.findChild("people"));
people = node_cast(node_people);
box.setPosition(vec3(-2, 0, 2.1f));

//force应该大于摩擦力,否则不会动
force = vec3(-5, 0, 0);
bAddFlag = 0;
//初始化controller
controller = new Controller(this);
}
~Model()
{
delete node_ref;
delete controller;
}
void add_force()
{
bAddFlag = 1;
}
void remove_force()
{
bAddFlag = 0;
}
void addForceFlush()//在flush()函数中被调用
{
if (bAddFlag == 1)
{
BodyRigid b = box.getBodyRigid();
b.addForce(force);
}
}
void update(float ifps)
{
controller.update(ifps);
if(bAddFlag == 1)
{
people.setFrame(0, 40*engine.game.getTime());
}
}
int isReverse()
{
vec3 location1 = box.getWorldPosition();
vec3 location2 = people.getWorldPosition();
if(location1.z <= 0.6 || location1.x >=  location2.x)
return 1;
else
return 0;
}
};
int init() {
//照相机初始化
PlayerSpectator camera = new PlayerSpectator();
camera.setPosition(Vec3(20.0f, 0.0f, 15.0f));
camera.setDirection(Vec3(-1.0f, 0.0f, -0.5f));
engine.game.setPlayer(camera);
//参照物初始化
{
{
Object mesh = Unigine::createBox(vec3(40, 0.1, 4));
mesh.setWorldPosition(vec3(0, 20, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
{
Object mesh = Unigine::createBox(vec3(40, 0.1, 4));
mesh.setWorldPosition(vec3(0, -20, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
{
Object mesh = Unigine::createBox(vec3(0.1, 40, 4));
mesh.setWorldPosition(vec3(20, 0, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
{
Object mesh = Unigine::createBox(vec3(0.1, 40, 4));
mesh.setWorldPosition(vec3(-20, 0, 0));
mesh.setMaterial("mesh_base", "*");
mesh.setProperty("surface_base","*");
}
}
//初始化model
model = new Model();
return 1;
}

int shutdown() {
return 1;
}

int update()
{
//ifps: 得到上一帧的时间, 作为时间参考
float ifps = engine.game.getIFps();
if(model != NULL)
{
model.update(ifps);
if(model.isReverse())//当模型翻转的时候,游戏结束,模型从场景里面删除,人和box从场景中消失
{
delete model;
model = NULL;
}
}
return 1;
}
int flush()
{
//需要在worldscript中的flush()函数中加力
if(model != NULL)
model.addForceFlush();
return 1;
}
          关于Unigine引擎

          Unigine引擎是一个具有广泛适用性的虚拟现实开发平台,应用领域包含但不限于工业设计及制造、海事模拟、铁路运输、飞行模拟、车辆模拟、医疗模拟、建筑可视化、城市规划、军事、模拟等等。模拟仿真/虚拟现实行业发展到今天,原本使用的各个引擎也已经到了亟需更新换代的时候,Unigine正是抓住了这个机会,非常迅速的踏入了这个行业。随着中国模拟仿真/虚拟现实行业的迅猛发展,工业制作业、科研、医疗、军事军工、娱乐等等领域都产生了大量的需求,而面对这些需求时,曾经引进的那些引擎已经出现了明显的瓶颈,而Unigine问世正好提供了解决方法。

          针对仿真行业的特殊要求,Unigine拥有很多针对性的功能,并进行了优化,比如高度逼真的图像渲染、精细宏大场景、多通道图像生产、非线性图像校正、边缘融合、支持非对称显示输出、适用于CAVE显示系统、立体画面输出、支持头戴显示设备、支持3D空间定位设备、支持多种工业模型数据格式、支持真实世界地理信息数据、强劲性能和可扩展性、丰富的内容支持等,使其在仿真领域更具专业性。

          了解更多详细信息,敬请访问Unigine官方网站:https://www.unigine.com

          Unigine Demo视频演示:https://i.youku.com/unigine
标签:Unigine
上一篇:可视现实:UNIGINE引擎渲染效果(多图)下一篇:Unigine2.0教程十一《简单的AI:寻路》
网友评论:Unigine2.0教程十二《动态刚体物理碰撞》
留名: 验证码:
最新评论
查看全部评论0
暂无评论
您可能还需要关注一下内容:
·Unigine2.0教程一《初识Unigine》
·Unigine2.0教程二《安装与创建工程》
·Unigine2.0教程三《设置规范化的文件夹》
·Unigine2.0教程四《Editor导入模型》
·Unigine2.0教程五《创建材质(Material)》
·Unigine2.0教程六《Nodes介绍》
·Unigine2.0教程七《为模型加骨骼动画》
·Unigine2.0教程八《制作简单的关键帧动画》
·Unigine2.0教程九《Script实现相机》
·Unigine2.0教程十《Script实现物体移动》
☏ 推荐产品

小宅 Z5 2018青春版
商家:小宅

杰瑞特运动平台
商家:杰瑞特智能

Dikalis眼动追踪
商家:赢富仪器

魔神 Hawk
商家:魔神运动分析

5DT Binoculars
商家:四维宇宙

Christie DS+750
商家:四维宇宙

Zalman M220W
商家:四维宇宙

全息360°
商家:四维宇宙

PD F10 AS3D
商家:四维宇宙

PHANTOM系列
商家:四维宇宙
☞ 外设导航
☏ 企业名录
【深圳】深圳市观度科技有限公司
【沈阳】沈阳中申高新科技有限公司
【北京】北京未尔锐创科技有限公司
【南昌】南昌虚拟现实检测技术有限公司
【上海】上海桥媒信息科技有限公司
【宁波】宁波维真显示科技股份有限公司
【潍坊】歌尔股份有限公司
【上海】霍尼韦尔(中国)有限公司
【北京】科视Christie-中国
【北京】北京华如科技股份有限公司
关于本站联系我们融资计划免责声明网站建设广告服务咨询策划行业推广
北京第三维度科技有限公司 版权所有 京ICP备15051154号-3
2008-2020 Beijing The third dimension Inc. All Rights Reserved.
Email:d3dweb@163.com  QQ:496466882
Mob:13371637112(24小时)
关注虚拟现实
关注第三维度