|
首先来看使用lua语言改写上篇的粒子系统代码.
(不过鄙人的lua,python都很菜的,其原因就是一直没有练习的机会)
对于Lua,其扩展有luabind,tolua++,luaplus,前2着都与boost有关
所以就使用luaplus,简单些
开始了先上lua脚本代码(我把lua当成了c++,开始书写很不习惯,居然不知道lua中的逻辑符号是not and or 而非 !&& || 呵呵)
lua脚本:
-- 这是盖莫引擎中使用lua脚本的测试粒子
-- 定义粒子池粒子个数
max_particles = 2400
-- 定义粒子初始位置
particle_pos_x = 0.0
particle_pos_y = 0.0
particle_pos_z = 3.0
-- 定义重力加速度
gravity = 9.8
-- 定义粒子大小
particle_size = 0.8
-- 定义粒子寿命
particle_life = 8.2
-- 定义批处理粒子个数
batch_particles = 80
-- 定义粒子和地面之间的摩擦力
friction = 0.75
-- 定义粒子系统发射半径
fountain_radius = 1.6
-- 定义粒子范围半径
particle_r = (fountain_radius + particle_size/2)*(fountain_radius + particle_size/2)
-- 初始化随机种子
function InitRand()
math.randomseed(os.time());
end
-- 初始化粒子颜色red,green,blue
function InitColorRed(t)
return 0.7 + 0.3 * math.sin(0.34*t + 0.1);
end
function InitColorGreen(t)
return 0.6 + 0.4 * math.sin(0.63*t + 1.1);
end
function InitColorBlue(t)
return 0.6 + 0.4 * math.sin(0.91*t + 2.1);
end
-- 定义粒子速度
particle_vel = 8.0
-- 获取时间对应的速度值
function GetVelByTime(t)
return particle_vel*(0.8 + 0.1*(math.sin(0.5*t)+math.sin(0.31*t)));
end
-- 获取粒子初始速度
function InitZVel()
return 0.7 + (0.3/4096.0) * (math.random(1,4095));
end
-- 获取xy平面随机转角
function GetRandRotXY()
return (2.0*3.14159265/4096.0) * math.random(1,4095)
end
-- 获取粒子随机速度x分量
function InitXVel(t)
xy_angle = GetRandRotXY();
vt = GetVelByTime(t);
return 0.45 * math.cos(xy_angle)*vt;
end
-- 获取粒子随机速度y分量
function InitYVel(t)
xy_angle = GetRandRotXY();
vt = GetVelByTime(t);
return 0.45 * math.sin(xy_angle)*vt;
end
-- 定义更新粒子后的全局变量
new_life = 0;
new_xpos = 0;
new_ypos = 0;
new_zpos = 0;
new_xvel = 1;
new_yvel = 1;
new_zvel = 1;
-- 更新粒子状态
function UpdateParticles(life,xpos,ypos,zpos,xvel,yvel,zvel,dt)
-- 修正粒子生命
new_life = life - dt * (1.0 / particle_life);
-- 修正粒子速度
new_zvel = zvel - gravity *dt;
new_xpos = xpos + xvel*dt;
new_ypos = ypos + yvel*dt;
new_zpos = zpos + new_zvel*dt;
if new_zvel < 0.0 then
if new_xpos*new_xpos + new_ypos*new_ypos < particle_r and new_zpos < particle_pos_z + particle_size/2 then
new_zvel = -friction * new_zvel;
new_zpos = particle_pos_z + particle_size/2 + friction * (particle_pos_z + particle_size/2 - new_zpos);
-- 当粒子碰撞到地面应该跳起来
elseif new_zpos < particle_size/2 then
new_zvel = -friction * new_zvel;
new_zpos = particle_size/2 + friction * (particle_size/2 - new_zpos);
end
end
end
其关联的c++代码如下:
#include <GEngine/Main.hpp>
#include <luaplus/luaplus.h>
#define WIN_WIDTH 640
#define WIN_HEIGHT 480
//! 粒子纹理
static const unsigned char particle_texture[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x11, 0x22, 0x22, 0x11, 0x00, 0x00,
0x00, 0x11, 0x33, 0x88, 0x77, 0x33, 0x11, 0x00,
0x00, 0x22, 0x88, 0xff, 0xee, 0x77, 0x22, 0x00,
0x00, 0x22, 0x77, 0xee, 0xff, 0x88, 0x22, 0x00,
0x00, 0x11, 0x33, 0x77, 0x88, 0x33, 0x11, 0x00,
0x00, 0x00, 0x11, 0x33, 0x22, 0x11, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//! 粒子纹理大小
#define P_TEX_WIDTH 8
#define P_TEX_HEIGHT 8
////////////////////////////////////////////////////////////
/// 给出一个初始化粒子的方法
////////////////////////////////////////////////////////////
void G_CALL InitParticle(core: article* p,float t);
////////////////////////////////////////////////////////////
/// 更新粒子函数
////////////////////////////////////////////////////////////
void G_CALL UpdateParticle(core::Particle* p,float time);
////////////////////////////////////////////////////////////
/// 场景旋转和偏移
////////////////////////////////////////////////////////////
float TransForm(double t);
////////////////////////////////////////////////////////////
/// 构造纹理
////////////////////////////////////////////////////////////
void BuildTexture(GLuint& texture_id);
////////////////////////////////////////////////////////////
/// 渲染场景
////////////////////////////////////////////////////////////
void RenderScene();
core: evice* device = NULL;
libmath::TriTable* table = NULL;
LuaPlus: uaStateOwner *state = NULL;
////////////////////////////////////////////////////////////
/// 初始化luaplus
////////////////////////////////////////////////////////////
void InitLua(const char* lua)
{
state = new LuaPlus::LuaStateOwner;
// 载入Lua脚本
(*state)->DoFile(lua);
LuaPlus::LuaFunction<void> initrand(*state,"InitRand");
initrand();
}
void DeinitLua()
{
delete state;
}
////////////////////////////////////////////////////////////
/// 从脚本载入粒子描述数据
////////////////////////////////////////////////////////////
void LoadData(core::ParticleSystemDesc &desc);
int main(int argc, char **argv)
{
InitLua("particle.lua");
int i;
double t0, t;
core::VideoMode mode;
mode.width = WIN_WIDTH;
mode.height = WIN_HEIGHT;
device = core::InitDevice("盖莫引擎粒子系统",false,mode);
table = device->GetTriTable();
core::ParticleSystemDesc desc;
GLuint texture_id;
BuildTexture(texture_id);
desc.texture_id = texture_id;
desc.init_fn = &InitParticle;
desc.update_fn = &UpdateParticle;
LoadData(desc);
core::ParticleSystem* ps = device->GetParticleSystem(desc);
t0 = device->GetTime();
BEGIN_LOOP(device)
t = device->GetTime() - t0;
RenderScene();
float dt = TransForm(t);
ps->Render();
END_LOOP(device)
device->Close();
device->Drop();
DeinitLua();
return 0;
}
void BuildTexture(GLuint& texture_id)
{
glGenTextures( 1, &texture_id );
glBindTexture( GL_TEXTURE_2D, texture_id);
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, particle_texture);
}
////////////////////////////////////////////////////////////
/// 场景旋转和偏移
////////////////////////////////////////////////////////////
float TransForm(double t)
{
double xpos, ypos, zpos, angle_x, angle_y, angle_z;
static double t_old = 0.0;
float dt = (float)(t-t_old);
t_old = t;
angle_x = 90.0 - 10.0;
angle_y = 10.0 * sin( 0.3 * t );
angle_z = 10.0 * t;
glRotated( -angle_x, 1.0, 0.0, 0.0 );
glRotated( -angle_y, 0.0, 1.0, 0.0 );
glRotated( -angle_z, 0.0, 0.0, 1.0 );
xpos = 15.0 * sin( (M_PI/180.0) * angle_z ) +
2.0 * sin( (M_PI/180.0) * 3.1 * t );
ypos = -15.0 * cos( (M_PI/180.0) * angle_z ) +
2.0 * cos( (M_PI/180.0) * 2.9 * t );
zpos = 4.0 + 2.0 * cos( (M_PI/180.0) * 4.9 * t );
glTranslated( -xpos, -ypos, -zpos );
return dt;
}
void RenderScene()
{
glViewport( 0, 0, WIN_WIDTH,WIN_HEIGHT);
glClearColor( 0.1f, 0.1f, 0.1f, 1.0f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(65.0, 640.0/480.0, 1.0, 60.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
////////////////////////////////////////////////////////////
/// 给出一个初始化粒子的方法(t为粒子系统启动时间(单位:秒))
////////////////////////////////////////////////////////////
void G_CALL InitParticle(core::Particle* p,float t)
{
//! 初始化粒子位置位置
float xpos = (*state)->GetGlobal("particle_pos_x").GetFloat();
float ypos = (*state)->GetGlobal("particle_pos_y").GetFloat();
float zpos = (*state)->GetGlobal("particle_pos_z").GetFloat();
p->position = Vector3f(xpos,ypos,zpos);
//! 初始化粒子颜色
LuaPlus::LuaFunction<float> red(*state,"InitColorRed");
LuaPlus::LuaFunction<float> green(*state,"InitColorGreen");
LuaPlus::LuaFunction<float> blue(*state,"InitColorBlue");
p->color.red = red(t);
p->color.green = green(t);
p->color.blue = blue(t);
//! 初始化粒子初始速度
LuaPlus::LuaFunction<float> xvel(*state,"InitXVel");
LuaPlus::LuaFunction<float> yvel(*state,"InitYVel");
LuaPlus::LuaFunction<float> zvel(*state,"InitZVel");
p->velocity = Vector3f(xvel(t),yvel(t),zvel(t));
}
////////////////////////////////////////////////////////////
/// 更新粒子函数
////////////////////////////////////////////////////////////
void G_CALL UpdateParticle(core::Particle* p,float time)
{
LuaPlus::LuaFunction<void> update_fn(*state,"UpdateParticles");
float life = p->life;
float xpos = p->position.x;
float ypos = p->position.y;
float zpos = p->position.z;
float xvel = p->velocity.x;
float yvel = p->velocity.y;
float zvel = p->velocity.z;
update_fn(life,xpos,ypos,zpos,xvel,yvel,zvel,time);
//! 获取粒子的更新后数据
p->life = (*state)->GetGlobal("new_life").GetFloat();
p->position.x = (*state)->GetGlobal("new_xpos").GetFloat();
p->position.y = (*state)->GetGlobal("new_ypos").GetFloat();
p->position.z = (*state)->GetGlobal("new_zpos").GetFloat();
p->velocity.x = xvel;
p->velocity.y = yvel;
p->velocity.z = (*state)->GetGlobal("new_zvel").GetFloat();
}
////////////////////////////////////////////////////////////
/// 从脚本载入粒子描述数据
////////////////////////////////////////////////////////////
void LoadData(core::ParticleSystemDesc &desc)
{
desc.batch_particles = (*state)->GetGlobal("batch_particles").GetInteger();
desc.particle_size = (*state)->GetGlobal("particle_size").GetFloat();
desc.life_span = (*state)->GetGlobal("particle_life").GetFloat();
int max_particles = (*state)->GetGlobal("max_particles").GetInteger();
desc.particle_number = max_particles;
}
对应的贴图如下:

不过刚开始做的时候写lua的时候有点问题其结果变成了下图,看来要熟悉Lua只有多多练习

那么下一步要做的就是把lua集成进引擎中了 |
|