摘要: 若想成大事,雷军认为有三条秘诀:预判未来、在对的时间做对的事情、顺势而为。颇为赞同,自己也有一些思考,记录下来。 阅读全文
摘要: 对于OpenGL的初学者来说,有两个不应该成为困难点的困难点。一个是编写OpenGL程序需要依赖特定平台的窗体系统。另外一个是OpenGL的扩展机制需要我们自己去处理。
这里推荐两个利器来解决这两个问题。让我们可以更加专注和有效的学习OpenGL。分别是GLUT和GLEW 阅读全文
摘要: 最近在Android平台上写NDK程序,使用OpenGL ES(注意:这里是OpenGL ES 1.0和1.1版本),发现程序在运行过程中出现如下错误:
通过log,在android的源码中的\frameworks\base\opengl\libs\EGL\目录下有Loader.cpp文件,通过这 个文件我们可以发现,我们的OpenGL的调用都是通过加载实现了OpenGL ES的dll,然后在该dll中查找我们调用的接口,如果接口没有找到,EGL就会打印出log,如上所示。
阅读全文
今天突然发现ANDROID模拟器启动失败,log显示如下错误信息:
ERROR: the user data image is used by another emulator. aborting
问题原因:avd的加锁机制使然。 .lock是加锁,如果程序崩溃等原因导致无法清除这些以.lock结尾的文件夹,就会出现这个问题,也就是这个avd的锁没有被释放,导致avd manager以为这个avd正在使用当中。
解决办法:删除C:\Documents and Settings\@USER@\.android\avd.找到该目录下与模拟器对应的avd,然后删除其中的.lock文件即可。
摘要: OpenGL中的Frame Buffer Object(FBO)扩展,被推荐用于把数据渲染到纹理对像。相对于其它同类技术,如数据拷贝或交换缓冲区等,使用FBO技术会更高效并且更容易实现。
FBO一个最常见的应用就是:渲染到纹理(render to texture),通过这项技术可以实现发光效果,环境映射,阴影映射等很炫的效果。
在OpenGL渲染管线中,几何数据和纹理最终都是以2d像素绘制到屏幕上。最后一步的渲染目标在OpenGL渲染管线中被称为帧缓存(frame buffer)。帧缓存是颜色缓存、深度缓存、模板缓存、累积缓存的集合。默认情况下, OpenGL使用的帧缓存是由窗体系统创建和管理的。
在OpenGL扩展中,GL_EXT_framebuffer_object扩展提供了一个创建额外帧缓存对象(FBO)的接口。这个帧缓存的创建和控制完全是由OpenGL完成的,有别于窗体系统创建的默认的帧缓存。与系统默认的帧缓存类似,一个FBO也是颜色缓存、深度缓存、模板缓存的集合(FBO不包括累积缓存),然后OpenGL程序就可以把渲染重定向到FBO 阅读全文
这段时间使用vim,写了不少测试代码,既然是测试代码,注释测试代码,取消注释就是一个经常性的操作,到今天才动手去找了一个vim的注释代码的插件。
下载地址:NERD Commenter
下载以后解压。把doc放doc目录下,NERD_commenter.vim放plugin目录下,启动vim,OK了。
注释代码:
在可视模式下,选择要注释的代码,输入: ,cc
取消注释: 选择要取消注释的代码,输入: ,cu
不错的插件。
在OpenGL中我们可以使用gluPerspective来设置视椎体。但是在OpenGL ES中却没有提供这样的实用库支持,其实我们可以自己来完成这个函数的功能。代码如下:
1
2 void __gluPerspective(double fovy, double aspect, double zNear, double zFar)
3 {
4 glMatrixMode(GL_PROJECTION);
5 glLoadIdentity();
6
7 double xmin, xmax, ymin, ymax;
8 ymax = zNear * tan(fovy * KPI / 360);
9 ymin = -ymax;
10 xmin = ymin * aspect;
11 xmax = ymax * aspect;
12
13 glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
14 }
15
16
在需要调用gluPerspective的地方,用该函数替换即可。
学习3D编程,四元数是不得不学的。其概念的引入和定义都比较抽象,今学了,总结归纳如下:
介绍四元数之前,先做如下约定:
1.采用右手坐标系(OpenGL)
2.旋转次序:x->y->z
3. 矩阵是列优先存储
1.什么是四元数?
直接用数学上的定义来解释,因为我很难在现实生活中找到可以描述明白的例子。
i, j, k 为虚数
Q = w + xi + yj
+ zk
其中w是实数,而x,y,z为复数。
另外一种常见的表达方式是:
Q = [w, v]
其中v=(x,y,z)称为矢量部(虽然称为矢量,但是这个不是三维空间中的矢量,而是四维空间的,想象吧L),w称为标量部。
2.四元数可以做什么?
有了四元数的概念还不行,四元数可以干什么?四元数可以用来描述方向。
先来看下如何求取四元数的长度:
||q|| = Norm(q)
= sqrt(w2 + x2 + y2 + z2)
单位长度的四元数有以下属性:
w2 +
x2 + y2 + z2 = 1
所以我们使用如下方法来标准化(Normalize)一个四元数:
q = q / ||q|| =
q / sqrt(w2 + x2 + y2 + z2)
使用一个单位四元数来描述方向,请记住必须是单位四元数才可以描述方向。
3.四元数的乘法
因为一个单位四元数可以代表一个三维空间中的方向,那么两个四元数相乘得到的结果仍然是一个四元数,这个四元素依旧可以标识一个方向。
给定两个四元数:
Q1 = (w1, x1,
y1, z1)
Q2 = (w2, x2,
y2, z2)
Q1 * Q2 = (w1.w2
– v1.v2, w1.v2 + w2.v1 + v1 x v2)
注意:.代表向量间的点积,x代表叉积。v1=(x1, y1, z1) v2=(x2, y2, z2)
优化一下:
w=w1w2 - x1x2 -
y1y2 - z1z2
x = w1x2 + x1w2 + y1z2 - z1y2
y = w1y2 + y1w2 + z1x2 - x1z2
z = w1z2 + z1w2 + x1y2 - y1x2
4.四元数的转换
为什么要转换,因为我们还不能直接使用四元数来进行3D物体的旋转。在OpenGL中和Direct3D中都是通过矩阵来描述3D旋转的。
4.1 四元数到矩阵的转换
使用单位四元数转换到矩阵:
Matrix = [ 1 - 2y2 - 2z2 2xy - 2wz 2xz + 2wy
2xy + 2wz 1 - 2x2 - 2z2 2yz - 2wx
2xz - 2wy 2yz + 2wx 1 - 2x2 - 2y2 ]
4.2 四元数到轴角的转换
轴角也是一种表达空间旋转的方式。
如果旋转轴是:(ax, ay, az)
旋转角度是:angle (单位:弧度)
那么四元数与轴角之间的转换关系如下:
angle = 2 *
acos(w)
ax = x / scale
ay = y / scale
az = y / scale
其中scale = sqrt(x2 + y2 + z2)
4.3 轴角到四元数的转换
假设旋转轴是(ax, ay, az),记得必须是一个单位向量。
旋转角度是theta. (单位:弧度)
那么转换如下:
w = cos(theta / 2
)
x = ax *
sin(theta / 2)
y = ay *
sin(theta / 2)
z = az *
sin(theta / 2 )
4.4 欧拉角到四元数的转换
如果你的欧拉角为(a, b, c)那么就可以形成三个独立的四元数,如下:
Qx = [ cos(a/2),
(sin(a/2), 0, 0)]
Qy = [ cos(b/2), (0, sin(b/2), 0)]
Qz = [ cos(c/2), (0, 0, sin(c/2))]
最终的四元数是Qx * Qy
* Qz的乘积的结果。
5.使用四元数来避免Gimbal
Lock
基本思路如下:
1)
使用一个四元数来标识一个方向
2)
创建一个临时的四元数来标识当前方向到新方向的变化
3)
右乘临时的四元数和初始四元数,结果是一个合并了两个四元数的新的四元数
4)
将四元数转换成矩阵
6.更深入的学习四元数
SLERP:球状线性插值对于三位模型进行动画处理非常有用,因为这种方式在模型的各种方向之间提供了平滑的转换。
摘要: 如果对象需要进行有意义的(non-trival)初始化,考虑使用明确的init()的方法来进行初始化操作。因为如果在构造函数中进行有意义的初始化操作,一旦这些操作失败,对象将进入不确定的状态。symbian编程中广泛使用一种称为“两阶段构造法”的方法来解决这个问题,值得借鉴。 阅读全文