C语言光线追踪器中任意方向圆锥体法向量求解问题
任意方向圆锥体的法向量求解方法
几何原理梳理
圆锥的法向量需要结合其径向方向和轴线方向计算:
- 设圆锥顶点为
P0(即cone.coordinate),轴线方向向量为dir(需归一化),高度为h,底面半径r = diameter/2,半角正切值tanθ = r/h。 - 对于命中点
P,先计算顶点到命中点的向量V = P - P0。 - 将
V分解为平行于轴线的分量V_parallel和垂直于轴线的分量V_perpendicular。 - 法向量由径向单位向量(垂直于轴线的方向)和轴线方向向量按比例组合后归一化得到。
完整实现代码
t_vec_3 cone_normal(t_point hitpoint, t_cone cone) { t_vec_3 V; t_vec_3 cone_dir; double h; double r; double tan_theta; double h_proj; t_vec_3 V_perp; t_vec_3 radial_dir; t_vec_3 normal; // 初始化核心参数 h = cone.height; r = cone.diameter / 2.0; tan_theta = r / h; // 确保圆锥方向向量为单位向量 cone_dir = cone.vector; normalize_vec(&cone_dir); // 计算顶点到命中点的向量V V = set_vec( hitpoint.x - cone.coordinate.x, hitpoint.y - cone.coordinate.y, hitpoint.z - cone.coordinate.z ); // 计算V在圆锥轴线上的投影长度 h_proj = dot_product(V, cone_dir); // 计算V垂直于轴线的分量 V_perp.x = V.x - h_proj * cone_dir.x; V_perp.y = V.y - h_proj * cone_dir.y; V_perp.z = V.z - h_proj * cone_dir.z; // 处理命中点在轴线上的特殊情况(理论上极少出现) if (V_perp.x == 0 && V_perp.y == 0 && V_perp.z == 0) return cone_dir; // 归一化垂直分量得到径向单位向量 normalize_vec(&V_perp); radial_dir = V_perp; // 组合径向与轴线向量得到法向量 normal.x = radial_dir.x / tan_theta - cone_dir.x * tan_theta; normal.y = radial_dir.y / tan_theta - cone_dir.y * tan_theta; normal.z = radial_dir.z / tan_theta - cone_dir.z * tan_theta; // 归一化最终法向量 normalize_vec(&normal); return normal; }
依赖补充
需要实现点积函数用于向量投影计算:
double dot_product(t_vec_3 a, t_vec_3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
内容的提问来源于stack exchange,提问作者coromo
相关产品推荐
相关产品推荐

