球体与球体之间的碰撞(C++)
Sphere to sphere collision (C++)
我正在实现一些基本的3D物理引擎。对于球体到球体的碰撞,我正在遵循本教程。我对 2 个移动球体有问题。我想我发现"缩短速度"的方式可能存在一些问题
bool collidingDSmove(Sphere sphere){
// Early Escape test: if the length of the movevec is less
// than distance between the centers of these circles minus
// their radii, there's no way they can hit.
在我的测试场景中,速度矢量是(-2,-4,-2)和(1,2,1)。因此,"shortVel"实际上变得大于原始速度。
vec3 shortVel = sphere.velocity.substract(velocity);
vec3 fromAtoBCenter = position.substract(sphere.position);
float distSquare = fromAtoBCenter.getLengthSquare();
float sumRadii = (radius + sphere.radius);
distSquare -= sumRadii*sumRadii;
if (shortVel.getLengthSquare() < distSquare){
return false;
}
// Normalize the movevec
vec3 N = shortVel.normalize();
// Find C, the vector from the center of the moving
// circle A to the center of B
vec3 C = sphere.position.substract(position);
// D = N . C = ||C|| * cos(angle between N and C)
float D = N.dot(C);
// Another early escape: Make sure that A is moving
// towards B! If the dot product between the movevec and
// B.center - A.center is less that or equal to 0,
// A isn't isn't moving towards B
if (D <= 0){
return false;
}
// Find the length of the vector C
float lengthCSquare = C.getLengthSquare();
float F = (lengthCSquare)-(D * D);
// Escape test: if the closest that A will get to B
// is more than the sum of their radii, there's no
// way they are going collide
float sumRadiiSquared = sumRadii * sumRadii;
if (F >= sumRadiiSquared){
return false;
}
// We now have F and sumRadii, two sides of a right triangle.
// Use these to find the third side, sqrt(T)
double T = sumRadiiSquared - F;
// If there is no such right triangle with sides length of
// sumRadii and sqrt(f), T will probably be less than 0.
// Better to check now than perform a square root of a
// negative number.
if (T < 0){
return false;
}
// Therefore the distance the circle has to travel along
// movevec is D - sqrt(T)
float distance = D - sqrt(T);
// Get the magnitude of the movement vector
float mag = velocity.getLength();
// Finally, make sure that the distance A has to move
// to touch B is not greater than the magnitude of the
// movement vector.
if (mag < distance){
return false;
}
//*** 金额不在 0 和 1 之间
float amount = shortVel.normalize().getLength() / velocity.getLength();
// Set the length of the movevec so that the circles will just
// touch
velocity = velocity.normalize().times(amount);
sphere.velocity = sphere.velocity.normalize().times(amount);
return true;
}
我的 vec3 类如下:
class vec3 {
public:
float x; float y; float z;
vec3() : x(0), y(0), z(0) { }
vec3 substract(vec3 v){
vec3 sub;
sub.x = x - v.x;
sub.y = y - v.y;
sub.z = z - v.z;
return sub;
}
float getLength() {
return sqrt(x*x + y*y + z*z);
}
float getLengthSquare() {
return x*x + y*y + z*z;
}
vec3 normalize(){
vec3 n;
n.x = x / getLength();
n.y = y / getLength();
n.z = z / getLength();
return n;
}
float dot(vec3 v) {
return x*v.x + y*v.y + z*v.z;
}
}
你能解释一下我在这里做错了什么吗?
这是我的更新功能。其中 deltaT 在 2 帧之间延时
void updateVelocity(double deltaT){
velocity.x = velocity.x + acceleration.x*deltaT;
velocity.y = velocity.y + acceleration.y*deltaT;
velocity.z = velocity.z + acceleration.z*deltaT;
}
void updatePosition(double deltaT){
position.x = position.x + velocity.x * deltaT + 0.5 * acceleration.x * deltaT * deltaT;
position.y = position.y + velocity.y * deltaT + 0.5 * acceleration.y * deltaT * deltaT;
position.z = position.z + velocity.z * deltaT + 0.5 * acceleration.z * deltaT * deltaT;
}
void update(double deltaT){
updateVelocity(deltaT);
updatePosition(deltaT);
}
首先,在 vec3 中创建加法和时间函数。
如果球体s1 和球体 s2 碰撞,位置为 p (vec3)、速度 v (vec3)、半径 r(浮点)和质量 m(浮子),您可以执行以下操作:
// from s1 to s2
vec3 pDiff = s2.p.subtract(s1.p);
// collision detection
if (pDiff.getLength() >= s1.r + s2.r) {
return;
}
// find direction from s1 to s2
vec3 dir = pDiff.normalize();
vec3 vDiff = s2.v.subtract(s1.v);
float fellingSpeed = vDiff.dot(dir);
// don't collide in this case
if (fellingSpeed >= 0) {
return;
}
// perfect spheric collision
float speed1 = (2 * s2.m * fellingSpeed) / (s1.m + s2.m);
float speed2 = (fellingSpeed * (s2.m - s1.m)) / (s1.m + s2.m);
s1.v = s1.v.add(dir.times(speed1));
s2.v = s2.v.add(dir.times(speed2 - fellingSpeed));
我希望它有所帮助。
相关文章:
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- 在cuda线程之间共享大量常量数据
- 在c代码之间共享数据的最佳方式
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 大小相等但成员数量不同的结构之间的性能差异
- 类与私有变量的其他类之间的线程安全性
- 如何在cpp文件之间切换窗口?在Qt中
- 线程之间的布尔停止信号
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 构造函数和转换运算符之间的重载解析
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数