# 手把手教你架构3D引擎高级篇系列六

## 向量

void Vec3::normalize()
{
float x = this->x;
float y = this->y;
float z = this->z;
float inv_len = 1 / sqrt(x * x + y * y + z * z);
x *= inv_len;
y *= inv_len;
z *= inv_len;
this->x = x;
this->y = y;
this->z = z;
}

Vec3 Vec3::normalized() const
{
float x = this->x;
float y = this->y;
float z = this->z;
float inv_len = 1 / sqrt(x * x + y * y + z * z);
x *= inv_len;
y *= inv_len;
z *= inv_len;
return Vec3(x, y, z);
}

float Vec3::length() const
{
float x = this->x;
float y = this->y;
float z = this->z;
return sqrt(x * x + y * y + z * z);
}



## 矩阵

void Matrix::fromEuler(float yaw, float pitch, float roll)
{
float sroll = sinf(roll);
float croll = cosf(roll);
float spitch = sinf(pitch);
float cpitch = cosf(pitch);
float syaw = sinf(yaw);
float cyaw = cosf(yaw);

m11 = sroll * spitch * syaw + croll * cyaw;
m12 = sroll * cpitch;
m13 = sroll * spitch * cyaw - croll * syaw;
m14 = 0.0f;
m21 = croll * spitch * syaw - sroll * cyaw;
m22 = croll * cpitch;
m23 = croll * spitch * cyaw + sroll * syaw;
m24 = 0.0f;
m31 = cpitch * syaw;
m32 = -spitch;
m33 = cpitch * cyaw;
m34 = 0.0f;
m41 = 0.0f;
m42 = 0.0f;
m43 = 0.0f;
m44 = 1.0f;
}

Matrix Matrix::rotationX(float angle)
{
Matrix m = IDENTITY;
float c = cosf(angle);
float s = sinf(angle);

m.m22 = m.m33 = c;
m.m32 = -s;
m.m23 = s;

return m;
}

Matrix Matrix::rotationY(float angle)
{
Matrix m = IDENTITY;
float c = cosf(angle);
float s = sinf(angle);

m.m11 = m.m33 = c;
m.m31 = s;
m.m13 = -s;

return m;
}

Matrix Matrix::rotationZ(float angle)
{
Matrix m = IDENTITY;
float c = cosf(angle);
float s = sinf(angle);

m.m11 = m.m22 = c;
m.m21 = -s;
m.m12 = s;

return m;
}



## Math

Vec3 degreesToRadians(const Vec3& v)
{
}

Vec3 radiansToDegrees(const Vec3& v)
{
}

float angleDiff(float a, float b)
{
float delta = a - b;
delta = fmodf(delta, PI * 2);
if (delta > PI) return -PI * 2 + delta;
if (delta < -PI) return PI * 2 + delta;
return delta;
}

bool getRayPlaneIntersecion(const Vec3& origin,
const Vec3& dir,
const Vec3& plane_point,
const Vec3& normal,
float& out)
{
float d = dotProduct(dir, normal);
if (d == 0)
{
return false;
}
d = dotProduct(plane_point - origin, normal) / d;
out = d;
return true;
}

bool getRaySphereIntersection(const Vec3& origin,
const Vec3& dir,
const Vec3& center,
Vec3& out)
{
ASSERT(dir.length() < 1.01f && dir.length() > 0.99f);
Vec3 L = center - origin;
float tca = dotProduct(L, dir);
if (tca < 0) return false;
float d2 = dotProduct(L, L) - tca * tca;
if (d2 > radius * radius) return false;
float thc = sqrt(radius * radius - d2);
float t0 = tca - thc;
out = origin + dir * t0;
return true;
}

bool getRayAABBIntersection(const Vec3& origin,
const Vec3& dir,
const Vec3& min,
const Vec3& size,
Vec3& out)
{
Vec3 dirfrac;

dirfrac.x = 1.0f / (dir.x == 0 ? 0.00000001f : dir.x);
dirfrac.y = 1.0f / (dir.y == 0 ? 0.00000001f : dir.y);
dirfrac.z = 1.0f / (dir.z == 0 ? 0.00000001f : dir.z);

Vec3 max = min + size;
float t1 = (min.x - origin.x) * dirfrac.x;
float t2 = (max.x - origin.x) * dirfrac.x;
float t3 = (min.y - origin.y) * dirfrac.y;
float t4 = (max.y - origin.y) * dirfrac.y;
float t5 = (min.z - origin.z) * dirfrac.z;
float t6 = (max.z - origin.z) * dirfrac.z;

float tmin = Math::maximum(
Math::maximum(Math::minimum(t1, t2), Math::minimum(t3, t4)), Math::minimum(t5, t6));
float tmax = Math::minimum(
Math::minimum(Math::maximum(t1, t2), Math::maximum(t3, t4)), Math::maximum(t5, t6));

if (tmax < 0)
{
return false;
}

if (tmin > tmax)
{
return false;
}

out = tmin < 0 ? origin : origin + dir * tmin;
return true;
}



## geometry

Geometry主要的功能包括：碰撞体之间的检测，设置视锥体，透视视锥体，正交视锥体的计算，每个视锥体有六个面，比如我们说的透视视锥体，前，后，左，右，上下；其中前后就是我们通常说的原裁剪面和近裁剪面等等。核心代码如下所示：

void Frustum::computePerspective(const Vec3& position,
const Vec3& direction,
const Vec3& up,
float fov,
float ratio,
float near_distance,
float far_distance,
const Vec2& viewport_min,
const Vec2& viewport_max)
{
ASSERT(near_distance > 0);
ASSERT(far_distance > 0);
ASSERT(near_distance < far_distance);
ASSERT(fov > 0);
ASSERT(ratio > 0);
float scale = (float)tan(fov * 0.5f);
Vec3 right = crossProduct(direction, up);
Vec3 up_near = up * near_distance * scale;
Vec3 right_near = right * (near_distance * scale * ratio);
Vec3 up_far = up * far_distance * scale;
Vec3 right_far = right * (far_distance * scale * ratio);

Vec3 z = direction.normalized();

Vec3 near_center = position + z * near_distance;
Vec3 far_center = position + z * far_distance;

setPoints(*this, near_center, far_center, right_near, up_near, right_far, up_far, viewport_min, viewport_max);
}

void Frustum::computePerspective(const Vec3& position,
const Vec3& direction,
const Vec3& up,
float fov,
float ratio,
float near_distance,
float far_distance)
{
computePerspective(position, direction, up, fov, ratio, near_distance, far_distance, {-1, -1}, {1, 1});
}

void Frustum::computeOrtho(const Vec3& position,
const Vec3& direction,
const Vec3& up,
float width,
float height,
float near_distance,
float far_distance,
const Vec2& viewport_min,
const Vec2& viewport_max)
{
Vec3 z = direction;
z.normalize();
Vec3 near_center = position - z * near_distance;
Vec3 far_center = position - z * far_distance;

Vec3 x = crossProduct(up, z).normalized() * width;
Vec3 y = crossProduct(z, x).normalized() * height;

setPoints(*this, near_center, far_center, x, y, x, y, viewport_min, viewport_max);
}



12-28

09-09 7402
03-19
12-08 9205
07-22 906
11-08
09-11 2185
09-10 1373
12-01 1448
09-12 945
01-27 4413
03-16
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客