查找圆锥法线

Find cone normal

提问人:coromo 提问时间:9/24/2023 最后编辑:coromo 更新时间:9/26/2023 访问量:69

问:

我实际上是在 c 中制作光线追踪器。我需要根据生命值找到圆锥的法线。我的函数是这样的原型:

t_vec_3 cone_normal(t_point hitpoint, t_cone cone);

Cone 结构包含以下信息:

struct    s_cone
{
    t_point    coordinate;
    t_vec_3    vector;
    double    diameter;
    double    height;
    t_color    color;
    t_material    material;
};

我尝试了几种解决方案,但在所有情况下,它们仅在圆锥向量等于 (0, 1, 0) 时才有效。

我的函数目前看起来像这样,但它只有在圆锥体笔直时才有效。

t_vec_3    cone_normal(t_point hitpoint, t_cone cone)
{
    t_vec_3    tmp;
    t_vec_3    result;

    tmp = set_vec(hitpoint.x - cone.coordinate.x, 0, hitpoint.z - cone.coordinate.z);
    calculate_norm(&tmp);
    tmp.x/= tmp.norme;
    tmp.z/= tmp.norme;
    normalize_vec(&tmp);
    result = set_vec(tmp.x * cone.height / (cone.diameter / 2), \
    (cone.diameter / 2) / cone.height, tmp.z * cone.height / (cone.diameter / 2));
    normalize_vec(&result);
    return (result);
}

编辑:

我忘了指定calculate_norm和normalize_vec代码。

double  calculate_norm(t_vec_3 *vec)
{
    double  norm;

    norm = sqrt(pow(vec->x, 2) + pow(vec->y, 2) + pow(vec->z, 2));
    vec->norme = norm;
    return (norm);
}

void    normalize_vec(t_vec_3 *vec)
{
    double  norm;

    norm = calculate_norm(vec);
    vec->x = vec->x / norm;
    vec->y = vec->y / norm;
    vec->z = vec->z / norm;
}
C 数学 图形 光线追踪

评论

0赞 Mike 'Pomax' Kamermans 9/27/2023
这回答了你的问题吗?垂直于圆锥体的表面

答:

0赞 Simon Goater 9/24/2023 #1

您知道 cone.height 和 cone.diameter,因此您知道顶点的角度(从侧面到轴)。

tan(apexangle) = cone.diameter / (2*cone.height)

一旦你有了单位向量 ihat 和 jhat,它们分别在轴方向指向命中点和沿轴,那么单位法线 nhat 必须

nhat = ihat * cos(apexangle) + jhat * sin(apexangle)

您可以通过除以 cos 来仅通过一次三角计算来做到这一点

nhat * sec(apexangle) = ihat + jhat * (cone.diameter / (2*cone.height))

jhat 只是你的归一化 cone.vector(我假设),而 ihat 是归一化的

(hitpoint - cone.coordinate)- ((hitpoint - cone.coordinate).jhat)jhat.

评论

0赞 coromo 9/25/2023
对不起,但我不明白“ihat”、“jhat”和“nhat”到底对应什么。而且我不明白在我的函数中在哪里实现这一点。
0赞 Rohan Bari 9/25/2023
@coromo 我猜它们是单位向量。
0赞 Simon Goater 9/25/2023
我假设向量从底部指向顶点(与 Spektre 的答案相反)。如果相反,则 jhat 被归一化 -cone.vector。
0赞 Spektre 9/25/2023 #2

我是这样看的:

cone

p0是圆锥位置,是中心轴单位矢量,是你在曲面上的命中点,是未知法线。您可以利用交叉产品:tpn

q = dot(t,p-p0);                                     // distance of p projected onto central axis and p0
     if (q<=0.0) n=-t;                               // special case hit point is equal to p0
else if (q>=cone_height) n=+t;                       // special case hit point is on base of cone
else n = (+/-) normalize(cross(cross(t,p-p0),p-p0)); // normal case

符号只是决定法线是向外还是向内,懒得评估它应该是 + 还是 - 所以,如果法线指向内,只需否定或交换其中一个叉积中的操作数......(+/-)

评论

0赞 coromo 9/25/2023
我试图实现你所解释的内容,但它不起作用。在圆锥体上,就好像没有光一样
0赞 Spektre 9/25/2023
@coromo这很可能只是正常指向与照明预期相反的方向,因此只需否定正常情况下的正常情况:或使用双面照明......如果它有任何区别。如果它仍然不起作用,请尝试渲染法线,同时查看输入是否也正常n = - normalize(cross(cross(t,p-p0),p-p0));np,p0,t
0赞 Spektre 9/25/2023
看到没有递归光线追踪就不可能反射和折射了吗? 看看调试渲染,你可以尝试做类似的事情......
0赞 coromo 9/26/2023 #3

我想出了如何找到正常的代码,我不会精确解释代码,但这是我是如何做到的

t_vec_3 cone_normal(t_ray camray, t_point hitpoint, t_cone cone)
{
    double  k;
    double  scalar;
    t_vec_3 result;
    t_vec_3 tmp;

    k = tan((cone.diameter / 2) * M_PI / 180.0);
    tmp = set_vec(camray.origin.x - cone.coordinate.x, camray.origin.y - \
        cone.coordinate.y, camray.origin.z - cone.coordinate.z);
    scalar = scalar_product(camray.direction, set_vec(hitpoint.x, hitpoint.y, \
        hitpoint.z)) + scalar_product(tmp, cone.vector);
    tmp = set_vec(hitpoint.x + camray.origin.x, hitpoint.y + camray.origin.y, \
        hitpoint.z + camray.origin.z);
    result = minus_vec(minus_vec(tmp, set_vec(cone.coordinate.x, \
        cone.coordinate.y, cone.coordinate.z)), multip_vec(cone.vector, \
        ((1 + pow(k, 2.0))) * scalar));
    normalize_vec(&result);
    return (result);
}

评论

0赞 Sergio Solorzano 9/28/2023
解释每种方法的作用的注释可以帮助社区中阅读解决方案的每个人