Check if object is close

Hi guys, I’m trying to play an animation to a spatial that is close to the camera.

So I tried to do an IF with some condition:

Vector3f dir = boss.getLocalTranslation().subtract(cam.getLocation()).normalize();

if (dir.x <= 0.2f && dir.z <= 0.2f){
    //Code that play the animation
}

The problem is that I’m going to do a lot of condition in the if. My question is if there is a simpler and efficient way to this?

Use distance.

float distance = FastMath.abs(cam.getLocation().distance(boss.getLocalTranslation());

if (dist <= 0.2f) {
    // do something
}

https://javadoc.jmonkeyengine.org/v3.3.0-beta1/com/jme3/math/Vector3f.html#distance-com.jme3.math.Vector3f-

3 Likes

Thanks it works fine!

2 Likes

it’s not more efficient, than TC proposed. two float comparisons + vector substraction are cheaper than one float comparison + distance (wich uses sqrt).

In this instance I think he meant efficient as in “less verbose” than “mathematically”.

Your code is very efficient. But it’s broken. dir is normalized. it means that sqrt(x*x + z*z) = 1. There are no any combination of x and y that matches this equation and the condition you’ve wrote at the same time.
Just do not normalize and you will get correct and efficient boss proximity check.

The only more efficient solution is to keep temp Vector3f for substraction and use subtractLocal. But please do not do such optimizations before you have a benchmark to prove it’s reasonability, because it makes code very ugly and buggy.

1 Like

Also keep in mind, that checking the x and z distance is an approximation. You are drawing a square around the player. Where the square root (distance) method is more accurate as it draws a circle. It may or may not matter depending on how accurate you want the distance check to be.

1 Like

You can drop the abs() because the distance cannot be negative.

Also distanceSquared() cannot be negative so you can do spherical distance checks without taking the square root:

final float maxDistanceSquared = 0.2f * 0.2f;
if(v1.distanceSquared(v2) <= maxDistanceSquared) {...}
5 Likes

I almost always do it like this. Sqrt can be really slow if done too many times a frame. Most of the time you’re not looking for exact distance but a comparison (is this distance less than this distance) and distSquared works fine for that.

2 Likes

Back when I first started programming, the rule was “avoid sqrt at all costs” to the point where C code would often implement ‘close approximations’, either with lookup tables or like Quake did with an equation that approximated the curve ‘enough’. I mean, back then a CPU could take something like 250+ cycles to calculate sqrt. Division was also really bad and on the “avoid if possible” list.

On modern CPUs, these operations are still expensive but not anything like what they were. In fact, sqrt is very close to division in performance now… both of which are like 13-14x slower than add or multiply. But keep in mind that on average at the CPU level an add or mult is 1 cycle. So it’s not that bad.

I would say the modern guidance on both sqrt and division would be “avoid if possible”. And consider it in your algorithms.

So, yes, if all you are doing is comparing the distance of objects to some fixed constant then 100% definitely do what @1000ml suggests. It basically costs you nothing to do it and turns it into all mutiplies.

Also, if you have some algorithm that requires you to do distance checks between all objects in the scene then it is better to organize the data spatially such that you can avoid large swaths of comparisons. (That’s more or less true, sqrt or not.)

But in modern CPU architecture, sqrt is not as poison as it used to be. So don’t go to extreme measures to avoid it… but if the sqrt isn’t really necessary anyway, then don’t do it. (Same with division… in an inner loop: better to multiply by a precalculated 1/value than to divide by value)

6 Likes