⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geometry.cpp

📁 国外游戏开发者杂志2003年第七期配套代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

    return result;
}

Vector3 Transformer::transform_point(Vector3 const &p) {
    return current_transform->transform(p);
}

Vector3 Transformer::backtransform_point(Vector3 const &p) {
    const Matrix4 *const &t = current_transform;
    Vector3 mid;
    mid.x = p.x;
    mid.y = p.y;
    mid.z = p.z;

    const double *const row_0 = t->coef[0];
    const double *const row_1 = t->coef[1];
    const double *const row_2 = t->coef[2];

    mid.x -= row_0[3];
    mid.y -= row_1[3];
    mid.z -= row_2[3];

    Vector3 result;
    result.x = mid.x * row_0[0] + mid.y * row_1[0] + mid.z * row_2[0];
    result.y = mid.x * row_0[1] + mid.y * row_1[1] + mid.z * row_2[1];
    result.z = mid.x * row_0[2] + mid.y * row_1[2] + mid.z * row_2[2];

    return result;
}

void Transformer::transform_point(Vector3 const &p, Vector3 *result) {
    const Matrix4 *const &t = current_transform;

    const double *const row_0 = t->coef[0];
    const double *const row_1 = t->coef[1];
    const double *const row_2 = t->coef[2];

    result->x = p.x * row_0[0] + p.y * row_0[1] + p.z * row_0[2]
		+ row_0[3];

    result->y = p.x * row_1[0] + p.y * row_1[1] + p.z * row_1[2]
		+ row_1[3];

    result->z = p.x * row_2[0] + p.y * row_2[1] + p.z * row_2[2]
		+ row_2[3];
}

Vector3 Transformer::transform_point_rotate_only(Vector3 const &p) {
    Matrix4 *t = current_transform;
    float x, y, z;

    x = p.x * t->coef[0][0] + p.y * t->coef[0][1] + p.z * t->coef[0][2];
    y = p.x * t->coef[1][0] + p.y * t->coef[1][1] + p.z * t->coef[1][2];
    z = p.x * t->coef[2][0] + p.y * t->coef[2][1] + p.z * t->coef[2][2];

    Vector3 result(x, y, z);

    return result;
}


void Matrix3::set(Quaternion q) {
    double Nq = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
    double s = (Nq > 0.0) ? (2.0 / Nq) : (0.0);

    double xs = q.x * s;
    double ys = q.y * s;
    double zs = q.z * s;

    double wx = q.w * xs;
    double wy = q.w * ys;
    double wz = q.w * zs;

    double xx = q.x * xs;
    double xy = q.x * ys;
    double xz = q.x * zs;

    double yy = q.y * ys;
    double yz = q.y * zs;
    double zz = q.z * zs;

    coef[0][0] = 1.0 - (yy + zz);
    coef[0][1] = xy - wz;
    coef[0][2] = xz + wy;

    coef[1][0] = xy + wz; 
    coef[1][1] = 1.0 - (xx + zz);
    coef[1][2] = yz - wx;

    coef[2][0] = xz - wy;
    coef[2][1] = yz + wx;
    coef[2][2] = 1.0 - (xx + yy);
}

void Matrix3::concat(Matrix3 *other) {
    int i, j, k;
    double accum;

    double new_coef[3][3];

    for (i = 0; i < 3; i++) {
		for (j = 0; j < 3; j++) {
			accum = 0;
			for (k = 0; k < 3; k++) {
				accum += other->coef[i][k] * coef[k][j];
			}

			new_coef[i][j] = accum;
		}
    }

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
			coef[i][j] = new_coef[i][j];
		}
    }
}

void Matrix3::identity() {
    coef[0][0] = 1.0;
    coef[0][1] = 0.0;
    coef[0][2] = 0.0;

    coef[1][0] = 0.0;
    coef[1][1] = 1.0;
    coef[1][2] = 0.0;

    coef[2][0] = 0.0;
    coef[2][1] = 0.0;
    coef[2][2] = 1.0;
}

Vector3 lerp(const Vector3 &p0, const Vector3 &p1, double fraction) {
    Vector3 result;
    result.x = p0.x + fraction * (p1.x - p0.x);
    result.y = p0.y + fraction * (p1.y - p0.y);
    result.z = p0.z + fraction * (p1.z - p0.z);

    return result;
}

inline Quaternion lerp(const Quaternion &p0, const Quaternion &p1, double fraction) {
    Quaternion result;
    result.x = p0.x + fraction * (p1.x - p0.x);
    result.y = p0.y + fraction * (p1.y - p0.y);
    result.z = p0.z + fraction * (p1.z - p0.z);
    result.w = p0.w + fraction * (p1.w - p0.w);

    return result;
}

Quaternion slerp(Quaternion &start, Quaternion &end, double t) {
    // Input quaternions should be unit length or else
    // something broken will happen.

    // The technique below will work for input vectors of any
    // number of dimensions (you could write a templatized version
    // of the code, or one that takes a generic N-vector data type,
    // and it would just work).


    // Compute the cosine of the angle between the two vectors.
    double dot = dot_product(start, end);

    const double DOT_THRESHOLD = 0.9995;
    if (dot > DOT_THRESHOLD) {
        // If the inputs are too close for comfort, linearly interpolate
        // and normalize the result.
        Quaternion result = lerp(start, end, t);
        result.normalize();
        return result;
    }

    Clamp(dot, -1, 1);
    double theta_0 = acos(dot);  // Angle between input vectors
    double theta = theta_0 * t;  // Angle between 'start' and result

    Quaternion e1 = start;
    Quaternion e2 = end - start * dot;
    e2.normalize();              // { e1, e2 } is now an orthonormal basis

    return (e1 * cos(theta)) + (e2 * sin(theta));
}



inline double safe_acos(double x) {
    Clamp(x, -1, 1);
    return acos(x);
}

inline double safe_asin(double x) {
    Clamp(x, -1, 1);
    return asin(x);
}


void Quaternion::set_from_axis_and_angle(double _x, double _y, double _z,
										 double theta) {
    Vector3 vec(_x, _y, _z);
    vec.normalize();

    theta *= 0.5;
    double st = sin(theta);
    double ct = cos(theta);

    x = vec.x * st;
    y = vec.y * st;
    z = vec.z * st;
    w = ct;
}


Quaternion Quaternion::scale(float factor) {
    Quaternion result;
    result.x = x * factor;
    result.y = y * factor;
    result.z = z * factor;
    result.w = w * factor;

    return result;
}

void Quaternion::normalize() {
    double sum;

    sum = (double) w * (double) w + 
		(double) x * (double) x + 
		(double) y * (double) y + 
		(double) z * (double) z;

	assert(sum > 0);
	if (sum == 0) return;
	
    double ilen = 1.0 / sqrt(sum);

    w = w * ilen;
    x = x * ilen;
    y = y * ilen;
    z = z * ilen;
}

void Vector3::normalize() {
    double dx, dy, dz;

    dx = (double) x;	
    dy = (double) y;
    dz = (double) z;

    double sq = sqrt(dx * dx + dy * dy + dz * dz);
	assert(sq > 0);
    if (sq == 0) return;

	double factor = 1.0 / sq;
    x = dx * factor;
    y = dy * factor;
    z = dz * factor;
}

void Vector2::normalize() {
    double dx, dy;

    dx = (double) x;	
    dy = (double) y;

    double sq = sqrt(dx * dx + dy * dy);
	assert(sq > 0);
    if (sq == 0) return;

	double factor = 1.0 / sq;
    x = dx * factor;
    y = dy * factor;
}

void Vector3::safe_normalize() {
    double dx, dy, dz;

    dx = (double) x;	
    dy = (double) y;
    dz = (double) z;

    double sq = sqrt(dx * dx + dy * dy + dz * dz);
    if (sq == 0) return;  // @Numerical: Want some kind of epsilon here.

	double factor = 1.0 / sq;
    x = dx * factor;
    y = dy * factor;
    z = dz * factor;
}

float Vector3::length() {
    double dx,dy,dz;

    dx = (double) x;	
    dy = (double) y;
    dz = (double) z;

    float sq = (float)sqrt(dx * dx + dy * dy + dz * dz);
    return sq;
}

void Plane3::normal_set(Vector3 *p1, Vector3 *p2, Vector3 *p3){
    double v1_x,v1_y,v1_z;
    double v2_x,v2_y,v2_z;
    double nx,ny,nz;
    double len;

    v1_x = (double) p3->x - p2->x;
    v1_y = (double) p3->y - p2->y;
    v1_z = (double) p3->z - p2->z;

    v2_x = (double) p1->x - p2->x;
    v2_y = (double) p1->y - p2->y;
    v2_z = (double) p1->z - p2->z;

    nx = (v1_y * v2_z - v1_z * v2_y);
    ny = (v1_z * v2_x - v1_x * v2_z);
    nz = (v1_x * v2_y - v1_y * v2_x);

    len = sqrt((nx*nx) + (ny*ny) + (nz*nz));
  
    nx = nx/len;
    ny = ny/len;
    nz = nz/len;

    a = nx;
    b = ny;
    c = nz;
    d = -(a*p1->x + b*p1->y + c*p1->z);
}


void Plane3::normalize() {
    double da,db,dc,dd;

    da = (double) a;
    db = (double) b;
    dc = (double) c;
    dd = (double) d;

    double len = sqrt(da * da + db * db + dc * dc);
    double ilen = 1.0 / len;

    a = da * ilen;
    b = db * ilen;
    c = dc * ilen;
    d = dd * ilen;
}

double distance(const Vector3 &p1, const Vector3 &p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    double dz = p2.z - p1.z;

    return sqrt(dx * dx + dy * dy + dz * dz);
}

float arctan2(float y, float x) {
    if (x == 0.0) {
        return (y < 0) ? (-M_PI/2) : (M_PI/2);
    }

    return (float)atan2(y, x);
}



void Matrix4::copy_33(Matrix3 *rm) {
    int j, i;
    for (j = 0; j < 3; j++) {
        for (i = 0; i < 3; i++) {
			coef[i][j] = rm->coef[i][j];
		}
    }
}

void orthonormalize(Vector3 *v, Vector3 *w) {
    v->normalize();
    double dot = dot_product(*v, *w);

    Vector3 proj = *v;
    proj.scale(dot);
    *w -= proj;

    w->normalize();
}



float Matrix3::invert() {
    double a = coef[0][0];
    double b = coef[0][1];
    double c = coef[0][2];
    double d = coef[1][0];
    double e = coef[1][1];
    double f = coef[1][2];
    double g = coef[2][0];
    double h = coef[2][1];
    double i = coef[2][2];

    double det3;
    det3 = a * (e*i - f*h) + d * (h*c - b*i) + g * (b*f - c*e);
    
    if (det3 == 0) return 0;
    assert(det3 != 0.0);

    double factor = 1.0 / det3;

    coef[0][0] =  (e * i - f * h) * factor;
    coef[1][0] = -(d * i - f * g) * factor;
    coef[2][0] =  (d * h - e * g) * factor;
    coef[0][1] = -(b * i - c * h) * factor;
    coef[1][1] =  (a * i - c * g) * factor;
    coef[2][1] = -(a * h - b * g) * factor;
    coef[0][2] =  (b * f - c * e) * factor;
    coef[1][2] = -(a * f - c * d) * factor;
    coef[2][2] =  (a * e - b * d) * factor;

    return det3;
}

void Matrix3::transpose() {
    double b = coef[0][1];
    double c = coef[0][2];
    double d = coef[1][0];
    double f = coef[1][2];
    double g = coef[2][0];
    double h = coef[2][1];

    coef[1][0] = b;
    coef[2][0] = c;
    coef[0][1] = d;
    coef[2][1] = f;
    coef[0][2] = g;
    coef[1][2] = h;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -