3D数学基础--向量

理论基础

  • 向量:它看起来就像一支箭,有大小和方向,没有位置。它的几何意义是表示一段位移,如(1, -2, 3)表示的位移是:向右平移1个单位,向下平移2个单位,向前平移3个单位。它们的执行顺序无关紧要。

  • 向量运算与几何意义
    零向量:数学表示(0,0,0),表示没有位移,就像标量0表示没有数量一样。

    负向量:几何意义是将得到和原来大小相等,方向相反的向量。

    向量的大小:即向量的模,数学表示sqrtf(x*x + y*y + z*z),其几何描述就是勾股定理,直角三角形的临边的平方和等于斜边的平方(x*x + y*y = s*s)。

    标量与向量相乘:得到的还是向量,就是将向量的每个分量都与标量相乘即可(除以标量就是乘以它的倒数)。其几何意义是:对向量的长度进行缩放,如果标量小于0则方向也被倒转。

    标准化向量:将向量转换为单位向量,即大小为1的向量。这主要用于我们只关心对象方向而对大小并不关心的情况,如:法线。数学计算就是向量除以它的大小(模)即可。

    向量与向量加减法:两个向量相加减,将对应分量相加减即可。其几何含义类似前面说的向量表示一段位移含义一样。如某个向量加上这个向量(1, -2, 3)表示将它向右平移1个单位,向下平移2个单位,向前平移3个单位得到的向量(减就是加上方向相反的向量)。

    向量点乘:即向量与向量相乘,数学计算是对应分量乘积的和,其结果是一个标量。另一种几何计算是:点乘等于向量大小与向量夹角的cos值的积(这里通过这个夹角就可以判断两向量的方向关系了,如垂直,平行,方向相同,相反)。点乘我们常用还有一个:投影,即将向量分解为平行和垂直于其他向量的两个分量。

    向量叉乘:仅用于3D向量,数学计算是交叉相乘,得到的结果是向量,这个向量垂直于原来的两个向量。所以叉乘最重要的应用是用于创建垂直于平面,三角形或多边形的向量。叉乘的长度等于向量的大小与向量夹角sin值的积。


向量类

//
//  Vector3.h
//  hello
//
//  Created by app05 on 15-6-15.
//  Copyright (c) 2015年 app05. All rights reserved.
/*注释:
--是否需要const修饰就是分析其数据是否需要修改,不需要修改就加const,安全性
--一般有两个地方需要考虑是否加const:1,成员函数参数处 2,成员函数本身,即类本身数据不允许修改(修饰的是this)
*/

#ifndef hello_Vector3_h
#define hello_Vector3_h
#include <math.h>

class Vector3
{
public:
    float x, y, z;
    //构造函数
    Vector3() {}
    Vector3(const Vector3 &a) : x(a.x), y(a.y), z(a.z) {}
    Vector3(float nx, float ny, float nz) : x(nx), y(ny), z(nz) {}
    //重载 '='
    Vector3 &operator =(const Vector3 &a)
    {
        x = a.x; y = a.y; z = a.z;
        return *this;
    }
    //重载 '=='
    bool operator ==(const Vector3 &a) const
    {
        return x == a.x && y == a.y && z == a.z;
    }
    //重载 '!='
    bool operator !=(const Vector3 &a) const
    {
        return x != a.x || y != a.y || z != a.z;
    }
    //置为零向量
    void zero() {x = y = z = 0.0f;}
    //重载一元 '-' (即负号)
    Vector3 operator -() const {return Vector3(-x, -y, -z);}
    //重载二元 '+' '-'(即加,减)
    Vector3 operator +(const Vector3 &a) const
    {
        return Vector3(x + a.z, y + a.y, z + a.z);
    }
    Vector3 operator -(const Vector3 &a) const
    {
        return Vector3(x - a.x, y - a.y, z - a.z);
    }
    //与标量的乘,除法
    Vector3 operator *(float a) const
    {
        return Vector3(x * a, y * a, z * a);
    }
    Vector3 operator /(float a) const
    {
        float val = 1.0f / a;  /*这里没有对除数为零进行检查*/
        return Vector3(x * val, y * val, z * val);
    }
    //重载自反运算符
    Vector3 operator +=(const Vector3 &a)
    {
        x += a.x; y += a.y; z += a.z;
        return *this;
    }
    Vector3 operator -=(const Vector3 &a)
    {
        x -= a.x; y -= a.y; z -= a.z;
        return *this;
    }
    Vector3 operator *=(float a)
    {
        x *= a; y *= a; z *= a;
        return *this;
    }
    Vector3 operator /=(float a)
    {
        float val = 1.0f / a;
        x *= val; y *= val; z *= val;
        return *this;
    }
    //向量标准化
    void normalize()
    {
        float magSq = x * x + y * y + z * z;
        if (magSq > 0)
        {
            float val = 1.0f / sqrt(magSq);
            x *= val;
            y *= val;
            z *= val;
        }
    }
    //向量点乘
    float operator *(const Vector3 &a) const
    {
        return x * a.x + y * a.y + z * a.z;
    }
};


///////////////////////////////////////////////////////////////////////
//
//非成员函数:有些函数写类外面更易懂
//
///////////////////////////////////////////////////////////////////////
/*加inline 可以防止函数重定义,因为内联直接在调用处展开,不会编译成全局的函数调用*/

//求向量的模
inline float vectorMag(const Vector3 &a)
{
    return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
}
//计算向量的叉乘
inline Vector3 crossProduct(const Vector3 &a, const Vector3 &b)
{
    return Vector3(
        a.y * b.z - a.z * b.y,
        a.z * b.x - a.x * b.z,
        a.x * b.y - a.y * b.x
    );
}
//实现标量左乘
inline Vector3 operator *(float k, const Vector3 &v)
{
    return Vector3(k * v.x, k * v.y, k * v.z);
}
//计算两点间的距离
inline float distance(const Vector3 &a, const Vector3 &b)
{
    float dx = a.x - b.x;
    float dy = a.y - b.y;
    float dz = a.z - b.z;
    return sqrt(dx * dx + dy * dy + dz * dz);
}

//提供一个全局零向量
extern const Vector3 kZeroVector;

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值