第一章《3D理论初步》
小伙伴们,你们好!
经历了两年多的Cocos2d-x的学习与开发,我相信你们都已经成长为一名合格的Cocos2d-x程序员。但是,千万不要觉得这样就可以万事无忧了!3D时代已经来临,3D手游的产品越来越多,怎么办?使用Unity3D?嗯,是啊,Unity3D看起来不错的样子,不过,你是愿意放弃长期习惯的VC++的开发方式?你是否愿意放弃开源引擎自由掌控代码的感觉?你是否愿意从此站在引擎底层之外,只是做一个使用者?
如果你想快速的基于现有的Cocos2d-x经验或项目来增加3D部分功能,或者你的志向是和我一样,成为一个引擎开发者,那么,勇敢的踏出这一步吧。相信自已经过短期的学习也有能力做出完整的3D引擎。
注:限于时间仓促,水平有限,错误及不妥之处在所难免,望各位兄台海涵并及时指正。
第一章《3D理论初步》
配套视频:http://my.tv.sohu.com/us/231143039/74549915.shtml
一.2D与3D:
相信大家都学过平面几何与立体几何,这2D与3D就是这两种几何空间,我们之前一直在平面几何里去展示自已的游戏内容,进入到立体几何空间后,X,Y增加了一个纵深Z,但难度却不仅仅只是增加了1/2。3D以摸拟现实为最高目标。除了位置的表现方式不同,其在大小,质感,光与影,环境氛围上均有更多深入的表现。
哈哈,不要怪我,实在找不到太合适的图进行对比:
这是一个2D场景中的美女:
这个则是3D场景中的美女:
同样都是美女,但3D场景中的建筑,人物,环境都有了具体的提升,它非常逼真,几乎和现实没有什么太大的不同。
一切,都源于它多了一个Z轴,使形状,位置,色深,质感有了更细腻的变化。
千里之行,始于足下,在做出非常棒的3D游戏之前,我们先要学习好3D的空间理论,掌握3D空间的位置,旋转,偏移的处理,只有这样,才可能一步步真正的了解3D的精髓。
首先来回顾一下,在2D空间中,我们使用笛卡尔坐标系:
但在3D空间中,它变成了:
左手坐标系与右手坐标系。
坐标系也好,右手系也罢,总归是用手心朝向,大拇指方向,手伸出的方向代表三个轴,X,Y,Z。所有的空间计算也都基于这三个轴。下面我们来详细学习一下。
二.向量:
空间的点,即一个位置的表示单位,学名向量,程序中就是一个结构,容纳了x,y,z三个变量。在Cocos2d-x中,这个结构体的名称叫做Vec3,它在libcocos2d math目录下的Vec3.h中定义。
[cpp] view plaincopy
class Vec3
{
public:
//X,Y,Z
float x;
float y;
float z;
//构造与拷贝构造
Vec3();
Vec3(float xx, float yy, float zz);
Vec3(const float* array);
Vec3(const Vec3& p1, const Vec3& p2);
Vec3(const Vec3& copy);
//从一个DWORD的色彩值中获取向量,即将R,G,B对应到X,Y,Z上返回。
static Vec3 fromColor(unsigned int color);
//析构
~Vec3();
//是否是零
bool isZero() const;
//是否是一
bool isOne() const;
//取得两个向量之间的角度
static float angle(const Vec3& v1, const Vec3& v2);
//与参数指定向量相加
void add(const Vec3& v);
//取得两个向量相加的和
static void add(const Vec3& v1, const Vec3& v2, Vec3* dst);
//将当前向量设置最大和最小值。
void clamp(const Vec3& min, const Vec3& max);
//对一个向量设置最大和最小值。
static void clamp(const Vec3& v, const Vec3& min, const Vec3& max, Vec3* dst);
//与参数指定向量进行叉积计算。
void cross(const Vec3& v);
//取得两个向量的叉积。
static void cross(const Vec3& v1, const Vec3& v2, Vec3* dst);
//与参数指定向量进行距离计算。
float distance(const Vec3& v) const;
//与参数指定向量进行距离的平方计算。因为向量长度的计算公式是sqrt(x^2+y^2+z^2);但sqrt比较消耗CPU,所以呢,一般我们在进行长度的使用时,如果是对比操作而不是取值操作,那可以直接用这个函数,相对会快一些,毕竟,两个长度的平方对比和两个长度的对比没有什么区别。
float distanceSquared(const Vec3& v) const;
//与参数指定向量进行点积计算
float dot(const Vec3& v) const;
//取得两个向量的点积
static float dot(const Vec3& v1, const Vec3& v2);
//取得当前向量的长度
float length() const;
//取得当前向量的长度的平方。
float lengthSquared() const;
//对当前向量取反
void negate();
//向量归一化。
void normalize();
//取得当前向量的归一化向量值。
Vec3 getNormalized() const;
//对当前向量进行缩放。
void scale(float scalar);
//设置当前向量的值。
void set(float xx, float yy, float zz);
void set(const float* array);
void set(const Vec3& v);
void set(const Vec3& p1, const Vec3& p2);
//与参数指定向量进行相减。
void subtract(const Vec3& v);
//取得两个向量的差
static void subtract(const Vec3& v1, const Vec3& v2, Vec3* dst);
//通过参数指定向量与时间值来取得插值向量值。
void smooth(const Vec3& target, float elapsedTime, float responseTime);
//操作符重载
inline const Vec3 operator+(const Vec3& v) const;
inline Vec3& operator+=(const Vec3& v);
inline const Vec3 operator-(const Vec3& v) const;
inline Vec3& operator-=(const Vec3& v);
inline const Vec3 operator-() const;
inline const Vec3 operator*(float s) const;
inline Vec3& operator*=(float s);
inline const Vec3 operator/(float s) const;
inline bool operator<(const Vec3& v) const;
inline bool operator==(const Vec3& v) const;
inline bool operator!=(const Vec3& v) const;
//x,y,z都为0的静态常量向量
static const Vec3 ZERO;
//x,y,z都为1的静态常量向量
static const