如何以快速方式将立方体投影到轴上?

时间:2016-01-21 00:13:45

标签: javascript functional-programming

我要将立方体投影到轴上。基本上,我所做的是将多维数据集的每个顶点的点积与轴进行比较,然后比较结果以找出最小和最大的值。在一天结束时,这两个值将告诉我从轴的哪个点开始投影和结束的位置。我为此写了以下函数;然而,事情是它有很多比较,因为我将调用这个函数数千次,我的整个代码运行得如此之慢。我正在寻找一种优化,使我的代码更快。这个函数有很多比较,我想知道是否有任何方法可以最大限度地减少其中的比较量。有什么想法吗?

代码是用JavaScript编写的,但我正在考虑在C ++和OpenGL上这样做,所以我愿意接受有关不同编程语言的建议。

function projectCube (axis, cube) {

    Pro = dotProdcut(axis, cube.vertex0);
    minPro = Pro;
    maxPro = Pro;

    Pro = dotProdcut(axis, cube.vertex1);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    Pro = dotProdcut(axis, cube.vertex2);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    Pro = dotProdcut(axis, cube.vertex3);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    Pro = dotProdcut(axis, cube.vertex4);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    Pro = dotProdcut(axis, cube.vertex5);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    Pro = dotProdcut(axis, cube.vertex6);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    Pro = dotProdcut(axis, cube.vertex7);
    if (Pro < minPro) { minPro = Pro; }
    if (Pro > maxPro) { maxPro = Pro; }

    return [minPro, maxPro];

}

3 个答案:

答案 0 :(得分:1)

您应该使用分析器来确定花费的时间,然后从那里开始。优化而不会浪费时间。我几乎可以保证你的时间不会花在你想象的地方。

另一方面,比较非常快,算术运算也是如此。更有可能的是,大部分时间花在你的点产品对象上。

答案 1 :(得分:1)

一个想法是矩阵顶点乘法:

[cube.vertex0.x cube.vertex0.y cube.vertex0.z
 cube.vertex1.x cube.vertex1.y cube.vertex1.z
 .
 .
 .
cube.vertex7.x cube.vertex7.y cube.vertex7.z]

multiply with column vector of [axis.x axis.y axis.z]

and return minmax(result)

在C ++中,您可以使用valarray&lt; double&gt;因为它在内部使用矢量化加法和乘法。

valarray<double> vx{cube.vertex0.x, cube.vertex1.x, ..., cube.vertex7.x};
valarray<double> vy{cube.vertex0.y, cube.vertex1.y, ..., cube.vertex7.y};
valarray<double> vz{cube.vertex0.z, cube.vertex1.z, ..., cube.vertex7.z};
valarray<double> result = vx * axis.x;
result += vy * axis.y;
result += vz * axis.z;
return [min(result), max(result)];

答案 2 :(得分:1)

首先,使用局部变量。

第二。不使用枚举属性,而是使用Arrays。您将遇到不同的情况,您必须处理此列表中的每个项目,如果您使用循环,它将更具可读性。

有时候重复自己并且不会将任何东西提取到实用工具方法中会更快,但有时只会提取!

好的函数调用会产生开销,因此会产生性能影响,另一方面,如果你内联所有内容并且函数变得很大,编译器甚至不会尝试优化(执行你的功能。在这里,我们回过头来:用分析器检查你的瓶颈。

然后从对象获取属性(一点点)比访问局部变量更昂贵,但这是优化只会影响你的代码,如果你在一些数学envoirement,你的代码运行几千次/帧。 另一方面,这种做法可以膨胀你的功能,......

试试这个版本:

function projectCube (axis, cube) {
    var x = axis.x, 
        y = axis.y, 
        z = axis.z, 
        v, dotProduct, min = Infinity, max = -Infinity, 
        vertices = cube.vertices;

    //in this example it doesn't matter that i am processing the vertices in reverse order,
    //and so i don't have to introduce a length-var and compare the index to it.
    for(var i = vertices.length; i--; ){
        v = vertices[i];
        dotProduct = x*v.x + y*v.y, z*v.z;
        if(dotProduct < min) min = dotProduct;
        if(dotProduct > max) max = dotProduct;
    }
    return [min, max];
}