2010年7月6日星期二

<转>文本文件和二进制文件的区别

从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。

ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。例如,数5678的存储形式为:
ASC码:    00110101 00110110 00110111 00111000
                        ↓        ↓        ↓        ↓
十进制码:   5      6      7      8

共占用4个字节。ASCII码文件可在屏幕上按字符显示,例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容。由于是按字符显示,因此能读懂文件内容。

二进制文件是按二进制的编码方式来存放文件的。例如,数5678的存储形式为:00010110 00101110只占二个字节。二进制文件虽然也可在屏幕上显示,但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。因此也把这种文件称作“流式文件”。

一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符'\n',而二进制模式认为它是两个字符0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。

2010年7月1日星期四

[转] Phong lighting model

From wikipedia:

Phong reflection is an empirical model of local illumination. It describes the way a surface reflects light as a combination of the diffuse reflection of rough surfaces with the specular reflection of shiny surfaces. It is based on Bui Tuong Phong's informal observation that shiny surfaces have small intense specular highlights, while dull surfaces have large highlights that fall off more gradually. The reflection model also includes an ambient term to account for the small amount of light that is scattered about the entire scene.

For each light source in the scene, we define the components is and id as the intensities (often as RGB values) of the specular and diffuse components of the light sources respectively. A single term ia controls the ambient lighting; it is sometimes computed as a sum of contributions from all light sources.

For each material in the scene, we define:

ks: specular reflection constant, the ratio of reflection of the specular term of incoming light
kd: diffuse reflection constant, the ratio of reflection of the diffuse term of incoming light (Lambertian reflectance)
ka: ambient reflection constant, the ratio of reflection of the ambient term present in all points in the scene rendered
α: is a shininess constant for this material, which is larger for surfaces that are smoother and more mirror-like. When this constant is large the specular highlight is small.

We further define lights as the set of all light sources, L as the direction vector from the point on the surface toward each light source, N as the normal at this point on the surface, R as the direction that a perfectly reflected ray of light would take from this point on the surface, and V as the direction pointing towards the viewer (such as a virtual camera).

Note L, N, R, V are all unit vecters.

Then the Phong reflection model provides an equation for computing the shading value of each surface point Ip:


The diffuse term is not affected by the viewer direction (V). The specular term is large only when the viewer direction (V) is aligned with the reflection direction R. Their alignment is measured by the α power of the cosine of the angle between them. The cosine of the angle between the normalized vectors R and V is equal to their dot product. When α is large, in the case of a nearly mirror-like reflection, the specular highlight will be small, because any viewpoint not aligned with the reflection will have a cosine less than one which rapidly approaches zero when raised to a high power.
When we have color representations as RGB values, this equation will typically be calculated separately for R, G and B intensities.

Although the above formulation is the common way of presenting the Phong model, a particular term in the sum should only be included if it is positive, i.e. the equation is formally incorrect.

Therefore, in the above fomulation, (Lm·N) should be exactly max(Lm·N, 0) and similarly (Rm·V) should be max(Rm·V, 0).

2010年6月25日星期五

Normal transformation matrix的推导

normal的transformation matrixh和vertex的transformation matrix并不相同。以下是推导:

vertex上的normal可以定义一个平面,  顶点在平面上,则有(nx, ny, nz, q)*(x0, yo, zo, w)' = 0。当顶点做完model-view transformation后,M为model-view transfornation matrix, 则有(nx, ny, nz, q)*inverse(M)*M*(x0, yo, zo, w)' = 0。变换后的(nx, ny, nz, q)为(nx', ny', nz', q') = (nx, ny, nz, q)*inverse(M), 由于我们并不需要q, 变换后的normal可以写成(nx', ny', nz')= (nx, ny, nz)*inverse(Mu),Mu为M的左上3×3submatrix。最后对(nx', ny', nz')做normalization使其变为unit vector完成变换。

由此得出若使用row vector表示normal则transformation matrix为inverse(Mu),使用column vector表示normal则transformation matrix为inverse(Mu)'

Projective Texture Mapping

Projective Texture Mapping是将texture用投影的方法投射到物体上的一种texture mapping方法。从顶点到texture坐标的变换如下图右所示:


在OpenGL里,实现projective mapping可以用两种texture生成方法, object linear和eye linear, 其变换矩阵分别如下图:

Object Linear Texgen

Eye Linear Texgen

Object Linear Texgen左乘的对象是顶点在object space的坐标,Eye Linear Texgen左乘的对象则是顶点在view space的坐标,一般使用Eye Linear Texgen来实现不同object coordinate system的物体的统一投影效果(如shadow mapping)。用OpenGL的实现Eye Linear Texgen,如果用R表示 [0,1] range transformation matrix,则需要将R*Pp*Vp的四个row vector分别设为s,t,r,q的eye plane。

最后发两张NV教学文档里的效果图:

 

2010年6月24日星期四

glTexGen中object linear和eye linear的区别

根据red book的解释,在eye linear模式下,t = p1' * Xe + p2' * Ye + p3' * Ze + p4' ,Xe,Ye,Ze是顶点在viewing space的坐标, 故有(Xe, Ye, Ze, We) = M * (x0, y0, z0, w0),x0 , y0 , z0 ,w0为顶点在object space的坐标。而( p1' , p2', p3', p4') = (p1, p2 , p3 ,p4)*inverse(M),这样看来 t =  (p1, p2, p3, p4) * (x0 , y0 , z0 ,w0), 生成的texture coordinates和在object linear模式下完全相同。怎么会这样呢?

实际上,在( p1' , p2', p3', p4') = (p1, p2 , p3 ,p4)*inverse(M)中,M为调用glTexGen时的Model-view矩阵,在生成坐标过程中不会再变化,而(Xe , Ye , Ze , We) = M * (x0 , y0 , z0 ,w0)中的M则是定义(x0 , y0 , z0 ,w0)时当前的Model-view矩阵,在定义不同顶点时Model-view矩阵可能会有所不同。只有在调用glTexGen后Model-view矩阵没有变化的情况下,在两种模式下生成的texture coordinates相同。简单的说,object linear模式中的纹理坐标跟据顶点的object coordinate(也就是glVertex定义的坐标)做一个固定的变换而生成,而eye linear模式则是把顶点变换到当先的viewing space,根据得到的viewing coordinate做一个固定的变换而生成。

2010年3月4日星期四

关于空集

空集不含任何元素,Ø 是空集,{Ø}不是空集,因为{Ø}含有元素Ø

对任意集合 A,空集是 A 的子集;
∀A: Ø ⊆ A

对任意集合 A, 空集和 A 的并集为 A:
∀A: A ∪ Ø = A

对任意集合 A, 空集和 A 的交集为空集:
∀A: A ∩ Ø = Ø

对任意集合 A, 空集和 A 的笛卡尔积为空集:
∀A: A × Ø = Ø

空集的唯一子集是空集本身:
∀A: A ⊆ Ø ⇒ A = Ø

空集的元素个数(即它的势)为零;特别的,空集是有限的:
Card(Ø) = 0
 
 空集是任何非空集合的真子集。.Ø  只有一个子集,没有真子集。{Ø}有两个子集,一个是Ø , 一个是它本身

2010年2月21日星期日

<转>malloc和calloc的区别

函数malloc()和calloc()都可以用来动态分配内存空间,但两者稍有区别。

malloc()函数有一个参数,即要分配的内存空间的大小:

void*malloc(size_tsize);

calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。

void*calloc(size_tnumElements,size_tsizeOfElement);

如果调用成功,函数malloc()和函数calloc()都将返回所分配的内存空间的首地址。

函数malloc()和函数calloc() 的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0;反之, 如果这部分内存曾经被分配过,则其中可能遗留有各种各样的数据。也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常进 行,但经过一段时间(内存空间还已经被重新分配)可能会出现问题。

函数calloc() 会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那麽这些元素将保证会被初始化为0;如果你是为指 针类型的元素分配内存,那麽这些元素通常会被初始化为空指针;如果你为实型数据分配内存,则这些元素会被初始化为浮点型的零。