平民程序 - linghuye's blog

天下风云出我辈,一入江湖岁月催。皇图霸业谈笑中,不胜人生一场醉。提剑跨骑挥鬼雨,白骨如山鸟惊飞。尘事如潮人如水,只笑江湖几人回。

随笔 - 221, 文章 - 0, 评论 - 680, 引用 - 0
数据加载中……

Lua的长字符串合并算法

形如:
-- WARNING: bad code ahead!!
local buff = ""
for line in io.lines() do
 buff = buff .. line .. "\n"
end

1.每次buff = buff .. line .. "\n",导致新建一块内存,复制原buff内存,销毁原buff内存.
2.由于GC内存回收机制的的存在使得当字符串为几十k时,程序效率无法接受.

作如下算法:
function newStack ()
  return { "" }   -- starts with an empty string
end

-- 将每个字符串加入到stack table中
-- 规定table中的字符串从尾至前为从长度小的字符串到长度长的字符串.
-- 故,在加入一字符串时,检查其是否长于尾部的字符串,若长于前字符串,与之相加.
-- 接着再向前判断前方的元素,若相加后的字符串前元素,再如此向前.
function addString (stack, s)
  table.insert(stack, s)    -- 塞入尾部
  for i=table.getn(stack)-1, 1, -1 do
   if(string.len(stack[i+1])  >  string.len(stack[i])) then
    stack[i] = stack[i] .. table.remove(stack) -- 移出尾部元素,并相加.
   else
          break
      end
  end
end

-- 调用
local s = newStack()
for line in io.lines() do
  addString(s, line .. "\n")
end
s = toString(s)

Reference:
Programming in lua

posted @ 2006-01-15 15:20 linghuye 阅读(2467) | 评论 (1)编辑 收藏

LuaShell

无聊的时候写了个执行Lua脚本的Shell Context Menu.
1.使用内含的RegisterShellMenu.bat文件进行Shell DLL插件注册.
2.任意选择一个.lua后缀文件,在其右键单击快捷菜单中选择Run Lua Script命令.
3.有语法错误的会报错,正确执行的会输出脚本中所有的print函数调用到对话框上。
4.支持到luaopen_base,luaopen_table,luaopen_string,luaopen_math,luaopen_io,不能把dll放到中文目录下.
5.用来做一些方便的Lua脚本Widget不错.
6.1.20:加入lua扩展支持:Windows API,Zip,COM,odbc,mysql,wxWidgets GUI.
7.1.22加入OpenGL支持.
-- Load package
function LoadPackage(pname, fname)
    local gf, err 
= loadlib(pname, fname or ("luaopen_" .. pname));
    
if(gf) then gf();
    
else error(err) end;
end

--**************************************************************
LoadPackage(
"zip");

local zfile, err 
= zip.open('C:\\view.zip')
for file in zfile:files() do
    print(file.filename);
end
zfile:close();

-- *************************************************************
LoadPackage(
"odbc""luaopen_luasqlodbc");
local env 
= assert(luasql.odbc());
local conn 
= assert(env:connect("nwind"));
local cur 
= conn:execute("SELECT * FROM Customers");

if(cur) then
    print(table.concat(cur:getcolnames(), 
"\t"));
    
    local data 
= {};
    cur:fetch(data);
    print(table.concat(data, 
"\t"));
end

cur:close();
conn:close();
env:close();

-- *************************************************************
LoadPackage(
"mysql""luaopen_luasqlmysql");
local env 
= assert(luasql.mysql());
local conn 
= assert(env:connect("wow""linghuye""yzwzsq"));
local cur 
= conn:execute("SELECT * FROM creature_names");

if(cur) then
    print(table.concat(cur:getcolnames(), 
"\t"));
    
    local data 
= {};
    cur:fetch(data);
    print(table.concat(data, 
"\t"));
end

cur:close();
conn:close();
env:close();

-- *************************************************************
LoadPackage(
"lfs");
local attrs 
= lfs.attributes("C:\\view.zip");
print(attrs.size);
print(lfs.currentdir());

http://www.cnitblog.com/Files/linghuye/LuaShell.7z.rar

posted @ 2006-01-07 19:50 linghuye 阅读(919) | 评论 (0)编辑 收藏

2005年末随想

今年对自己的评价是,有所得,有所失.
虽然所计划的事情大都没能达到预期的成果,但确实都一一地做过了,在图形学上所作的研究和进步也让自己很满意,谋事在人,成事在天,如是而已.
也甚怀疑自己是否太过追求技术,弄得喜怒哀乐之心情似乎都随技术而变.或许明年,应该象高中时的理想而追求那平静恬淡的生活,不要对自己要求太高,太过苛刻,要多玩游戏,多看好莱坞肥皂剧,在这种平淡的生活中持续对技术的绵泊的追求.
看来,图形学和游戏技术是够我研究一辈子的了,纯粹的程序技术或语言或思想总是有限的,起初的深奥,现在看也不过是如此,构不成一个人认知的极限,还是数学这个东西最能刺激我.
2005年过去了,我很怀念她.

posted @ 2005-12-31 15:51 linghuye 阅读(412) | 评论 (1)编辑 收藏

无缝世界场景加载的解决方案研究

1.每帧评估周围MapArea的可见度,对即将可见的区域送入预加载线程逻辑,对必须可见的区域送入即时加载模块.
2.必须加载2*2,进入3/4距离处开始预加载,退出1距离处卸载,保证最大加载量为3*3.

a.DX是有多线程支持,OpenGL渲染RC与线程相关,跨线程加载使用图形资源,如何解决?
b.遇到更复杂的逻辑时,如何处理.
c.是否要预加载全部,还是分Terrain,Model,Wmo加载.
But it is just a design question.

posted @ 2005-12-31 11:44 linghuye 阅读(1991) | 评论 (0)编辑 收藏

罕见却实用的C语言技巧

1.SOLID的基本vector类型为:   typedef DT_Scalar DT_Vector3[3];
很有意思地定义DT_Vector3为一个三元组,这样:
a.DT_Vector3声明变量时,可以定义三元组.
b.DT_Vector3作为函数参数时,却可以直接传入float指针进行调用.而在C++中一般用类型强转运算符实现.

2. t_MyStruct p[10] = { 0 }; t_MyStruct 是个c结构, = {0},可以用0初始化*整个*结构数组,很好用.

posted @ 2005-12-31 11:26 linghuye 阅读(1151) | 评论 (0)编辑 收藏

3D人物模型在TriangleMesh环境中行走跳跃的碰撞行为反应

How general games solve this question?So difficult.

ODE作的是刚体动力学,似乎不适合作解决方案.

1.The easiest way to handle a collision is to simply stop and not allow the move when a collision is detected. On the other hand - that is not how the professionals do is it? No, we want fancy collision response like sliding along the walls, automatically climbing stairs and automatically bumping over smaller obstacles on the ground.

2.The penetration depth of a pair of intersecting objects is the shortest vector over which one object needs to be translated in order to bring the pair in touching contact.

3.Responses are managed in response tables. To each object on which a response is defined in a response table a response class is assigned. Responses are defined per pair of response classes, rather than per pair of objects. So, the response for a pair of objects is the response defined for their respective response classes.

1.Move our sphere as close as possible to the triangle we’re colliding with.
Lets call this position for “newPosition”.

2. Calculate the sliding plane based on this new position.

3. Project the original velocity vector to the sliding plane to get a new
destination.

4.Make a new velocity vector by subtracting the polygon intersection
point from the new destination point.

5.Recursively call the entire collision detection routine with the new position
and the new velocity vector.


Reference:
http://www.peroxide.dk/download/tutorials/tut10/pxdtut10.html
http://www.win.tue.nl/~gino/solid/gdc2001depth.pdf
http://www.gamasutra.com/features/20000330/bobic_01.htm
http://people.netfarm.it/~guyver1/Didattica/RTM/Lezioni/Lezione6/CollisionDetection_file/frame.html#slide0067.html

posted @ 2005-12-28 17:08 linghuye 阅读(2558) | 评论 (5)编辑 收藏

PolygonSoup碰撞检测学习笔记

解决PolygonSoup碰撞检测的成熟方案是使用层次BV树,根据BV的不同衍生出:AABB,OBB,K-dop三种方案.
在内存使用上: AABB -> OBB -> K-dop递增.在效率上则尚无定论,根据具体的应用环境不同而不同.

Opcode: 开源,完全免费,采用AABB树构造,内存耗用很小,支持复杂模型,起初想使用它,但发现其,基本上没有文档,Sample,1.3版本接口变动巨大,且无文档,自2003年来再无更新,最致命的是不支持Instance transform的Scale,AABBCollider没有Transform支持,而且是在看代码时发现的,吐血.主要设计目标是少的内存耗用,但速度也很快.为ODE,Tokamak,Crystal Space所用.

RAPID: 开源,免费,采用OBB构造,内存耗用巨大,学院派设计,最倒霉的库,因为其他每个库都拿它作比较,都说比它快.

SOLID: GPL开源,商业软件,采用AABB树构造,2005.4月出3.5版本,效率不错,内存耗用中等,在后面4.0会支持AABB数据压缩,有文档,接口简单,代码清晰.支持复杂模型,支持Instance transform的Scale,甚至支持各向不等缩放,支持Penetration Depth计算,cool.作者Gino van den Bergen是3D碰撞研究专家,著有:Collision Detection in Interactive 3D Environments一书,有e版.逻辑顺畅地集成入DM,效果不错,满足使用要求.不过其IndexBuffer是unsigned int,Matrix是DX风格的,但代码很清晰,很容易定制.
SOLID有个严重的Bug,必须确保DT_GetCommonPoint,DT_GetPenDepth,DT_GetClosestPair在检测Complex和Convex对象时,第一个参数必须是Complex对象,否则崩溃.因为SOLID的double dispatch实现有问题,不完整,没有Convex + Complex顺序的对应函数.

QuickCD: 开源,免费,K-dop树构造.

ColDet,支持复杂模型,也不支持Instance Transform的Scale.

Reference:
http://www.codercorner.com/Opcode.htm
http://www.dtecta.com/
http://www.cs.unc.edu/~geom/OBB/OBBT.html
http://www.ams.sunysb.edu/~jklosow/quickcd/QuickCD.html
http://photoneffect.com/coldet/
http://www.merl.com/projects/vclip/
http://www.q12.org/ode/ode.html

void DmModel::SetBoundPolygonSoup(uint32 nPolygonSoupVertices, vec3_type* pVertices, uint32 nTrianglePrims, uint16* pTrianglePrims)
{    
    ASSERT(m_hSolidShape 
== NULL);
    
    
if(nTrianglePrims == 0return;
    
if(nPolygonSoupVertices == 0return;
            
    
// Save polygon soup data for collision test!
    m_pPolygonSoupVertices = new vec3_type[nPolygonSoupVertices];
    memcpy(m_pPolygonSoupVertices, pVertices, 
sizeof(vec3_type) * nPolygonSoupVertices);
    
    
// Build 
    DT_VertexBaseHandle hVertexBase = DT_NewVertexBase(m_pPolygonSoupVertices, 0);
    m_hSolidShape 
= DT_NewComplexShape(hVertexBase);
    m_hSolidVertexBase 
= hVertexBase;
        
    
// Define mesh triangles
    for(uint32 i = 0; i < nTrianglePrims; i += 3)
    
{    
        DT_VertexIndices(
3, pTrianglePrims + i);
    }

    
    
// End it
    DT_EndComplexShape();
}


void DmModelInstanceNode::BuildPhysics()
{    
    
// Setup Phisic stuffs
    DT_ShapeHandle hShape = (DT_ShapeHandle)m_pRefModelInstance->m_pRefModel->m_hSolidShape;
    
if(hShape)
    
{    
        DT_ObjectHandle hObject 
= DT_CreateObject(NULL, hShape);
        DM_SetMatrixf(hObject, m_matTransform);
        m_hSolidObject 
= hObject;
    }

}


void DmGameCreature::BuildPhysics()
{    
    ASSERT(m_hSolidObject 
== NULL);
    
    vec3_type vMin, vMax;
    getBoundBox(vMin, vMax);
    DT_ShapeHandle hShape 
= DT_NewBox(vMax.x - vMin.x, vMax.y - vMin.y, vMax.z - vMin.z);
    DT_ObjectHandle hObject 
= DT_CreateObject(NULL, hShape);
    
    m_hSolidShape 
= hShape;
    m_hSolidObject 
= hObject;
}


bool DmModelInstanceNode::TestCollision(HANDLE hSolidObject)
{    
    
if(!m_hSolidObject) return false;
    
    DT_ObjectHandle hTestObject 
= (DT_ObjectHandle)hSolidObject;
    DT_ObjectHandle hThisObject 
= (DT_ObjectHandle)m_hSolidObject;
        
    DT_Vector3 v;
    
return (DT_GetCommonPoint(hThisObject, hTestObject, v) != 0);
}

posted @ 2005-12-26 22:59 linghuye 阅读(2891) | 评论 (22)编辑 收藏

Clip segment with OpenGL near plane

 

// Clip with near Z plane
// a,b is the vertex after opengl projection, that is M * v
static bool ClipLine(vec4_type& a, vec4_type& b)
{    
    
// -w <= z <= w
    bool aClip = (a.z < -a.w);
    
bool bClip = (b.z < -b.w);
    
if(!(aClip  ||  bClip))      return true;
    
else if(aClip  &&  bClip) return false;

    
// near plane
    if(aClip)
    
{    
        
const float dx = b.x - a.x;
        
const float dy = b.y - a.y;
        
const float dz = b.z - a.z;
        
const float dw = b.w - a.w;
        
        
const float t = -(a.z + a.w) / (dw + dz);
        a.x 
+= dx * t;
        a.y 
+= dy * t;
        a.z 
+= dz * t;
        a.w 
+= dw * t;
    }
    
    
else if(bClip)
    
{    
        
const float dx = a.x - b.x;
        
const float dy = a.y - b.y;
        
const float dz = a.z - b.z;
        
const float dw = a.w - b.w;
        
        
const float t = -(b.z + b.w) / (dw + dz);
        b.x 
+= dx * t;
        b.y 
+= dy * t;
        b.z 
+= dz * t;
        b.w 
+= dw * t;
    }

    
    
return true;
}

怪不得DX要把z映射到[0,1],计算简洁多了.

posted @ 2005-12-22 14:55 linghuye 阅读(588) | 评论 (0)编辑 收藏

程序员和美女

网易最近搞了个游戏业界丽人行,很好,本人十分的喜欢.游戏公司里的美女是挺多的(当然人多了出几个美女,根据数学上的统计分布而言是很正常的概率).
不过就我见到的程序的女友都算不上是美女,所以基本上我认为程序和美女是没啥缘分的.我不喜欢缘分这个词,因为人们通常把它当褒义词来用,我一般喜欢说Destiny,很中性,很有逻辑,但有时我更喜欢给它加上the fucking这个形容词,以表达我对它的无知.
而美女肯定是有男友的,虽则古有名训,名花虽有主,我来松松土,但大部分程序员获知这个条件判断后,再评估一下自己民工式的邋遢,马上很有逻辑的if,else,then了,于是闭关修炼,技术噌噌地往上涨,没有女友可以show,也只好show自己的场景渲染效果图了,虽然很可悲,却也聊剩于无,间或解嘲自己几句the fucking而已.
所以我总是在想,在一个美女有没有男友这个重大的0/1是非问题上,信息共享是多么的重要啊,我们应该致力于解决这个问题,相信有很多程序员愿意脱掉他的袜子表示赞成,也相信有很多女同胞愿意把我当耶稣供到那个流血的十字架上去.
图形学的最高境界是什么,我坚定不疑地相信是渲染一个真正的有灵气的美女,不是模型的那种,得根据自然演化算法,模拟自然的养成规律渲染出来的,搞个开发库,来个glHint(GL_BEAUTY, GL_NICEST)之类的,cool!
美女之美,我所欲也,程序之美亦我所欲也,近程序而远美女者,盖不得之也.

posted @ 2005-12-21 00:06 linghuye 阅读(879) | 评论 (2)编辑 收藏

纹理空间方案定义

1.载入的纹理, 以0.0f处为正置图像的顶端, 1.0f为图像的底端.
2.放弃OpenGL的数学坐标系的纹理空间思维,以同质的Window DC坐标系为纹理空间思维习惯.
3.凡读取PixelBuffer, FrameBuffer中的数据来制作纹理的OpenGL函数,总是从数学坐标系原点,从Frame的底部向上方扫描,形成纹理.
4.假设读取的图形数据(也就是传入glTexImage2D的pixels参数)是从上至下的,glTexImage2D将按从下至上的顺序写入Texture的内存区域,而glTexCoords的0,0在左下点,最终的结果等于图像是从上到下画出的.
  推论1:即Frame底部对应要形成的纹理坐标为0.0f,顶部为1.0.
  推论2:要想得到正确的1中的纹理,Frame中的图像应该是倒置的.

posted @ 2005-12-14 15:44 linghuye 阅读(577) | 评论 (0)编辑 收藏

仅列出标题
共23页: First 9 10 11 12 13 14 15 16 17 Last