以前看过很长时间的boost,记得上面有STATIC_ASSERT
在loki库中也有类似的宏
1 LOKI_STATIC_CHECK(expr, msg)
其中expr代表要断言的表达式
当其为假,则让程序无法通过编译
其实现很简单
利用模板特化:
1 template<int> struct CompileTimeError;
2 template<> struct CompileTimeError<true> {};
当表达式为真则使用模板特化形式
注意其模板在这里仅仅做前向引用
再看具体的宏:
1 #define LOKI_STATIC_CHECK(expr, msg) \
2 { Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
使用代码块(statement block)
声明一个编译时错误对象
(具体原因在于当条件为假则模板对象没有具体实现,抛出一个未定义完全的对象)
9 D:\Dev-Cpp\prj\test\main.cpp aggregate `Loki::CompileTimeError<0> ERROR_wo' has incomplete type and cannot be defined
对于其宏的实现在我看来
(void)ERROR_##msg;这句是多余的(不知道这句的作用是什么??谁能告诉我)
摘要: 设计引擎的时候一直在考虑什么时候才可以支持多渲染器,比如d3d9比如软件渲染器为了尽可能的让opengl的API尽可能的与引擎代码分离我加上了一个初步封装了opengl API的类VideoDriver当前只是简单的封装了很多opengl的函数代码如下:
Code highlighting produced by Actipro CodeHighlighter (freeware)http://...
阅读全文
1.ode引擎中的几何体
ode物理引擎中的几何体有球体,盒子,胶囊,射线,平面,圆柱,网格等等
对于一般的几何体比如球体,盒子等其默认的位置为原点,也就是其中心点在坐标原点
那么对于box来说描述一个盒子只需要3个参变量分别为长高宽
对于Capped Cylinder来说
其特点就是在圆柱的上下地上各加了一个半圆形的帽子,其新生产的圆柱轴总是z轴
2.ode geom和body的关系
geom是简单的几何体
body可以代表物理场景对象
一般而言一个body总是对应于1个或者多个几何体
一个物理对象总是包含1个或者多个几何体
当然ode有函数可以检测给定几何体和物理对象的管理
对于body之间也有函数检测他们是不是相连的
3. ode关节类型
ode 具有5种类型的关节分别为
hinge,ball,slider,unversal(万向轮)以及hinge2
hinge是常见的合页那种关节形式
ball类型于游戏摇杆
slider:插销形式
hinge2则是带有轴的关节
其中大多数关节都具有内置的马达而球-涡球则不具有
Mos t joints have motors built in.Ball and sockets do not
3.弹簧-阻尼系统
2种解决方式
1.简单的:使用erp和cfm
2.复杂点的:使用物理方程式
1.erp模式:施加力保持关节附着物理不偏离
2.cfm模式-constraint force mixing
胡克定律:非k*(ra-a);
带阻尼的形式: f = k*(ra-a)-d*da
4.如何保持ode模拟的平稳性
1.僵硬的弹簧不可取
2.严格的束缚条件
3....
5.如果保持ode模拟更快
1.使用较少的关节
2.使用简单的替代物替换多重关节
3.使用较少的接触面
4.如果可能使用无摩擦或者粘性接触面替换库伦摩擦接触面
6.ode质量函数类..
清空质量
void dMassSetZero (dMass *);
void dMassSetSphere (dMass *, dReal density, dReal radius);
void dMassSetSphereTotal (dMass *, dReal total_mass, dReal radius);
void dMassSetCappedCylinder (dMass *, dReal density, int direction,dReal radius, dReal length);
void dMassSetCappedCylinderTotal (dMass *, dReal total_mass,int direction, dReal radius, dReal length);
void dMassSetCylinder (dMass *, dReal density, int direction,dReal radius, dReal length);
void dMassSetCylinderTotal (dMass *, dReal total_mass, int direction,dReal radius, dReal length);
void dMassSetBox (dMass *, dReal density,dReal lx, dReal ly, dReal lz);
void dMassSetBoxTotal (dMass *, dReal total_mass,dReal lx, dReal ly, dReal lz);
void dMassAdjust (dMass *, dReal newmass);
void dMassTranslate (dMass *, dReal x, dReal y, dReal z);
void dMassRotate (dMass *, const dMatrix3 R);
void dMassAdd (dMass *a, const dMass *b);
这是新版盖莫游戏引擎2.1.1中全脚本控制的粒子系统
相关的配套lua脚本(以后还会加入对python等脚本的支持)
1 -- 这是盖莫引擎中使用lua脚本的测试粒子
2
3 -- 定义粒子池粒子个数
4 max_particles = 2400
5
6 -- 定义粒子初始位置
7 particle_pos_x = 0.0
8 particle_pos_y = 0.0
9 particle_pos_z = 2.0
10
11 -- 定义重力加速度
12 gravity = 9.8
13
14 -- 定义粒子大小
15 particle_size = 0.8
16
17 -- 定义粒子寿命
18 particle_life = 8.2
19
20 -- 定义批处理粒子个数
21 batch_particles = 80
22
23 -- 定义粒子和地面之间的摩擦力
24 friction = 0.75
25
26 -- 定义粒子系统发射半径
27 fountain_radius = 1.6
28
29 -- 定义粒子范围半径
30 particle_r = (fountain_radius + particle_size/2)*(fountain_radius + particle_size/2)
31
32 -- 初始化随机种子
33 function InitRand()
34 math.randomseed(os.time())
35 end
36
37 -- 定义粒子速度
38 particle_vel = 8.0
39
40 -- 获取时间对应的速度值
41 function GetVelByTime(t)
42 return particle_vel*(0.8 + 0.1*(math.sin(0.5*t)+math.sin(0.31*t)))
43 end
44
45 -- 获取xy平面随机转角
46 function GetRandRotXY()
47 return (2.0*3.14159265/4096.0) * math.random(1,4095)
48 end
49
50 function InitParticles(dt)
51 -- 定义粒子初始位置
52 local xpos=particle_pos_x
53 local ypos=particle_pos_y
54 local zpos=particle_pos_z
55 -- 初始化粒子颜色red,green,blue
56 local red=0.7 + 0.3 * math.sin(0.34*dt + 0.1)
57 local green=0.6 + 0.4 * math.sin(0.63*dt + 1.1)
58 local blue=0.6 + 0.4 * math.sin(0.91*dt + 2.1)
59 ---- 获取粒子随机速度x分量
60 local xy_angle = GetRandRotXY()
61 local vt = GetVelByTime(dt)
62 local xvel=0.45 * math.cos(xy_angle)*vt
63 -- 获取粒子随机速度y分量
64 xy_angle = GetRandRotXY()
65 vt = GetVelByTime(dt)
66 local yvel=0.45 * math.sin(xy_angle)*vt
67 -- 获取粒子初始速度
68 local zvel=0.7 + (0.3/4096.0) * (math.random(1,4095))
69 return xpos,ypos,zpos,
70 red,green,blue,
71 xvel,yvel,zvel
72 end
73
74 -- 更新粒子状态
75 function UpdateParticles(life,xpos,ypos,zpos,xvel,yvel,zvel,red,green,blue,dt)
76 -- 修正粒子生命
77 local new_life = life - dt * (1.0 / particle_life)
78 -- 修正粒子速度
79 local new_zvel = zvel - gravity *dt
80 local new_xpos = xpos + xvel*dt
81 local new_ypos = ypos + yvel*dt
82 local new_zpos = zpos + new_zvel*dt
83 if new_zvel < 0.0 then
84 if new_xpos*new_xpos + new_ypos*new_ypos < particle_r and new_zpos < particle_pos_z + particle_size/2 then
85 new_zvel = -friction * new_zvel
86 new_zpos = particle_pos_z + particle_size/2 + friction * (particle_pos_z + particle_size/2 - new_zpos)
87 -- 当粒子碰撞到地面应该跳起来
88 elseif new_zpos < particle_size/2 then
89 new_zvel = -friction * new_zvel
90 new_zpos = particle_size/2 + friction * (particle_size/2 - new_zpos)
91 end
92 end
93
94 return new_life,
95 new_xpos,new_ypos,new_zpos,
96 red,green,blue,
97 xvel,yvel,new_zvel
98 end
99
100 --[[
101 盖莫引擎2.1.1使用的lua粒子脚本格式如下:
102 全局变量:
103 batch_particles
104 particle_size
105 particle_life
106 max_particles
107
108 粒子初始化函数:
109 InitParticles(dt)(参数当前时间)
110 返回位置,颜色,速度
111
112 粒子更新函数:
113 UpdateParticles(life,xpos,ypos,zpos,xvel,yvel,zvel,dt)
114 返回更新后的粒子寿命,位置,颜色以及速度
115 ]]
116
这是引擎当前粒子系统配置的脚本文件
可以改动的就是例子初始化和更新函数的实现
粒子初始化函数有1个时间输入参数
9个输出参数分别为:位置颜色速度
更新函数有粒子寿命,位置颜色速度和当前时间
传回参数有粒子新寿命,粒子位置,颜色和速度
另外几个不可缺少的全局粒子变量有
batch_particles
particle_size
particle_life
max_particles
含义就不提了
对应的cpp代码如下:
1 #include <GEngine/Gaimo.hpp>
2 using namespace core;
3 void TransForm(double t);
4
5 //! 设备指针
6 RefPtr<Device> device;
7 //! 视频驱动指针
8 RefPtr<VideoDriver> videodriver;
9 //! 3角函数表指针
10 RefPtr<libmath::TriTable> table;
11
12 int main(int argc, char **argv)
13 {
14 double t0, t;
15 device = core::InitDevice("盖莫引擎粒子测试1",argv[0]);
16 videodriver = device->GetVideoDriver();
17 table = device->GetTriTable();
18
19 core::ParticleSystemDesc desc = device->GetLuaContext()->GetParticleSystemDesc("..\\script//particle1.lua");
20 core::RefPtr<core::ParticleSystem> ps = device->GetSceneManager()->GetParticleSystem(desc);
21
22 t0 = device->GetTime();
23 BEGIN_LOOP(device)
24 t = device->GetTime() - t0;
25 videodriver->SetViewPort(Recti(0,0,640,480));
26 videodriver->SetClearColor(Color(0.0f, 0.0f, 0.3f, 1.0f));
27 videodriver->SetClearBuffer(ENGINE_CLEAR_COLOR | ENGINE_CLEAR_DEPTH);
28 videodriver->SetPerpective(65.0f,64.0/48.0,1.0f,60.0f);
29 TransForm(t);
30 ps->Render();
31 END_LOOP(device)
32 return 0;
33 }
34
35 void TransForm(double t)
36 {
37 double xpos, ypos, zpos, angle_x, angle_y, angle_z;
38 static double t_old = 0.0;
39 float dt = (float)(t-t_old);
40 t_old = t;
41
42 angle_x = 80;
43 angle_y = 10.0 * table->SinTable( 0.3 * t );
44 angle_z = 10.0 * t;
45
46 xpos = 15.0 * table->SinTable( (M_PI/180.0) * angle_z ) +
47 2.0 * table->SinTable( (M_PI/180.0) * 3.1 * t );
48 ypos = -15.0 * table->CosTable( (M_PI/180.0) * angle_z ) +
49 2.0 * table->CosTable( (M_PI/180.0) * 2.9 * t );
50 zpos = 4.0 + 2.0 * table->CosTable( (M_PI/180.0) * 4.9 * t );
51 videodriver->SetPilotView(xpos,ypos,zpos,angle_z,angle_y,angle_x);
52 }
使用方法很简单就是从设备指针获取lua上下文然后传入粒子配置脚本文件
获取粒子描述符
之后以其为参数从场景管理中获取粒子系统即可使用
够简洁吧
截图如下:
这是使用盖莫游戏引擎播放视频的例子
当前解码器为ffmpeg.
以后还会使用dxshow解码
播放代码如下:
1 #include <stdio.h>
2 #include <GEngine/Gaimo.hpp>
3
4 using namespace core;
5
6 bool state = 0;
7 //! 视频播放完成后的处理工作
8 inline void IsVideoEnded(){state = 1;}
9
10 using namespace core;
11 int main()
12 {
13 RefPtr<Device> device = InitDevice("视频播放");
14 //! 获取视频播放器指针
15 RefPtr<VideoPlayer> player = device->GetVideoPlayer();
16 //! 不处理音频的话那么视频将会是无声的O(∩_∩)O~
17 core::RefPtr<core::AudioDevice> audiodevice = device->GetAudioDevice();
18 uint16 number = audiodevice->GetAudioDeviceNumber();
19 engine_string audiodeviceinde = audiodevice->GetDeviceByIndex(1);
20 std::cout<<audiodevice->GetDeviceByIndex(1)<<std::endl;
21 std::cout<<audiodevice->GetDefaultDeviceName()<<std::endl;
22 std::cout<<"初始化音频设备"<<audiodevice->Init(audiodeviceinde,4,0)<<std::endl;
23 player->isstoped.connect( sigc::ptr_fun(&IsVideoEnded));
24 player->Play("..\\video//1.Mp4",Rectf(-1,-1,2,2));
25 player->SetVolume(1.0f);
26
27 BEGIN_LOOP(device)
28 player->Update();
29 BREAK_LOOP(state,1);
30 END_LOOP(device)
31 return 0;
32 }
33
可以看出当前代码使用sigc++作为插槽系统当播放结束的时候程序自动退出(当然可选sigslot)O(∩_∩)O~
截图如下:
这几天一直在做引擎的视频播放问题
1.3版本的引擎采用的是vlc视频处理库
使用vlc库其实还可以 就是外挂的插件太多了对我这样的懒人来说又不大愿意动手去编译本来
引擎的视频本来是打算采用,ffmpeg
最后考虑引擎当前是基于opengl的那就采用ffmpeg吧(最少这个也可以跨平台达到引擎设计的一贯要求)
视频播放我感觉还是有点难度的
这涉及图形,音频多线程问题
所加的线程无非就是音频线程解码线程系统处理线程
需要说明的就是
手头有3个ffmpeg版本(比较╮(╯_╰)╭)
a.包含了老版本的image_convert,avcodec_decode_audio
b.有 avcodec_decode_audio2,avcodec_decode_audio3,
c.是最新的sdk;FFmpeg-full-SDK-3.2
简单描述下:
image_convert 大致上相当于:sws_scale
而avcodec_decode_audio2基本等于avcodec_decode_audio(注意是基本而不是绝对等于)
不过还有一个比较新的avcodec_decode_audio3
如果采用的是ffplay那种方式的话不会涉及到多线程渲染
对于盖莫引擎来说 当前基于opengl,那么在这里使用opengl多线程是十分必要的
因为要在主线程渲染,在视频解码线程build图片
另外对于avpicture_get_size,avpicture_fill这些函数需要选择合适的PIX_FMT_RGB
要不然会出现图形错乱
此外视频和音频同步也是很重要的,引擎这里采用的是同步到视频的方法
至于音频的处理问题当然是盖莫音频引擎了现成的啊.
最后说下涉及到得ffmpeg版本问题
关于avcodec_decode_audio2
如果旧的视频代码采用的是avcodec_decode_audio工作正常的话
如果替换为较新版本的avcodec_decode_audio2话 这里可能会出现内存错误的问题
我的解决方案就是使用最新的ffmpeg解决它
这是当前盖莫游戏引擎设计的简单线程相关模块,比较简单
当然也就通俗易懂了
最基本的Mutex...
1 ////////////////////////////////////////////////////////
2 /// 定义引擎线程互斥
3 ////////////////////////////////////////////////////////
4 class Mutex : public Object
5 {
6 public:
7 Mutex(){}
8 virtual ~Mutex(){}
9 public:
10 ////////////////////////////////////////////////////
11 /// 锁线程
12 ////////////////////////////////////////////////////
13 virtual void Lock() = 0;
14 ////////////////////////////////////////////////////
15 /// 解线程
16 ////////////////////////////////////////////////////
17 virtual void UnLock() = 0;
18
19 DECLARE_OBJECT(Mutex)
20 };
方便的线程锁
1 ////////////////////////////////////////////////////////
2 /// 定义引擎线程基本锁
3 ////////////////////////////////////////////////////////
4 template<class Lock = RefPtr<Mutex> >
5 class MutexLock
6 {
7 public:
8 MutexLock(Lock ptr):mutex(ptr){mutex->Lock();}
9 ~MutexLock(){mutex->UnLock();}
10 private:
11 Lock mutex;
12 };
简单的更新和渲染同步类
1 template<class T,class Mutex,class Condition>
2 class ThreadSync
3 {
4 public:
5 double time; //! timestamp
6 float difftime;
7 int physics_frame;
8 int render_frame;
9 Mutex lock;
10 Condition physics_condition;
11 Condition render_condition;
12 };
至于具体的使用吗 期待盖莫2.1.1版本吧O(∩_∩)O~
摘要: 对于像游戏引擎的程序设计而言引擎的体系结构的重要性质是不言而喻的其中对象基类的设计也是很重要的主要的功能应该包含以下方面:1.对象类型识别2.对象的继承关系识别3.获取对象名字4.获取对象编号5.附带有智能指针6.当然必要的序列话作用也是必要的最基本的是对象引用计数类:
1 //////////////////////////////////////////////////...
阅读全文
应用程序正常初始化(0xc0000005)失败.请单击确定,终止应用程序是一个很常见的错误
常见的原因有指针初始化错误
不过因为是正常初始化失败所有错误原因可能源于全局的静态变量
对于具体的程序设计其原因还可能与涉及的其他动态库有关系O(∩_∩)O~
有时候我们需要typedef 一种模板
但是c++并没有直接的解决方案
也就是这样是不可行的.
typedef std::vector<T> myvector<T>;
间接的解决方式是:
(该代码源于盖莫游戏引擎代码)
1 #include <loki/flex/flex_string.h>
2 typedef flex_string<char> engine_string;
3 #include <loki/yasli/yasli_vector.h>
4 template<class T>
5 struct vector_typedef
6 {
7 typedef yasli::vector<T,std::allocator<T> > type;
8 };
9 template<class T>
10 struct list_typedef
11 {
12 typedef yasli::vector<T,std::allocator<T> > type;
13 };
使用的时候是这样的
list_typedef<int>::type v;
list_typedef<Vector3f>::typedef veclist;
...