如何计算3D物体位置的三个JS和放置物品的场景,使得多个3D对象不相互重叠

问题描述 投票:1回答:1

我工作的货运规划申请,并希望装载货物的集装箱。我创建使用threejs它的3D模型。我完全新的threejs,至今已成功地创建3D对象(货物)和订货量大它们的容器(另一个3D对象)内。我面临的问题是,当我添加容器的那些对象彼此重叠的多个内的3D对象。我不能够计算应设置防止这个重叠问题的正确对象的位置。

利用基本的数学来计算场景中的物体的位置和它,我刚试过。

这里是JS捣鼓它

https://jsfiddle.net/nro48e6u/1/

用于计算对象位置的逻辑被写在仅使用基本的数学的addCargo功能。下面是它的代码

function addCargo(dimension, color, isPallete) {
var dimensionExceed = false; // boolean value that checksifthe cargo dimensions exceed the containerdimension               
if (objects.length == 0) {
    var geometry = new THREE.BoxGeometry(dimension.width, dimension.height, dimension.length);
    var material = new THREE.MeshBasicMaterial({
        color: color
    });
    cargo = new THREE.Mesh(geometry, material);
    wireframe = generateWireframe(geometry);
    default_box_position = {
        x: container_dimension.width / 2 - dimension.width / 2,
        y: dimension.height / 2 - container_dimension.height / 2,
        z: container_dimension.length / 2 - dimension.length / 2
    }
    cargo.position.set(default_box_position.x, default_box_position.y, default_box_position.z);

} else {
    var geometry = new THREE.BoxGeometry(dimension.width, dimension.height, dimension.length);
    var material = new THREE.MeshBasicMaterial({
        color: color,
        wireframe: false
    });
    cargo = new THREE.Mesh(geometry, material);
    wireframe = generateWireframe(geometry);
    cargo.add(wireframe);
    var firstObject = objects[0];
    var xUpdated = false;

    position = {
        x: 0,
        y: 0,
        z: 0
    }
    var startIndex = 0;
    if (palleteDeimension.isSet) {
        position.y = palleteDeimension.height;
        startIndex = 1;
    }
    for (var i = startIndex; i < objects.length; i++) {
        if (!xUpdated || i == objects.length - 1) {
            position.z += parseFloat(objects[i].geometry.parameters.depth);
            xUpdated = false;
        } else {
            xUpdated = false;
            position.z += parseFloat(objects[i].geometry.parameters.depth);
        }
        if (position.z >= container_dimension.length) {
            if (position.z - parseFloat(objects[i].geometry.parameters.depth) + parseFloat(dimension.length) <= container_dimension.length) {
                position.z -= parseFloat(objects[i].geometry.parameters.depth);
            } else {
                position.x += parseFloat(objects[i].geometry.parameters.width);
                position.z = 0;
            }

        } else if (position.z + parseFloat(dimension.length) > container_dimension.length) {
            xUpdated = true;
            position.x += parseFloat(dimension.width);
            position.z = 0;
        }

        if (position.x >= container_dimension.width) {
            position.y += parseFloat(objects[i].geometry.parameters.height);
            position.x = 0;
            position.z = 0;
        } else if (position.x + parseFloat(dimension.width) > container_dimension.width) {
            position.y += parseFloat(dimension.height);
            position.x = 0;
            position.z = 0;
        }
    }
    var z_pos = container_dimension.length / 2 - position.z - (dimension.length / 2);
    var y_pos = position.y - container_dimension.height / 2 + (dimension.height / 2);
    var x_pos = container_dimension.width / 2 - position.x - (dimension.width / 2);
    if (Math.abs(z_pos) <= container_dimension.length / 2 && position.x == 0 && position.y == 0) {
        cargo.position.set(default_box_position.x, default_box_position.y, z_pos);

        if (firstObject.geometry.parameters.width != dimension.width)
            cargo.position.x = x_pos;
        if (firstObject.geometry.parameters.height != dimension.height)
            cargo.position.y = y_pos;
    } else if (Math.abs(y_pos) <= container_dimension.height / 2 && position.x == 0) {
        cargo.position.set(default_box_position.x, y_pos, z_pos);
        if (firstObject.geometry.parameters.width != dimension.width)
            cargo.position.x = x_pos;
    } else
        cargo.position.set(x_pos, y_pos, z_pos);
}
scene.add(cargo);
objects.push(cargo);
initDragCargo();
}

当添加在容器内的多个货物的货物的彼此重叠。我注意到知道如何摆脱掉这种重叠问题。

javascript three.js 3d
1个回答
0
投票

你可以尝试放松法,即在一个无限循环改变一点点每个箱子,直到所有的箱子都高兴。

dx = 0.1;
while(overlap_at_all(boxes)) {
    foreach(var box in boxes) {
        var overlapping_boxes = get_overlapping_boxes(box, boxes);
        foreach(var overlapping_box : overlapping_boxes)
            push_away_boxes(box, overlapping_box, dx);
    }
}

功能“get_overlapping_boxes”做一个碰撞检测检查,并与当前框返回碰撞盒。这可以有效地使用BVH(包围盒层次,如动态AABB-树)或一些其它数据结构来完成。即使是OctTree可以得到很好的效果。这同样适用于功能“overlap_at_all”

函数“push_away_boxes”只是移动两个框在相反方向上具有小距离dx(可以说0.1或10或其他一些可以被认为是“小”相对于箱子的尺寸的)。因此,“push_away_boxes”的一个特定的一对重叠的框中累计应用程序将最终使他们不重叠。该“收敛”一旦达到不再有重叠的盒子。收敛速度可以通过扩大“DX”距离提高,但精度受到影响,规模较大的DX性能越好,但在更差的精度为代价的。

现在,容器箱不考虑。我们可以引入它的盒子“push_away_boxes”功能内的运动作为约束。然而该方法的收敛,不能保证因为约束。所以我们可以给迭代的最大数量的循环,防止无限循环。该解决方案并不能保证,如果有一个解决方案,将被发现。

用的空间最小腰围寻求最优的安排是出于对我的回答范围。

© www.soinside.com 2019 - 2024. All rights reserved.