2009-08-30

Problem of OnReceive of CSocket

以前用过CSocket这个类,主要是考虑可以用CSocketFile进行串行化数据,比较方便。这次写的时候竟然出了几个问题:

1. 网上下载了chatter例程,用VC6.0编译后运行,没有任何问题;切换到VS2008下,编译没有问题,运行时,发现OnReceive时而触发,时而不触发。到网上查了查,同样问题的人很多,看来是个老大难了。后来加上OnReceive结束之后,调用 AsyncSelect( FD_READFD_WRITE ),解决了此问题。几乎弄了一整天,跟http://www.ecjtu.org/forum/read.php?tid-19062.html这位仁兄情况几乎相同;

2. 其实,刚开始我就发现了这个解决方案,但是我一直觉得OnReceive函数由系统框架来调用,不应该需要施加“外力”影响。国外很多人说是OnReceive函数里面调用了多次Receive引发的。如果真是这样,另外一个问题就是CArchieve的load动作跟CSocket的Receive关系是什么?

3. CArchieve的Read和Write函数可以读写缓冲区,我原来一直用“>>”和“<<"符号一个一个地写DWORD,晕,效率很低。

结论:好像用CSocketFile来发送、接受数据有点得不偿失,问题很多,实际也没有带来很多好处。不如直接用CAsyncSocket类呢。

2009-08-29

Study of photography

扫盲一下照相相关的几个术语,这个解释很到位。

光圈

光圈的功能就如同我们人类眼睛的虹蟆,主要用来调整数码相机的进光量,一般以f/2、F2、1:2来表示,举例来说:f/2表示光圈的大小为镜头直径的1/2 ,而f/8 则表示光圈为镜头直径的1/8而已,所以较小的f值表示较大的光圈,一般镜头上的标示会以数码相机的最大光圈值表示,变焦镜头若有显示2个f值,则表示此相机最大及最小的光圈。光圈除了可控制光线的明暗外,对于图像的景深也是会有影响。景深是影响拍摄主体与背景之间清晰程度的关键,也可以说是图像的锐利度,大光圈时拍摄出来的图像锐利度较小,小光圈拍摄则较大。从数码上而言,光圈数值越小表示光圈越大,也代表透光的孔径大、透光量大,不论要拍摄快速移动的物体或在昏暗的空间拍摄,都很方便。而且光圈也决定了画面的景深(锐利度),如果是设定为大光圈,那么画面中除了主题清晰,其它景物都会呈现模糊、柔美的感觉。时下多数数码相机的光圈值最大都在2.8左右。

景深

在进行拍摄时,调节相机镜头,使距离相机一定距离的景物清晰成像的过程,叫做对焦,那个景物所在的点,称为对焦点,因为"清晰"并不是一种绝对的概念,所以,对焦点前(靠近相机)、后一定距离内的景物的成像都可以是清晰的,这个前后范围的总和,就叫做景深,意思是只要在这个范围之内的景物,都能清楚地拍摄到。景深的大小,首先与镜头焦距有关,焦距长的镜头,景深小,焦距短的镜头景深大。其次,景深与光圈有关,光圈越小(数值越大,例如f16的光圈比f11的光圈小),景深就越大;光圈越大(数值越小,例如f2.8的光圈大于f5.6)景深就越小。其次,前景深小于后后景深,也就是说,精确对焦之后,对焦点前面只有很短一点距离内的景物能清晰成像,而对焦点后面很长一段距离内的景物,都是清晰的。

F值

就是光圈值
光圈是一个用来控制光线透过镜头,进入机身内感光面的光量的装置,它通常是在镜头内。表达光圈大小我们是用f值。

光圈f值=镜头的焦距/镜头口径的直径

单反相机

单反就是指单镜头反光,即SLR(Single Lens Reflex)。在这种系统中,反光镜和棱镜的独到设计使得摄影者可以从取景器中直接观察到通过镜头的影像。单镜头反光照相机的构造图中可以看到,光线透过镜头到达反光镜后,折射到上面的对焦屏并结成影像,透过接目镜和五棱镜,我们可以在观景窗中看到外面的景物。拍摄时,当按下快门钮,反光镜便会往上弹起,软片前面的快门幕帘便同时打开,通过镜头的光线(影像)便投影到软片上使胶片感光,尔后反光镜便立即恢复原状,观景窗中再次可以看到影像。单镜头反光相机的这种构造,确定了它是完全透过镜头对焦拍摄的,它能使观景窗中所看到的影像和胶片上永远一样,它的取景范围和实际拍摄范围基本上一致,消除了旁轴平视取景照相机的视差现象,从学习摄影的角度来看,十分有利于直观地取景构图。 单镜头反光相机还有一个很大的特点就是可以交换不同规格的镜头。

2009-08-26

Hong Kong Tramways

香港的电车被戏称为“叮铛车”,据我的理解,这个名字有两层含义,一则电车走在铁轨上发出的叮当的声音,另一个方面是电车走得慢,比起其他公交的风驰电掣,电车就像是自行车的速度。电车没有空调,但是价格便宜,2港元,双层结构还可以观光。

昨天晚上坐电车,发现了电车另外一个问题,可靠性不高,要是一辆电车坏了,占住了轨道,其他的全被阻塞。照片是10多辆电车阻塞了的景象,呵呵。



wiki:香港电车是指香港的一个路面电车系统,来往香港岛北部的筲箕湾及坚尼地城,另有环形支线来往跑马地,每日平均可接载24万人次的乘客,是全球现存唯一全数采用双层电车的电车系统。香港电车在1904年投入服务,是香港最历史悠久的交通工具之一。香港电车除了是港岛北居民的主要交通工具之一,还是外地旅客的著名景点之一。经历百年来的变迁,香港电车现由九龙仓集团有限公司及威立雅运输集团合营的香港电车有限公司经营。

2009-08-25

Radiosity Rendering Algorithm.

辐射度算法是一种全局光照算法。基本思路如下:
1. 首先,根据外部光源,得到一幅直接光照生成的光照图。
2. 然后,以此光照图+外部光源为光源,对场景进行辐射。
3. 迭代2过程。

Hugo Elias 的解释非常形象,以场景中的每个面片看到的“场景”为光源,计算此面片的亮度。

算法伪代码:

load scene

divide each surface into roughly equal sized patches

initialise_patches:
for each Patch in the scene
if this patch is a light then
patch.emmision = some amount of light
else
patch.emmision = black
end if
patch.excident = patch.emmision
end Patch loop

Passes_Loop:each patch collects light from the scene
for each Patch in the scene
render the scene from the point of view of this patch
patch.incident = sum of incident light in rendering
end Patch loop

calculate excident light from each patch:
for each Patch in the scene
I = patch.incident
R = patch.reflectance
E = patch.emmision
patch.excident = (I*R) + E
end Patch loop

Have we done enough passes?
if not then goto Passes_Loop

代码解释

initialize patches:(初始化面片)
一开始,所有的面片都是黑的,除了那些能自身辐射出光线的面片。因此,那些能辐射光线的面片的出射光强的初始值应被初始化伪它的辐射光强。其他面片的辐射光强都应为0。

Passes Loop(遍历循环):
代码多次重复这个循环直到场景有了可接受的光照效果。每次循环之后,也就多模拟了一次光在场景中的反射。

each patch collects light from the scene(每个面片从场景中收集光强)
如果我之前在文章中解释的那样,每个面片都被它能够看见的其他面片照亮。要达到这个目的,可以简单地把把场景渲染到面片的视角,然后把它所看的光强相加。我将在下一小节更详细地解释这一步。

calculate excident light from each patch(为每个面片计算出射光强):
计算出有多少光强抵达面片之后,我们现在可以计算出有多少光强离开面片(被反射)。
这个过程必须被循环多次以达到一个好的效果。如果渲染器还需要一个循环,我们就调转到标记"Passes Loop"。

Reference:
1. English:http://freespace.virgin.net/hugo.elias/radiosity/radiosity.htm
2. Chinese:http://dev.gameres.com/Program/Visual/3D/Radiosity_Translation.htm

2009-08-24

Illumination Tech of CG.

Direct Illumination Problems and Advantages

Direct Illumination is a term that covers the principal lighting methods used by old school rendering engines such as 3D Studio and POV. A scene consists of two types of entity: Objects and Lights. Lights cast light onto Objects, unless there is another Object in the way, in which case a shadow is left behind.

Ray Tracing:
- Can render both mathematically described objects and polygons
- Allows you to do some cool volumetric effects
- Slow
- Very sharp shadows and reflections

Shadow Volumes:
- Can be modified to render soft shadows (very tricky)
- Tricky to implement
- Very sharp shadows
- Polygons only

Z-Buffer:
- Easy to implement
- Fast (real-time)
- Sharp shadows with aliasing problems


Global Illumination Problems and Advantages

Images produced by global illumination methods can look very convincing indeed; in a league of their own, leaving old skool renderers to churn out sad cartoons. But, and it's a big 'but': 'BUT!' they are slower. Just as once you may have left your ray tracer all day, and come back to be thrilled by the image it produced, you will be doing the same here.

Radiosity:
- Very realistic lighting for diffuse surfaces
- Conceptually simple and easy to implement
- Easy to optimise with 3D hardware

- Slow
- Does not handle point sources well - nor shiny surfaces
- Always over complicated and poorly explained in books


Monte Carlo Method:
- Very, very good results.
- Can simulate pretty well any optical phenomenon

- Slow
- Slightly difficult
- Requires some cleverness to optimise
- Always over complicated and poorly explained in books

Reference:http://freespace.virgin.net/hugo.elias/radiosity/radiosity.htm

2009-08-23

Food of HKU.

刚来HKU的时候,头三天的时候,吃了食堂的东西,一边吃一赞,貌似很丰盛。一个星期后,开始徘徊在食堂给出的菜单前面,10秒钟点好菜;现在三个星期,开始迷惘在菜单前面,1分钟才能决定吃什么。

香港的饮食太清淡,实在是有些受不了。抛开甜不说,盐也不够,酱油没有,辣椒,做梦才有。现在最想吃的就两样:红汤酸菜鱼+红烧仔鸡,想着就流口水。


有图为证:



无意间看到美国的一个博友描写美国食堂的情况,看来这是个全球问题。呵呵。

水调歌头 食堂诉苦

包子几时有,汉堡不新鲜。
我问pizza hut,为什么弄这么咸?
我欲乘船归去,又恐老板不许,上学真叫烦,
深夜梦烙饼,馋在卫生间。

2009-08-22

Study of Computer Graphic.


Reference: 3D Games - Real time rendering and software technology Volume I.
1. 仿射变换(affine transformations):旋转、缩放、平移、错切变换;
2. 法线:向量叉积;
向量夹角:点积(V.W>0,θ<90;v.w=0,θ=90...);
投影:点积(v单位向量,w对v进行投影:|x|=v.w)。
3. 双线性插值(bi-linear interpolation):顶点-->边;边-->多边形内部;
4. 模型表示方法:
  • polygonal--ploygon or triangle(Problem:continuous LOD is hard, avoiding popping).
  • bi-cubic parametric patches(双三次曲面)= curved quadrilaterals(曲面四边形)(Problem:smoothness between quadrilaterals,inapposite for complex object. BUT easy for LOD).
  • constructive solid geometry,CSG(intersection,union,subtraction).
  • spatial subdivision techniques(空间细分技术).
  • implicit representation(隐式表示).
 5. Economy of mesh represatation
  • Triangle chains
  • LOD
6.Terrain modeling
  • fractal geometry(分形几何学)
  • terrain LOD: triangle bintree(三角二叉树)
7. Curve and curved face
  • Bezier curve:
    • 平行六面体
    • 四个control point Pi(i=0,1,2,3);
    • 基函数Bi为(1-u)^3,3u(1-u)^2,3u^2(1-u),u^3; 曲线Q(u)= ∑PiBi.
    • Disadvantage: global effection when manipulating one control point; smoothness of multi Bezier connection;
  • B样条:任意个控制点,任意4个一组;内在连续性;局部性(任意个控制点改变,影响4个曲线段)。
  • 非均匀有理B样条(NURBS)
8. Rendering
  • 视见体裁剪;
  • 局部反射模型:计算顶点的光强;明暗算法:由定点得到面片的每一点的光强;
  • 局部反射模型:Phong—反射光=环境光+漫反射+镜面反射,这个是Phong光照模型
  • 明暗算法:
    • Gouraud—Ip=interpolation(Ia,Ib),对顶点a,b的亮度进行插值,不会有高光出现;
    • Phong—对法向插值,得到插值点的Np,再求亮度。这个是Phong着色模型
    • 一般Gouraud球漫反射分量,Phong求镜面发射分量。
  • 隐面剔除:Z缓冲—在搜索的同时,将Z值最小的像素写入Frame Buffer;需要x*y*n大小。
9. texture mapping
  • function
    • 1)common color of pixel: color of texture与局部反射模型计算得到的漫反射系数相乘;
    • 2)specular color: 进行环境映射贴图,避免完全光线跟踪;沿着反射后的视见向量,在场景中寻找纹理,可倒映出环境中有光泽的物体;
    • 3)凹凸纹理(bump mapping): normal vector perturbation;
    • 4)transparent:控制透明物体的不透明程度;
  • bitmap-->planar, cylinder, sphere-->object

2009-08-21

Study about Fourier Transform

Reference:http://blog.csdn.net/dznlong/archive/2008/04/08/2261150%20.aspx

1.傅里叶变换是一种逼近表示,而非精确表示;
2.选用正弦、余弦波形表示是否唯一?不是,只是为了方便。
3. 傅里叶变换的四种分类:
非周期性连续信号 --- 傅立叶变换(Fourier Transform)
周期性连续信号 --- 傅立叶级数(Fourier Series)
非周期性离散信号 --- 离散时域傅立叶变换(Discrete Time Fourier Transform)
周期性离散信号 --- 离散傅立叶变换(Discrete Fourier Transform)
4. 傅立叶变换是针对正无穷大和负无穷大的信号,即信号的的长度是无穷大的. 非无穷怎么办?扩展即可。
5. 傅里叶变换实质:将信号分解为若干个离散的、不同频率的正弦、余弦信号分量。

2009-08-14

Derivation of AFX

用MS的编程也有n多年,今天突然想起afx是什么意思,网上一查,如下:

是MFC小组早期的代号,AFX,当时是指applecation freamwork,如果你的程序用到了MFC,那这个头文件是一定要包含的。

Microsoft的程序员开始试图将C++和面向对象的编程概念应用于Windows编程中,经编写出一个可以使windows编程工作更加简便的应用程序框架。他们把这个应用程序框架叫做AFX(AFX这个词来源于Application FrameWork,但奇怪的是这个词组中并没有包含"X"这个字母)。直到今天,AFX小组早已不存在了,AFX这个名称也于1994年初不再使用,但在Visual C++和MFC中,AFX的影子却随处可见,很多全局函数、结构和宏的标识符都被加上了AFX的前缀。

在九十年代初的时候OO被炒得很热,许多人以为OO是无所不能的.微软也这么认为,所以他们想搞出一套类库来封装全部的OS特性,使得程序可以在WINDOWS,OS/2,X等等任何的GUI系统上运行,结果可想而知,这个东西当然是没做出来到94年微软放弃了AFX,把AFX中已经完工的部分做了一点改进,形成了MFC,至今MFC还有LINUX版本,也算是AFX计划的一点残留吧.

2009-08-10

HK Victoria Peak.

太平山就在香港大学的后面。本着锻炼身体的目的,我和leo在下午5:00做出发爬山。一出港大后,一个很陡的坡就给了我一个下马威。恩,好长时间没有锻炼身体了,一路气喘吁吁地往上爬,中间还休息了n次。估计一个小时后,到了山顶。
山顶游人如织,呵呵,可以俯瞰香港中环及维多利亚港。不过,天还没有全黑,所以没有看到夜景。而正好没有相机,也不打算等了,到山顶的McDonald吃了一点,开始下山。知道7:30才到港大,历时二个多小时。
只能用手机随便拍了照片。期待发工资,然后去买单反,O(∩_∩)O~

0x5f3759df, Magic?

昨天无意看到网上有一个开平方根的快速算法,其实是很老的一个帖子,大约在2000年出现的:
---------------------------------------------------
有人在Quake III的源代码里面发现这么一段用来求平方根的代码:

/*================SquareRootFloat================*/

float SquareRootFloat(float number) {
long i;
float x, y;
const float f = 1.5F;
x = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 ); //注意这一行
y = * ( float * ) &i;
y = y * ( f - ( x * y * y ) );
y = y * ( f - ( x * y * y ) );
return number * y;
}

0x5f3759df? 这是个什么东西? 学过数值分析就知道,算法里面求平方根一般采用
的是无限逼近的方法,比如牛顿迭代法,抱歉当年我数值分析学的太烂,也讲不清楚
。简单来说比如求5的平方根,选一个猜测值比如2,那么我们可以这么算

5/2 = 2.5; 2.5+2/2 = 2.25; 5/2.25 = xxx; 2.25+xxx/2 = xxxx ...
这样反复迭代下去,结果必定收敛于sqrt(5),没错,一般的求平方根都是这么算的
。而卡马克的不同之处在于,他选择了一个神秘的猜测值0x5f3759df作为起始,使得
整个逼近过程收敛速度暴涨,对于Quake III所要求的精度10的负三次方,只需要一
次迭代就能够得到结果。

好吧,如果这还不算牛b,接着看。

普渡大学的数学家Chris Lomont看了以后觉得有趣,决定要研究一下卡马克弄出来的
这个猜测值有什么奥秘。Lomont也是个牛人,在精心研究之后从理论上也推导出一个
最佳猜测值,和卡马克的数字非常接近, 0x5f37642f。卡马克真牛,他是外星人吗?


传奇并没有在这里结束。Lomont计算出结果以后非常满意,于是拿自己计算出的起始
值和卡马克的神秘数字做比赛,看看谁的数字能够更快更精确的求得平方根。结果是
卡马克赢了... 谁也不知道卡马克是怎么找到这个数字的。

最后Lomont怒了,采用暴力方法一个数字一个数字试过来,终于找到一个比卡马克数
字要好上那么一丁点的数字,虽然实际上这两个数字所产生的结果非常近似,这个暴
力得出的数字是0x5f375a86。

Lomont为此写下一篇论文,"Fast Inverse Square Root"。
-------------------------------------------------

于是我写了一段程序来验证,程序参考了Lomont的程序,http://www.lomont.org/Math/Papers/2003/InvSqrtCode.zip但是号称快四倍的神秘算法,我一直未能得到很多的结果,程序表明两个算法性能差不多。奇怪中!

---------------------------------------------------------
float InvSqrtExact(float x)
{
return (float)(1.0/sqrt(x));
} // InvSqrtExact

/// "Carmack" version of fast inverse sqrt,
/// based on Newton method, 1 iteration
float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1); // hidden initial guess, fast
x = *(float*)&i;
x = x*(1.5f-xhalf*x*x);
// x = x*(1.5f-xhalf*x*x); // add this in for added precision, or many more...
return x;
} // InvSqrt

/// Chris Lomont version of fast inverse sqrt,
/// based on Newton method, 1 iteration, more accurate
float InvSqrt_Lomont(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f375a86 - (i>>1); // hidden initial guess, fast - LOMONT
x = *(float*)&i;
x = x*(1.5f-xhalf*x*x);
// x = x*(1.5f-xhalf*x*x); // add this in for added precision, or many more...
return x;
} // InvSqrt_Lomont


/// given a function, a number of passes, and a value to test, do it
void TimeFunction(float (*func)(float), int passes, float v)
{
unsigned long used;
used = timeGetTime();
for (int pos = 0; pos < passes; pos++)
func(v);
used = timeGetTime() - used;

cout << used << " ms used for " << passes << " passes, avg ";
cout << (double)used/passes << " ms\n";
} // TimeFunction

int main(void)
{
// timing of versions
int passes = 10000000;
float v = 1.234f; // test value
cout << "Timing basic function\n";
TimeFunction(InvSqrtExact,passes,v);
cout << "Timing Carmack function\n";
TimeFunction(InvSqrt,passes,v);
cout << "Timing Lomont function\n";
TimeFunction(InvSqrt_Lomont,passes,v);

cout << "Done. By Chris Lomont 2003\n";
return 0;
} // main

---------------------------------------------------------

运算结果相差无几,难道我的程序有什么问题?

继续探索,发现同样的程序在VC6.0和VC20008下面竟然表现不同,怪事!

VC++.net 2008
-------------------------------------
Timing basic function
2187 ms used for 10000000 passes, avg 0.0002187 ms
Timing Carmack function
828 ms used for 10000000 passes, avg 8.28e-005 ms
Timing Lomont function
844 ms used for 10000000 passes, avg 8.44e-005 ms
Done. By Chris Lomont 2003

VC++ 6.0
--------------------------------------
Timing basic function
625 ms used for 10000000 passes, avg 6.25e-005 ms
Timing Carmack function
453 ms used for 10000000 passes, avg 4.53e-005 ms
Timing Lomont function
453 ms used for 10000000 passes, avg 4.53e-005 ms
Done. By Chris Lomont 2003
------------------------------------

貌似跟“using namespace std”有一定的关系,可能是sqrt的函数库版本不太一样,因为我是用VC++6.0,崩溃中......

看来0x5f3759df也不是那么神奇吧,另外,也可以看出.net程序的性能确实不怎样。

2009-08-06

VCC new layout.

VCC lab重新装修,焕然一新。条件越来越好,呵呵。






2009-08-02

The University of Hong Kong

今天第一天来到香港大学,立此存照。O(∩_∩)O