自学内容网 自学内容网

3d图形学基础(一):向量与坐标系

1.1 向量与坐标系

1.1.1 向量与坐标系的应用

零向量: 零向量是没有方向的向量;

负向量: 负向量是与原向量方向相反、长度相等的向量;

向量的模: 即向量的长度,向量中各标量的平方和开根可以得到向量的模;

请添加图片描述

/*
* 三维坐标取模
*/
float mod(const Vector3& pos)
{
if (*this == VEC3_ZERO)
return 0;
float squaresSum = x * x + y * y + z * z;
return sqrt(squaresSum);
}

单位向量: 长度为1的向量,向量除以向量的模等于该向量的单位向量;

请添加图片描述

/*
* 归一化,获取单位向量
*/
Vector3 normal() const 
{ 
float tep = mod();
if (tep == 0)
return VEC3_ZERO;
return *this/tep;
}

坐标间的距离: 将两个坐标相减所得到的新坐标进行取模就能得到坐标间的距离;

/*
* 计算与指定坐标的距离
*/
float distance(const Vector3& vec) {
Vector3 tep = *this - vec;
float distance = tep.mod();
return distance;
}
/*
* 计算两个坐标间的距离
*/
inline float Distance(const Vector3& vec1, const Vector3& vec2) {
Vector3 tep = vec1 - vec2;
float distance = tep.mod();
return distance;
}

向量点乘: 向量点乘的结果是一个标量,公式如下;
在这里插入图片描述
在这里插入图片描述

利用向量点乘可以获得两个向量的方向:点乘结果等于 0 两个向量垂直,大于 0 方向相同,小于 0 方向相反;

利用向量点乘还可以获得夹角:

a * b = || a || || b || cosθ => cosθ = (a * b) / (|| a || || b || ) => θ = arccos((a * b) / (|| a || || b || ))

/*
* 点乘
*/
inline float Dot(const Vector3& vec1, const Vector3& vec2) {
float result = vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
return result;
}
/*
* 计算与指定坐标的夹角
*/
float angle(const Vector3& vec) const{
float dot = Dot(*this, vec);
float mod1 = mod();
float mod2 = vec.mod();
if (mod1 == 0.0f || mod2 == 0.0f)
return 0.0f;
float result = acosf(dot / (mod1 + mod2));
return result;
}
/*
* 获取两个向量间的夹角
*/
inline float Angle(const Vector3& vec1, const Vector3& vec2) {
float dot = Dot(vec1, vec2);
float mod1 = vec1.mod();
float mod2 = vec2.mod();
if (mod1 == 0.0f || mod2 == 0.0f)
return 0.0f;
float angle = acosf(dot / (mod1 + mod2));
return angle;
}

向量叉乘: 向量叉乘的结果是一个向量,叉乘的结果垂直于进行叉乘的两个向量,公式如下;
在这里插入图片描述
在这里插入图片描述

叉乘获得的结果进行模运算的结果是进行叉乘前的两个向量所映射出的平行四边形的面积;

叉乘还可用来判断两个向量是否平行,如果叉乘结果是零向量则两个向量是平行的;

/*
* 叉乘
*/
inline Vector3 Cross(const Vector3& vec1, const Vector3& vec2) {
return Vector3(
vec1.y * vec2.z - vec1.z * vec2.y,
vec1.z * vec2.x - vec1.x * vec2.z,
vec1.x * vec2.y - vec1.y * vec2.x
);
}
/*
* 两个向量的方向是否平行
*/
inline bool IsParallel(const Vector3& vec1, const Vector3& vec2) {
Vector3 result = Cross(vec1, vec2);
return result == VEC3_ZERO;
}
/*
* 计算与指定坐标的方向是否平行
*/
bool isParallel(const Vector3& vec) {
Vector3 result = Cross(*this, vec);
return result == VEC3_ZERO;
}

1.1.2 完整测试代码

#include <cmath>
#include <sstream>
#ifndef __VECTOR3_H_INCLUDED__
#define __VECTOR3_H_INCLUDED__
class Vector3
{
public:
float x, y, z;
Vector3() {}
Vector3(const Vector3& pos) : x(pos.x), y(pos.y), z(pos.z) {}
Vector3(float nx, float ny, float nz) : x(nx), y(ny), z(nz) {}
Vector3 operator +() const { 
        return Vector3(fabs(x), fabs(y), fabs(z)); 
    }
Vector3 operator -() const { 
        return Vector3(-x, -y, -z); 
    }
Vector3 operator +(Vector3 vec) const { 
        return Vector3(x + vec.x, y + vec.y, z + vec.z); 
    }
Vector3 operator +=(Vector3 vec) {
x += vec.x;
y += vec.y;
z += vec.z;
return *this;
}
Vector3 operator -(Vector3 vec) const { 
        return Vector3(x - vec.x, y - vec.y, z - vec.z); 
    }
Vector3 operator -=(Vector3 vec) {
x -= vec.x;
y -= vec.y;
z -= vec.z;
return *this;
}
Vector3 operator *(float num) const { 
        return Vector3(x * num, y * num, z * num); 
    }
Vector3 operator *=(float num) {
x *= num;
y *= num;
z *= num;
return *this;
}
Vector3 operator /(float num) const { 
float tep = 1.0f / num;
const float threshold = 1e-6; 
if (tep < threshold)
return VEC3_ZERO;
Vector3 result = Vector3(
x * tep , 
y * tep, 
z * tep
);
return result;
}
Vector3 operator /=(float num) {
float tep = 1.0f / num;
float tep = 1.0f / num;
const float threshold = 1e-6;
if (tep < threshold) 
*this = VEC3_ZERO;
else
*this *= tep;
return *this;
}
bool operator ==(const Vector3 &vec) const{
bool isbool = vec.x == x && vec.y == y && vec.z == z;
return isbool;
}
/*
* 坐标置0
*/
void zero() { x = y = z = 0.0f; }

/*
* 取向量模
*/
float mod() const
{
if (*this == VEC3_ZERO)
return 0;
float squaresSum = x * x + y * y + z * z;
return sqrt(squaresSum);
}
/*
* 归一化,获取单位向量
*/
Vector3 normal() const 
{ 
float tep = mod();
if (tep == 0)
return VEC3_ZERO;
return *this/tep;
}
/*
* 返回坐标字符串
*/
std::string string() const {
std::stringstream ss;
ss << "Vector3:" << "(" << x << ", " << y << ", " << z << ")";
return ss.str();
}
/*
* 计算与指定坐标的距离
*/
float distance(const Vector3& vec) const{
Vector3 tep = *this - vec;
float distance = tep.mod();
return distance;
}
/*
* 计算与指定坐标的夹角
*/
float angle(const Vector3& vec) const{
float dot = Dot(*this, vec);
float mod1 = mod();
float mod2 = vec.mod();
if (mod1 == 0.0f || mod2 == 0.0f)
return 0.0f;
float result = acosf(dot / (mod1 + mod2));
return result;
}
/*
* 计算与指定坐标的方向是否平行
*/
bool isParallel(const Vector3& vec) {
Vector3 result = Cross(*this, vec);
return result == VEC3_ZERO;
}
};
const Vector3 VEC3_ZERO = Vector3(0, 0, 0);
const Vector3 VEC3_ONE = Vector3(1, 1, 1);
inline Vector3 operator *(float num, const Vector3 &vec) {
return vec * num;
}
/*
* 计算两个坐标间的距离
*/
inline float Distance(const Vector3& vec1, const Vector3& vec2) {
Vector3 tep = vec1 - vec2;
float distance = tep.mod();
return distance;
}
/*
* 点乘
*/
inline float Dot(const Vector3& vec1, const Vector3& vec2) {
float result = vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
return result;
}
/*
* 叉乘
*/
inline Vector3 Cross(const Vector3& vec1, const Vector3& vec2) {
return Vector3(
vec1.y * vec2.z - vec1.z * vec2.y,
vec1.z * vec2.x - vec1.x * vec2.z,
vec1.x * vec2.y - vec1.y * vec2.x
);
}
/*
* 获取两个向量间的夹角
*/
inline float Angle(const Vector3& vec1, const Vector3& vec2) {
float dot = Dot(vec1, vec2);
float mod1 = vec1.mod();
float mod2 = vec2.mod();
if (mod1 == 0.0f || mod2 == 0.0f)
return 0.0f;
float angle = acosf(dot / (mod1 + mod2));
return angle;
}
/*
* 两个向量的方向是否平行
*/
inline bool IsParallel(const Vector3& vec1, const Vector3& vec2) {
Vector3 result = Cross(vec1, vec2);
return result == VEC3_ZERO;
}
#endif // ! __VECTOR3_H_INCLUDED__
```\

原文地址:https://blog.csdn.net/jc15274630894/article/details/136385168

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!