在C中的圆柱上的纹理映射(构建光线跟踪器)

时间:2017-03-06 14:57:01

标签: c algorithm mapping textures raytracing

这是我在这里的第一个问题,所以我希望我做得对。

我正在尝试为学校项目构建光线跟踪器,并且我想在我的基本形状中添加一些纹理贴图。我已经为球体做了它并且它完美地工作,这是我使用的算法(UV映射):

d = vector3d_normalize(vector3d_sub(hit->point, object->position));
u = 0.5 + atan2(d.z, d.x) / M_PI * 0.5;
v = 0.5 - asin(d.y) / M_PI;

对于气缸,我找不到任何算法,所以我尝试不同的东西,但我不能使它工作。实际上,当它固定在(x:0,y:0,z:0)时,它适用于圆柱体,但是从我在空间中移动它的那一刻起,纹理看起来很拉伸。

对于此时的代码,它包含以下内容:

d = vector3d_sub(hit->point, vector3d_mult(object->position, ray->direction));
u = 0.5 + atan2(d.z, d.x) / M_PI * 0.5;
v = d.y / M_PI;
v = v - floor(v);

(0,0,0)中的圆柱:img

使用翻译:img

如果你有任何想法,我会陷入困境,这对我有很大的帮助!

1 个答案:

答案 0 :(得分:0)

以下是Jamis's Buck的 Ray Tracer Challenge (强烈推荐)中的一些伪代码:

    // Based off of pseudocode from Jamis Buck: http://raytracerchallenge.com/bonus/texture-mapping.html
    // Input: point on the cylinder. The cylinder is assumed to be of radius 1, centered at the origin and parallel with the y axis.
    // Output: (u,v) with u and v both between 0 and 1.
    // u will vary from 0 to 1 with the azimuthal angle, counter-clockwise.
    // v will vary from 0 to 1 with whole units of y; note that the cylinder will have to be scaled by PI in the y axis to prevent stretching
    map_cylinder_point_to_uv(point: (x: float, y: float, z: float)) -> (float, float) {
        // compute the azimuthal angle, -PI < theta <= PI
        float theta = arctan2(point.x, point.z);
        // convert from radians to units
        // -0.5 < rawU <= 0.5
        float rawU = theta / (2 * Constants.PI)
        // convert to correct scale, and flip it so that u increases with theta counter-clockwise
        // 0 <= u < 1
        float u = 1 - (rawU + 0.5);

        // v will vary from 0 to 1 between whole units of y
        // Use whatever modulus method or operator your language has to gauarantee a positive value for v.
        // It's different for every programming language: https://en.wikipedia.org/wiki/Modulo_operation#In_programming_languages
        float v = point.y % 1

        return (u, v)
    }

您的问题可能与以下事实有关:您在圆柱体上放置了正方形纹理,并且应用于圆柱体侧面的纹理的长度将是2 PI(圆的周长)的倍数。您只需通过PI或2 PI在y轴上缩放圆柱即可解决您的问题。

如果您不希望局限于特定尺寸的圆柱,并且具有可以像方格图案一样重复的纹理,则可以缩放v以防止拉伸。将此行替换上面的v计算,

// let v go from 0 to 1 between 2*pi units of y
let v = point.y % (2 * Constants.PI) * 1 / (2 * Constants.PI);

我还将注意到,最近几天,计算机图形的堆栈交换可能比SO更有用:https://computergraphics.stackexchange.com/