使用盖莫游戏引擎在线程中渲染的简单例子
绘制简单的几何体小例子
比较简单
代码如下:
1 #include <GEngine/GaiMo.hpp>
2
3 core::Color color1(0.0f,0.0f,1.0f),color2(0.0f,1.0f,0.0f);
4 core::Color color3(1.0f,0.0f,0.0f),color4(1.0f,0.0f,1.0f);
5 core::Color color5(1.0f,1.0f,0.0f),color6(0.0f,1.0f,1.0f);
6
7 core::Device *device = NULL;
8
9 ThreadId id = 0;
10 bool flag = true;
11
12 void G_CALL Render(void* ptr)
13 {
14 device->AttachRender();
15 do
16 {
17 BEGIN_LOOP(device)
18 //! 绘制矩形
19 core::Render::SetCurrentColor(color1);
20 core::Render::FillRect(100,120,50,50);
21 //! 绘制矩形
22 core::Render::SetCurrentColor(color2);
23 core::Render::DrawRect(100,180,50,50);
24 //! 绘制网格
25 core::Render::SetCurrentColor(color3);
26 core::Render::DrawGrid(Point(10,10),Point(20,20),Point(5,5));
27 //! 绘制变色矩形
28 core::Render::DrawRaisedRectangle(libmath::Rect<float>(250,50,50,50),color5,color6);
29 //! 绘制三角形
30 core::Render::SetCurrentColor(color4);
31 core::Render::DrawTriangle(Point(200,180),Point(200,270),Point(290,110),true);
32 END_LOOP(device);
33 }while(flag);
34 }
35
36 int Main()
37 {
38 device = core::InitDevice("线程渲染");
39 device->Ortho2D();
40 device->DetachRender();
41 id = device->CreateThread(Render,NULL);
42 BEGIN_LOOP(device)
43 if(device->GetInput()->IsPressedKey(KEY_BACKSPACE) == true)
44 flag = false;
45 END_LOOP(device)
46
47 device->Close();
48 device->Drop();
49
50 return 1;
51 }
52
贴图为:
说明使用线程渲染是先断开opengl上下文
然后在线程中再勾住opengl上下文
然后其他操作就一般化了
摘要: 本例子源于ode自带的例子:demo_chain2演示的是一个由小盒子构成的链子在受正弦力左右下的物理现象(当然还有重力因素).其代码如下:
1 //! 2010.03.03 2 ///////////////////////////////////////////////////// 3 ...
阅读全文
摘要: 当前引擎只是简单的封装了ode几个函数而已更多的工作需要以后慢慢加入之这个demo的含义是物理对象在物理场景中会是到重力的作用,如果没有支持物的话会向下掉下面这是实现的代码-为了贴图我把重力加速度设置的很小(-0.0098f)
1 //! 2010.03.03 2 ////////////////////////////...
阅读全文
这不是正式测试的demo例子
其存在的必要是为物理引擎Demo做准备的O(∩_∩)O~
1 //! 2010.03.03
2 /////////////////////////////////////////////////////
3 /// 盖莫游戏引擎的立方体绘制
4 /////////////////////////////////////////////////////
5 //! 测试立方体绘制函数,矩阵,输入输出
6 //! 按键f1,f2,f3旋转立方体
7 #include <GEngine/Gaimo.hpp>
8 using namespace std;
9
10 Matrix4f mat;
11
12 //! 处理鼠标响应
13 void MouseCheck(core::Input* input);
14
15 int main(int argc, char **argv)
16 {
17 //! 初始化引擎设备并得到设备指针
18 core::Device* device = core::InitDevice("盖莫引擎立方体测试");
19 //! 得到引擎场景指针
20 core::RefPtr<core::SceneManager> scenemanager = device->GetSceneManager();
21 //! 得到引擎资源指针
22 core::ResourceManager* resourcemanager = device->GetResourceManager();
23
24 //! 获取lua指针
25 LuaPlus::LuaStateOwner *lua = device->GetLuaStateOwner();
26
27 //! 得到logo图形和其纹理
28 core::RefPtr<core::Image> logo = resourcemanager->GetImage("logo","..\\image//logo.jpg");
29 core::RefPtr<core::Texture> logotexture = resourcemanager->GetTexture("logo",logo);
30 logotexture->Bind();
31
32 //! 获取全局摄像机
33 core::RefPtr<core::Camera> camera = scenemanager->GetGlobalCamera(Vector3f(30,30,30),
34 Vector3f(0,0,0),
35 Vector3f(0,1,0));
36 camera->SetViewport(0,0,640,480);
37 camera->SetPerspective(50.0f,640.0f/480.0f,0.1f,1000.0f);
38 glClearDepth(1.0f);
39 glDepthFunc(GL_LEQUAL);
40 glEnable(GL_DEPTH_TEST);
41 glEnable(GL_CULL_FACE);
42 glShadeModel(GL_SMOOTH);
43 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
44
45 float sides[] = {16,16,16};
46 float pos[] = {0,0,0};
47
48 BEGIN_LOOP(device)
49 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
50 glLoadIdentity();
51 camera->SetPerspective(45.0f,640.0f/480.0f,0.1f,1000.0f);
52 camera->Render();
53 MouseCheck(device->GetInput());
54 core::Render::RenderCube((int)logotexture->GetTextureId(),pos,mat.ptr(),sides);
55 END_LOOP(device)
56
57 device->Close();
58 device->Drop();
59
60 return 0;
61 }
62
63 //! 处理鼠标响应
64 void MouseCheck(core::Input* input)
65 {
66 if(input->IsPressedKey(KEY_F1))
67 {
68 mat*=mat.Rotate((rand()%200)/900.0f,1,0,0);
69 }
70 else if(input->IsPressedKey(KEY_F2))
71 {
72 mat*=mat.Rotate((rand()%200)/900.0f,0,1,0);
73 }
74 else if(input->IsPressedKey(KEY_F3))
75 {
76 mat*=mat.Rotate((rand()%200)/900.0f,0,0,1);
77 }
78 }
显示结果如图:
2.
其实这里的按键消息响应应该采用插槽
当然是使用盖莫游戏引擎啦。
代码如下:
1 代码如下:
2
3 #include <GEngine/Gaimo.hpp>
4 #include <iostream>
5 using namespace std;
6
7 int main(int argc, char **argv)
8 {
9 //! 初始化引擎设备并得到设备指针
10 core::Device* device = core::InitDevice("盖莫引擎室外场景测试1");
11 //! 得到引擎场景指针
12 core::RefPtr<core::SceneManager> scenemanager = device->GetSceneManager();
13 //! 得到引擎资源指针
14 core::ResourceManager* resourcemanager = device->GetResourceManager();
15
16 //! 获取lua指针
17 LuaPlus::LuaStateOwner *lua = device->GetLuaStateOwner();
18 //! 载入lua脚本
19 (*lua)->DoFile("..\\script//skybox.lua");
20 //! 获取天空盒表对象
21 LuaPlus::LuaObject skyboxtable = (*lua)->GetGlobal("skybox");
22
23 //! 得到天空盒图形和其纹理
24 core::RefPtr<core::Image> skyimage0 = resourcemanager->GetImage("sky1",skyboxtable["front"].GetString());
25 core::RefPtr<core::Image> skyimage1 = resourcemanager->GetImage("sky2",skyboxtable["back"].GetString());
26 core::RefPtr<core::Image> skyimage2 = resourcemanager->GetImage("sky3",skyboxtable["left"].GetString());
27 core::RefPtr<core::Image> skyimage3 = resourcemanager->GetImage("sky4",skyboxtable["right"].GetString());
28 core::RefPtr<core::Image> skyimage4 = resourcemanager->GetImage("sky5",skyboxtable["top"].GetString());
29 core::RefPtr<core::Texture> sky0 = resourcemanager->GetTexture("front",skyimage0);
30 core::RefPtr<core::Texture> sky1 = resourcemanager->GetTexture("back",skyimage1);
31 core::RefPtr<core::Texture> sky2 = resourcemanager->GetTexture("left",skyimage2);
32 core::RefPtr<core::Texture> sky3 = resourcemanager->GetTexture("right",skyimage3);
33 core::RefPtr<core::Texture> sky4 = resourcemanager->GetTexture("top",skyimage4);
34
35 //! 得到天空盒指针
36 core::RefPtr<core::Renderable> skybox = scenemanager->GetSkyBox(sky0,sky1,sky2,sky3,sky4,
37 skyboxtable["width"].GetFloat(),
38 skyboxtable["length"].GetFloat(),
39 skyboxtable["heigth"].GetFloat()
40 ,skyboxtable["rotstep"].GetFloat());
41 //! 载入lua脚本
42 (*lua)->DoFile("..\\script//terrain.lua");
43 //! 获取地形表对象
44 LuaPlus::LuaObject terraintable = (*lua)->GetGlobal("terrain");
45
46 //! 得到地形图形和其纹理
47 core::RefPtr<core::Image> terrainimage0 = resourcemanager->GetImage("terrain0",terraintable["image1"].GetString());
48 core::RefPtr<core::Image> terrainimage1 = resourcemanager->GetImage("terrain1",terraintable["image2"].GetString());
49 core::RefPtr<core::Texture> terraintexture0 = resourcemanager->GetTexture("terraim0",terrainimage0);
50 core::RefPtr<core::Texture> terraintexture1 = resourcemanager->GetTexture("terraim1",terrainimage1);
51
52 //! 创建地形描述符
53 core::TerrainDesc desc;
54 desc.main_texture = terraintexture0;
55 desc.detail_texture = terraintexture1;
56 desc.use_detail = terraintable["usedetail"].GetInteger();
57
58 //! 获取地形指针
59 core::RefPtr<core::Terrain> terrain = scenemanager->GetTerrain(desc);
60 terrain->LoadHeigthMap(terraintable["rawfile"].GetString(),terraintable["mapsize"].GetInteger(),terraintable["cell"].GetInteger());
61
62 //! 获取全局摄像机
63 core::RefPtr<core::Camera> camera = scenemanager->GetGlobalCamera(Vector3f(250,terrain->GetHeight(250,215)+10,215),
64 Vector3f(251,terrain->GetHeight(251,216)+10,216),
65 Vector3f(0,1,0));
66 camera->SetViewport(0,0,640,480);
67 camera->SetPerspective(50.0f,640.0f/480.0f,0.1f,1000.0f);
68 glClearDepth(1.0f);
69 glDepthFunc(GL_LEQUAL);
70 glEnable(GL_DEPTH_TEST);
71 glEnable(GL_CULL_FACE);
72 glShadeModel(GL_SMOOTH);
73 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
74 BEGIN_LOOP(device)
75 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
76 glLoadIdentity();
77 camera->SetPerspective(45.0f,640.0f/480.0f,0.1f,1000.0f);
78 camera->Render();
79 skybox->Render();
80 terrain->Render();
81 END_LOOP(device)
82
83 device->Close();
84 device->Drop();
85
86 return 0;
87 }
2个lua配置文件
1.
-- 这是盖莫引擎中使用lua脚本配置天空盒的脚本
1 -- 定义天空盒数据
2 skybox =
3 {
4 front = "..\\image//sky//front.jpg";
5 back = "..\\image//sky//back.jpg";
6 left = "..\\image//sky//left.jpg";
7 right = "..\\image//sky//right.jpg";
8 top = "..\\image//sky//top.jpg";
9 width = 600;
10 length = 600;
11 heigth = 600;
12 rotstep= 0.003;
13 }
2.
1 -- 这是盖莫引擎中使用lua脚本配置地形的脚本
2
3 -- 定义地形数据
4 terrain =
5 {
6 rawfile = "..\\terrain//terrain.raw";
7 image1 = "..\\terrain//terrain.bmp";
8 image2 = "..\\terrain//detail.bmp";
9 usedetail = 1;
10 mapsize = 1024;
11 cell = 16
12 }
这里使用了简单的lua表数据结构
当然这个还会不断改进的
接上文介绍了ode的基本函数,接下来应该考虑如何绑定Ode和游戏引擎
简单的说,单单使用ode不是什么难事情,必须网上使用ode的例子一大把
问题的关键是如何较好的结合ode和引擎,记不至于游戏引擎把ode封装的太深以至于影响其使用的灵活性.另外一方面是,也不能把过多的额外操作抛给用户操作。
不过可以先设计一个基本的框架,以后根据需要和认识的不断加深再做修改。
于是先写下物理引擎的基本框架-很简单的了:
1 ////////////////////////////////////////////////////////////
2 /// 定义物理引擎模板类
3 ////////////////////////////////////////////////////////////
4 template<class World,class Space,class JointGroup,class Geom>
5 class PhysicsEngine
6 {
7 public:
8 typedef void(*ContactNearCallback)(void *data, Geom o1, Geom o2);
9 public:
10 ///////////////////////////////////////////////////////
11 /// 构造,析构物理引擎类
12 ///////////////////////////////////////////////////////
13 PhysicsEngine();
14 ~PhysicsEngine();
15 public:
16 ///////////////////////////////////////////////////////
17 /// 设定物理引擎平面(ax+by+cz+d=0)
18 ///////////////////////////////////////////////////////
19 void SetPlane(float a = 0, float b = 0, float c = 1, float d = 0);
20
21 ///////////////////////////////////////////////////////
22 /// 设定物理世界重力加速度
23 ///////////////////////////////////////////////////////
24 void SetGravity(float x = 0, float y = 0, float z = -9.81);
25
26 ///////////////////////////////////////////////////////
27 /// 设定物理世界仿真更新值
28 ///////////////////////////////////////////////////////
29 inline void SetStepValue(float step = 0.05f, bool quick = true)
30 {
31 this->step = step; this->quick = quick;
32 }
33
34 ///////////////////////////////////////////////////////
35 /// 加载引擎物理对象碰撞回调函数
36 ///////////////////////////////////////////////////////
37 inline void SetCollideCallBack(ContactNearCallback callback)
38 {
39 this->callback = callback;
40 }
41
42 ///////////////////////////////////////////////////////
43 /// 调用物理引擎模拟
44 ///////////////////////////////////////////////////////
45 void Simulation();
46
47 ///////////////////////////////////////////////////////
48 /// 获取物理引擎世界,空间和关节组对象.
49 ///////////////////////////////////////////////////////
50 inline World GetWorld(){return world;}
51 inline Space GetSpace(){return space;}
52 inline JointGroup GetContactGroup(){return contactgroup;}
53 private:
54 World world;
55 Space space;
56 JointGroup contactgroup;
57 ContactNearCallback callback;
58 float step;
59 bool quick;
60 };
61
62 #ifdef PHYSICS_EXT_ODE
63 #include "OdePhysics.inl"
64 #endif
具体对于ode,我看可以这样使用之:
1 core::PhysicsEngine<dWorldID,dSpaceID,dJointGroupID,dGeomID> engine;
或者可以这样
1 core::PhysicsEngine<> engine;
再给出一个简单的物理对象数据结构
1 ////////////////////////////////////////////////////////////
2 /// 定义引擎物理对象数据结构(一个对象由N个几何体构成)
3 ////////////////////////////////////////////////////////////
4 /*template<class Object,class Geom,int N>
5 struct PhysicsObject
6 {
7 Object object;
8 //! 有必要设计一个定长数组了.
9 Geom geom[N];
10 };*/
一个物理对象由N个简单几何体构成
这个是简单到了极点只是不太符合要求
下一步该考虑设计物理对象类了
对象可以旋转,平移,设置质量,加挂几何体.......
最后再上几个ode函数加深一点认识吧:
1 /**
2 * @brief Set the local offset rotation matrix of a geom from its body.
3 *
4 * Sets the geom's rotational offset in local coordinates.
5 * After this call, the geom will be at a new position determined from the
6 * body's position and the offset.
7 * The geom must be attached to a body.
8 * If the geom did not have an offset, it is automatically created.
9 *
10 * @param geom the geom to set.
11 * @param R the new rotation matrix.
12 * @ingroup collide
13 */
14 ODE_API void dGeomSetOffsetRotation (dGeomID geom, const dMatrix3 R);
设置几何体相对于其物体的局部旋转平移矩阵
1 /**
2 * @brief Set the offset position of a geom from its body.
3 *
4 * Sets the geom's positional offset to move it to the new world
5 * coordinates.
6 * After this call, the geom will be at the world position passed in,
7 * and the offset will be the difference from the current body position.
8 * The geom must be attached to a body.
9 * If the geom did not have an offset, it is automatically created.
10 *
11 * @param geom the geom to set.
12 * @param x the new X coordinate.
13 * @param y the new Y coordinate.
14 * @param z the new Z coordinate.
15 * @ingroup collide
16 */
17 ODE_API void dGeomSetOffsetWorldPosition (dGeomID geom, dReal x, dReal y, dReal z);
生成,设置几何对象的函数:
1 ODE_API dGeomID dCreateSphere (dSpaceID space, dReal radius);
2 ODE_API void dGeomSphereSetRadius (dGeomID sphere, dReal radius);
3 ODE_API dReal dGeomSphereGetRadius (dGeomID sphere);
4 ODE_API dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz);
5 ODE_API void dGeomBoxSetLengths (dGeomID box, dReal lx, dReal ly, dReal lz);
6 ODE_API void dGeomBoxGetLengths (dGeomID box, dVector3 result);
7 ODE_API dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length);
8 ODE_API void dGeomCapsuleSetParams (dGeomID ccylinder, dReal radius, dReal length);
9 ODE_API void dGeomCapsuleGetParams (dGeomID ccylinder, dReal *radius, dReal *length);
10 ODE_API dReal dGeomCapsulePointDepth (dGeomID ccylinder, dReal x, dReal y, dReal z);
11 ODE_API dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length);
12 ODE_API void dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length);
13 ODE_API void dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length);
14 ODE_API dGeomID dCreateRay (dSpaceID space, dReal length);
15 ODE_API void dGeomRaySetLength (dGeomID ray, dReal length);
16 ODE_API dReal dGeomRayGetLength (dGeomID ray);
17 ODE_API void dGeomRaySet (dGeomID ray, dReal px, dReal py, dReal pz,
18 dReal dx, dReal dy, dReal dz);
19 ODE_API void dGeomRayGet (dGeomID ray, dVector3 start, dVector3 dir);
刚使用dev c++编译完ode0.11.1库
现在说明下如何编译之(说实话有些开源库似乎不是太容易编译的)
1.从http://sourceforge.net/projects/opende/files/下载ode库
2.ode库是依赖于opcode库的所以先要编译opcod库
3.为简便起见把ode中的
#if defined(_MSC_VER)
#if defined(ODE_DLL)
#define ODE_API __declspec(dllexport)
#elif !defined(ODE_LIB)
#define ODE_DLL_API __declspec(dllimport)
#endif
#endif
#if !defined(ODE_API)
#define ODE_API
#endif
直接使用
#define ODE_API __declspec(dllexport) 代替之
4.对于opcode库也一样
5.编译opcode库
6.编译ode库如何发现有没定义的alloca函数则包含头文件malloc于所在问题
7.对于其它一些没定义的函数或者数据结构也要加上其函数声明的头文件
本人使用devc++编译过的开源库列表
1.zthread.
2.glfw
3.ogg
4.libmad
5.freetype
6.ftgl
7...
题外话,
ode大致的函数看过了
ode也编译了
ode所带的例子也看过了
那下一步的动作是?
接着上文继续学习ode物理引擎的函数和数据结构O(∩_∩)O~
15.刚体对象的启用和禁止
刚体对象可以被启用或者禁止
禁止刚体对象则在仿真过程中刚体不参与仿真
如果启用自禁止的话,那么刚体对象会在给定仿真步中idle(如何翻译?)
如果启用自动禁止的话,那么当刚体线速度和角速度同时小于给定阈值之时被禁止
1 void dBodyEnable (dBodyID);
2 void dBodyDisable (dBodyID);
3 int dBodyIsEnabled (dBodyID);
4 void dBodySetAutoDisableFlag (dBodyID, int do_auto_disable);
5 int dBodyGetAutoDisableFlag (dBodyID);
1void dBodySetAutoDisableAngularThreshold (dBodyID, dReal angular_threshold);
2dReal dBodyGetAutoDisableAngularThreshold (dBodyID);
3void dBodySetAutoDisableLinearThreshold (dBodyID, dReal linear_threshold);
4dReal dBodyGetAutoDisableLinearThreshold (dBodyID);
需要确保的是线速度和角速度要小于给定的阈值
16.几个杂项函数
1 void dBodySetData (dBodyID, void *data);
2 void *dBodyGetData (dBodyID);
设置,和获取刚体数据
1 int dBodyGetNumJoints (dBodyID b);
获取关联到物体上的关节个数
1 dJointID dBodyGetJoint (dBodyID, int index);
获取给物体上定标号的关节句柄
1 void dBodySetGravityMode (dBodyID b, int mode);
2 int dBodyGetGravityMode (dBodyID b);
设置和获取物体是否受重力影响(默认为是)
1 void dMakeRandomVector (dReal *A, int n, dReal range);
获取n个范围在+-rang中的随机变量
17.矩阵操作
-- 在任何引擎中矩阵都是必不可少的
1 void dRSetIdentity (dMatrix3 R);
2 void dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az,dReal angle);
3 void dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi);
4 void dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az,dReal bx, dReal by, dReal bz);
5 void dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az);
6 void dQSetIdentity (dQuaternion q);
7 void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az,dReal angle);
8 void dQMultiply0 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc);
9 void dQMultiply3 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc);
10 void dRfromQ (dMatrix3 R, const dQuaternion q);
11 void dQfromR (dQuaternion q, const dMatrix3 R);
12 void dDQfromW (dReal dq[4], const dVector3 w, const dQuaternion q);
这些函数为别是:
设置为单位矩阵,
从给定轴和角度或者矩阵
从欧拉角到矩阵
...
18.ode关节
1 dJointID dJointCreateBall (dWorldID, dJointGroupID);
2 dJointID dJointCreateHinge (dWorldID, dJointGroupID);
3 dJointID dJointCreateSlider (dWorldID, dJointGroupID);
4 dJointID dJointCreateContact (dWorldID, dJointGroupID,
5 const dContact *);
6 dJointID dJointCreateUniversal (dWorldID, dJointGroupID);
7 dJointID dJointCreateHinge2 (dWorldID, dJointGroupID);
8 dJointID dJointCreateFixed (dWorldID, dJointGroupID);
9 dJointID dJointCreateAMotor (dWorldID, dJointGroupID);
10 void dJointDestroy (dJointID);
可以看出ode中定义的关机类型有Ball,Hinge,Slider,...
对关节的销毁动作为断开所有连接的引擎物体,再销毁关节
1 dJointGroupID dJointGroupCreate (int max_size);
2 void dJointGroupDestroy (dJointGroupID);
3 void dJointGroupEmpty (dJointGroupID);
4
第一个函数中的max_size目前必须是(0)这是为了和以前兼容
销毁关节和清空关节点区别在于销毁会销毁关节组中所有的关节对象和销毁关节组,而清空关节组则只是销毁所有的关节对象
1 void dJointAttach (dJointID, dBodyID body1, dBodyID body2);
使用给定关节连接2个物理对象,如果关节先前是连接的则断开之,如果body1或者body2有1个为0则说明把对象连接对静态环境中去
1 void dJointSetData (dJointID, void *data);
2 void *dJointGetData (dJointID);
设置关节数据没什么好说的
1 int dJointGetType (dJointID);
获取给定关节的关节类型
可能的类型有
dJointTypeBall A ball-and-socket joint.
dJointTypeHinge A hinge joint.
dJointTypeSlider A slider joint.
dJointTypeContact A contact joint.
dJointTypeUniversal A universal joint.
dJointTypeHinge2 A hinge-2 joint.
dJointTypeFixed A fixed joint.
dJointTypeAMotor An angular motor joint.
1 dBodyID dJointGetBody (dJointID, int index);
获取关节给定索引的连接物理对象(以0索引起始)
1 int dAreConnected (dBodyID, dBodyID);
检测2个问题是不是别连接了
19.关节接触;
ode用户指南的原文是:
The contact joint prevents body 1 and body 2 from inter-penetrating at the contact point. It does this by
only allowing the bodies to have an "outgoing "velocity in the direction of the contact normal. Contact joints
typically have a lifetime of one time step. They are created and deleted in response to collision detection.
Contact joints can simulate friction at the contact by applying special forces in the two friction directions
that are perpendicular to the normal.When a contact joint is created, a dContact structure must be supplied. This has the following definition:
接触关节预防碰撞对象的"刺穿"问题,当接触关节产生的时候,其必要的数据元素必须被标记
1 struct dContact {
2 dSurfaceParameters surface;
3 dContactGeom geom;
4 dVector3 fdir1;
5 };
goem是碰撞函数设置的数据结构其中包含了:
碰撞点,碰撞法向矢量和碰撞的2个对象id
而fdir是第一摩擦力方向(其方向和摩擦力方向是相同的),同时也是垂直于接触面法向矢量的.
当且仅当surface.mode = dContactFDir1时期需要被定义
而第二摩擦力方向则是由第一摩擦里方向和接触面方向矢量计算的正交向量
其中的dSurfaceParameters surface是由用户设置的数据结构
其数据结构为:
1 typedef struct dSurfaceParameters {
2 /* must always be defined */
3 int mode;
4 dReal mu;
5
6 /* only defined if the corresponding flag is set in mode */
7 dReal mu2;
8 dReal bounce;
9 dReal bounce_vel;
10 dReal soft_erp;
11 dReal soft_cfm;
12 dReal motion1,motion2;
13 dReal slip1,slip2;
14 } dSurfaceParameters;
其中的mode必须被标记
mu和mu2取值为(0 to dInfinity.)
如果没有设置mu2,则使用mu为2个摩擦力方向
如果设置了mu2则使用mu为第一个摩擦力方向使用mu2为第二摩擦力方向
如果设置了fdir1则使用fdir作为第一摩擦力方向要不然则自动获取其值
bounce表明其为弹性表面也就是说碰撞对象会相互弹起(取值0-1)0标明完全没有弹性
soft_erp控制的是接触表面的erp,这个值可以设置柔性表面
soft_cfm控制的是柔性表面的最大cfm
其他参数以后再介绍之
20.几何体对象
几何体是检测系统中的基本单元
几何体的销毁和生成
1 void dGeomDestroy (dGeomID);
2 void dGeomSetData (dGeomID, void *);
3 void *dGeomGetData (dGeomID);
4 void dGeomSetBody (dGeomID, dBodyID);
5 dBodyID dGeomGetBody (dGeomID);
6 void dGeomSetPosition (dGeomID, dReal x, dReal y, dReal z);
7 void dGeomSetRotation (dGeomID, const dMatrix3 R);
8 void dGeomSetQuaternion (dGeomID, const dQuaternion);
9 const dReal * dGeomGetPosition (dGeomID);
10 const dReal * dGeomGetRotation (dGeomID);
11 void dGeomGetQuaternion (dGeomID, dQuaternion result);
12 void dGeomGetAABB (dGeomID, dReal aabb[6]);
13 int dGeomIsSpace (dGeomID);
14 dSpaceID dGeomGetSpace (dGeomID);
其中有几何体的销毁,设置几何体数据,关联几何体到缸体
设置,获取几何体旋转,
获取几何体aabb盒子以及检测几何体是否在空间中
1 int dGeomGetClass (dGeomID);
这是获取几何体类型的函数其取值为:
dSphereClass Sphere
dBoxClass Box
dCCylinderClass Capped cylinder
dCylinderClass Regular flat-ended cylinder
dPlaneClass Infinite plane (non-placeable)
dGeomTransformClass Geometry transform
dRayClass Ray
dTriMeshClass Triangle mesh
dSimpleSpaceClass Simple space
dHashSpaceClass Hash table based space
int dGeomGetClass (dGeomID);
下面的是几何体的禁止和启用
1 void dGeomEnable (dGeomID);
2 void dGeomDisable (dGeomID);
3 int dGeomIsEnabled (dGeomID);
如果几何体被禁止那么他就不会才与碰撞(尽管它在物理空间中)
该篇就到这里吧,这里给出一个典型的接触面设置:
1 surface.mode = dContactBounce | dContactSoftCFM;
2 surface.mu = dInfinity;
3 surface.mu2 = 0;
4 surface.bounce = 0.01;
5 surface.bounce_vel = 0.1;
6 surface.soft_cfm = 0.01;
可以看出他是使用了接触面弹起
其第一摩擦力方向和第二摩擦力方向是相同的
常见的物理引擎有ode,newtow,phycisX,Havok以及子弹引擎等等
本文介绍ode物理引擎中常用的函数:
1.获取物理引擎世界,大部分程序我们仅仅需要一个world(返回值为世界句柄)
dWorldID dWorldCreate();
2.销毁给定的物理引擎世界和包含的所有物体和不包含在关节组中的所有关节
1 dWorldDestroy (dWorldID);
3.设置和获取物理世界中的重力加速度
1 void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z);
2 void dWorldGetGravity (dWorldID, dVector3 gravity);
其单位是m/s^2,假定z轴向上的话,那么地球重力加速度是(0,0,-9.81)
在ode中默认的重力加速度是(0,0,0)
4.设置和获取引擎仿真步修正误差
1 void dWorldSetERP (dWorldID, dReal erp);
2 dReal dWorldGetERP (dWorldID);
典型的取值为(0.-0.8),默认取值为0.2
5.设置引擎全局混合约束力(constraint force mixing)
1 void dWorldSetCFM (dWorldID, dReal cfm);
2 dReal dWorldGetCFM (dWorldID);
典型取值为(10e-9,1)之间,
默认值为单精度时为10e-5,双精度时为10e-10
6.物理世界的更新操作
1 void dWorldStep (dWorldID, dReal stepsize);
2 void dWorldQuickStep (dWorldID, dReal stepsize);
stepsize为步进大小一般可取为0.5f
可简单描述为dWorldStep:精度高但是速度低
dWorldQuickStep:精度低但是速度快
7.设置和获取仿真步迭代器个数
1void dWorldSetQuickStepNumIterations (dWorldID, int num);
2int dWorldGetQuickStepNumIterations (dWorldID);
默认的迭代器个数为20.迭代器越多则结果越精确但是速度会变慢
8.设置和获取对象接触修正速度
void dWorldSetContactMaxCorrectionVel (dWorldID, dReal vel);
dReal dWorldGetContactMaxCorrectingVel (dWorldID);
其默认值是没有限制的
简言之该函数决定了对象碰撞之后对象的速度变化上限
9.设置对象表面接触深度
1 void dWorldSetContactSurfaceLayer (dWorldID, dReal depth);
2 dReal dWorldGetContactSurfaceLayer (dWorldID);
默认的大小是0也就是对象不会透过对象
给定一个极小值比如0.01可以预防振动问题
接下来是一些刚体函数:
10.获取和销毁给定空间中的刚体对象
1 dBodyID dBodyCreate (dWorldID);
2 void dBodyDestroy (dBodyID);
新生成的刚体质量为默认值,其位置在0点
销毁一个刚体其附加的关节点并不会消除也就是说不会影响仿真
11.刚体的位置和旋转操作
1 void dBodySetPosition (dBodyID, dReal x, dReal y, dReal z);
2 void dBodySetRotation (dBodyID, const dMatrix3 R);
3 void dBodySetQuaternion (dBodyID, const dQuaternion q);
4 void dBodySetLinearVel (dBodyID, dReal x, dReal y, dReal z);
5 void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z);
6 const dReal * dBodyGetPosition (dBodyID);
7 const dReal * dBodyGetRotation (dBodyID);
8 const dReal * dBodyGetQuaternion (dBodyID);
9 const dReal * dBodyGetLinearVel (dBodyID);
10 const dReal * dBodyGetAngularVel (dBodyID);
这些函数含义很明显,需要注意的就是
dBodyGetRotation返回的是一个4*3的旋转矩阵
12.设置,获取刚体质量
1 void dBodySetMass (dBodyID, const dMass *mass);
2 void dBodyGetMass (dBodyID, dMass *mass);
13.刚体受力
1 void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz);
2 void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz);
3 void dBodyAddRelForce (dBodyID, dReal fx, dReal fy, dReal fz);
4 void dBodyAddRelTorque (dBodyID, dReal fx, dReal fy, dReal fz);
5 void dBodyAddForceAtPos (dBodyID, dReal fx, dReal fy, dReal fz,
6 dReal px, dReal py, dReal pz);
7 void dBodyAddForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz,
8 dReal px, dReal py, dReal pz);
9 void dBodyAddRelForceAtPos (dBodyID, dReal fx, dReal fy, dReal fz,
10 dReal px, dReal py, dReal pz);
11 void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz,
12 dReal px, dReal py, dReal pz);
四个参数的函数表明受力点为刚体质心
7个参数的函数表明受力点位刚体给定点位置
1 const dReal * dBodyGetForce (dBodyID);
2 const dReal * dBodyGetTorque (dBodyID);
3 void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z);
4 void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z);
注意这是刚体受力和扭矩设置,获取函数
这对于清空刚体受力或者扭矩很有作用
最后是几个ode空间函数
14.空间的构造和析构
1 dSpaceID dSimpleSpaceCreate (dSpaceID space);
2 dSpaceID dHashSpaceCreate (dSpaceID space);
3 dSpaceID dQuadTreeSpaceCreate (dSpaceID space, dVector3 Center, dVector3 Extents, int Depth);
4 void dSpaceDestroy (dSpaceID);
15.空间平面坐标系设定
dCreatePlane(space, a, b, c, d);
参数a,b,c,d满足以下函数关系
ax+by+cz = d;
那么
1 dCreatePlane(space, 0, 1, 0, 0);
2 dWorldSetGravity(world, 0, -0.8, 0);
的含义是
以空间y轴为重力加速度效果方向
其重力加速度大小为-0.8速度为沿y轴向下.
给引擎正式加入对lua脚本的支持
其实最便利的办法就是脚本和引擎独立开来,但是这样不便于c++和lua的通信
若是把lua全部都封装进引擎则由于lua和c++是2个不同的语言很难实现
再者封装的一个弊端是封装的越好则越的其灵活性降低
考虑下我把引擎lua上下文设计成了以下的样子:
1 ////////////////////////////////////////////////////////////
2 /// 定义引擎Lua脚本上下文
3 ////////////////////////////////////////////////////////////
4 class LuaContext : public core::Object
5 {
6 public:
7 ///////////////////////////////////////////////////////
8 /// 构造,析构引擎Lua脚本上下文
9 ///////////////////////////////////////////////////////
10 LuaContext(){}
11 virtual ~LuaContext(){}
12 public:
13 #ifdef LUA_EXT_LUAPLUS
14 ///////////////////////////////////////////////////////
15 /// 获取luastateowner指针
16 ///////////////////////////////////////////////////////
17 virtual LuaPlus::LuaStateOwner* GetLuaStateOwner() = 0;
18 #endif
19 ///////////////////////////////////////////////////////
20 /// 执行给定lua脚本字符串
21 ///////////////////////////////////////////////////////
22 virtual int DoStirng(const char* script) = 0;
23
24 ///////////////////////////////////////////////////////
25 /// 载入给定lua脚本并执行(.lua,.luac)
26 ///////////////////////////////////////////////////////
27 virtual int DoFile(const char* luafile) = 0;
28 public:
29 ///////////////////////////////////////////////////////
30 /// 从lua上下文中获取给定名字的全局整数变量
31 ///////////////////////////////////////////////////////
32 virtual int GetInteger(const char* var, int def = 0) = 0;
33
34 ///////////////////////////////////////////////////////
35 /// 从lua上下文中获取给定名字的全局浮点数变量 GetDouble()
36 ///////////////////////////////////////////////////////
37 virtual float GetFloat(const char* var, float def = 0.0f) = 0;
38 virtual double GetDouble(const char* var, double def = 0.0) = 0;
39
40 ///////////////////////////////////////////////////////
41 /// 从lua上下文中获取给定名字的全局字符串变量(len为字符串长度)
42 ///////////////////////////////////////////////////////
43 virtual const char* GetString(const char* var, int &len) = 0;
44
45 ///////////////////////////////////////////////////////
46 /// 从lua上下文中获取给定名字的全局布尔变量(flag为标记符号)
47 ///////////////////////////////////////////////////////
48 virtual bool GetBoolean(const char* var, bool &flag) = 0;
49
50 ///////////////////////////////////////////////////////
51 /// 执行lua上下文中的给定函数(该函数既无参数也无返回值)
52 ///////////////////////////////////////////////////////
53 virtual void RunFunction(const char* fn) = 0;
54
55 DECLARE_OBJECT(LuaContext)
56 };
57
通过GetLuaStateOnwer获取引擎全局的lua state指针.
当然LuaContext中只是简单封装了一些获取全局变量的函数.
当然这些是最常用的.
随着引擎的开发我再根据情况加入更多可能的函数.