0
\$\begingroup\$

I'm working on a 3D-project with three.js and webGl. I've written a function to check for 2 objects to be near each other and thus "snap" to each other.

The objects don't move on the Y-axis, so I only have to check the 4 sides of each object against the side of all other objects in the scene. At the moment I'm doing that with this code:

for (var i = 0; i < elements.length; i++) {

            var newBox = updateBoundingBox(elements[i]);

            var snapped = null;

            if (newBox.min.x - box.max.x < 5 && newBox.min.x - box.max.x > -box.size().x / 2//5
                && box.max.z > newBox.min.z && box.min.z < newBox.max.z) {

                activeElement.position.x = newBox.min.x - ((box.max.x - box.min.x) / 2) - 0.5;
                box = updateBoundingBox(activeElement);
                snapped = [elements[i], "X"];
            }

            if (newBox.min.z - box.max.z < 5 && newBox.min.z - box.max.z > -box.size().z / 2//5
                && box.max.x > newBox.min.x && box.min.x < newBox.max.x) {

                activeElement.position.z = newBox.min.z - ((box.max.z - box.min.z) / 2) - 0.5;
                box = updateBoundingBox(activeElement);
                snapped = [elements[i], "Z"];

            }

            if (box.min.x - newBox.max.x < 5 && box.min.x - newBox.max.x > -box.size().x / 2
                && box.max.z > newBox.min.z && box.min.z < newBox.max.z) {

                activeElement.position.x = newBox.max.x + ((box.max.x - box.min.x) / 2) + 0.6;
                box = updateBoundingBox(activeElement);
                snapped = [elements[i], "X"];

            }

            if (box.min.z - newBox.max.z < 5 && box.min.z - newBox.max.z > -box.size().z / 2
                && box.max.x > newBox.min.x && box.min.x < newBox.max.x) {

                activeElement.position.z = newBox.max.z + ((box.max.z - box.min.z) / 2) + 0.5;
                box = updateBoundingBox(activeElement);
                snapped = [elements[i], "Z"];

            }

            if (snapped != null) {

                activeElement.snapped.push(snapped);
                debug.snapped = true;
            }


}

But, it is very obvious that the 4 if-statements are almost identical, so I was wondering if it was possible to write them in a better/shorter way so I can just loop over them?

\$\endgroup\$
1
\$\begingroup\$

1) Do not hard-code the distance that will define 'near', but rather make it a variable/parameter.
2) Split the solution : 1) do we 'approximatively' overlap ? and 2) are we on the left or right, and are we up or down ?
3) Use as much 'standard' code as you can : here 'update' will define a BBox based on a list of points, 'expand' and 'overlaps' will do what-you-guess.

var nearDistance = 5;
var newBox new BoundingBox();
var boxSize = null;

for (var i = 0; i < elements.length; i++) {
            var thisElement = elements[i];

            // newBox is now the BBox of thisElement
            newBox.update(thisElement);

            // do we approximatively overlap ?
            newBox.expand(nearDistance);    
            var overlaps = newBox.overlaps(box);    
            if (!overlaps) continue;

            // are we on the left/right, up/down ??

            newBox.expand(-nearDistance);
            boxSize = box.size() ;  

            var newXPosition = -1, newZPosition = -1;

            if ( newBox.min.x - box.max.x > -boxSize.x / 2) {    
                // left
                newXPosition = newBox.min.x - ((box.max.x - box.min.x) / 2) - 0.5;
            } else {
                // right
               newXPosition = newBox.max.x + ((box.max.x - box.min.x) / 2) + 0.6;
            }

            if (newBox.min.z - box.max.z > -boxSize.z / 2 ) {    
                // up
                newZPosition = newBox.min.z - ((box.max.z - box.min.z) / 2) - 0.5;    
            } else {
                // down
                newZPosition= newBox.max.x + ((box.max.x - box.min.x) / 2) + 0.6;
            }                        

            //adjust position
            activeElement.position.x = newXPosition ;
            activeElement.position.z = newZPosition;

            box.update(activeElement);

            activeElement.snapped.push( /* thisElement was snapped */);
            debug.snapped = true;
            }    
}
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.