问题
So how can I constraint movement of my object ONLY in a Sphere? I tried with the bounding box and the intersection method but it doesn't seem to work?
Edit 1 :
this was not a question... i was asking this: i have 2 bounding spheres, one big and one small , the small will be moving inside the big but i dont want it to go outside the big bounding sphere how do i do it?
回答1:
The distance of the center of the small sphere from the center of the big sphere must never be more than (BigRadius - SmallRadius). If you want to calculate the position where contact is made, you can scale the movement vector by the ratio of the difference in radii needed to make contact and the total difference in radii from starting point to ending point (unless the movement is large enough to cross a plane defined by one of the big bounding sphere's axis)
class Sphere {
public Vector3 Pos;
public double Radius;
}
void Test()
{
Sphere big = new Sphere() { Pos = new Vector3(0, 0, 0), Radius = 10.0 };
Sphere small = new Sphere() { Pos = new Vector3(8, 0, 0), Radius = 1.0 };
Vector3 move = new Vector3(0, 10, 0);
// new position without check, if within sphere ok
Vector3 newPos = small.Pos + move;
if (Vector3.Distance(newPos, big.Pos) < big.Radius - small.Radius)
return;
// diff in radius to contact with outer shell
double space = (big.Radius - small.Radius) - Vector3.Distance(small.Pos, big.Pos);
// movement past moment of hitting outer shell
double far = Vector3.Distance(newPos, big.Pos) - (big.Radius - small.Radius);
// scale movement by ratio to get movement to hit shell
move = move * (space / (space + far));
newPos = small.Pos + move;
}
I think this will work UNLESS the movement crosses a plane defined by one of the coordinates of the big sphere and moves outside. Maybe you could add special checking for sign of movement X, Y, or Z being different than big.Pos - small.Pos (relative position of small sphere center to big sphere center) X, Y or Z...
回答2:
There's a faster way of making sure the center distance doesn't exceed the radius difference. It doesn't require taking a square root every time.
Precompute max_distance_squared
whenever one of the radiuses are set or changed, and store it somewhere it can be reused:
local max_distance = big.radius - small.radius
max_distance_squared = max_distance*max_distance
Now you can omit taking the square root to get the distance:
local dx = big.center_x - small.center_x
local dy = big.center_y - small.center_y
if (dx*dx + dy*dy <= max_distance_squared)
# great
else
# explode
The time saved can increase your frame rate or simulation speed a bit.
回答3:
if (Vector3.Distance(bigSphere, smallSphere) < bigSphereradius - smallSphereradius) {
// inside
}
Or use the BoundingSphere class:
http://msdn.microsoft.com/en-us/library/bb195373.aspx
ps. if vectors are normalized then radiuses must be too :)
来源:https://stackoverflow.com/questions/5737440/object-in-spherebounding-sphere-want-it-to-restrict-movement-within-sphere