- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我把事情简化为立方体/一个立方体与一个无限大的质量矩形相撞,下面是代码:
问题是,这些盒子往往旋转过多,粘在一起旋转,如果包含二进制搜索,只需点击并旋转很多。
谢谢你的帮助。
/// <summary>
/// Projects an abstract 1D line "perpendicular" to the axis,
/// stretching across the width of the model,
/// measured from that axis.
/// </summary>
/// <param name="Axis"></param>
/// <param name="Min"></param>
/// <param name="Max"></param>
protected virtual void ProjectToAxis(Vector2 Axis, IMotionData motionData, out double Min, out double Max)
{
Double DotP = Axis.Dot(motionData.PositionGS + (this.Vertices[0].Position * this.Model.Scale).Rotate(motionData.RotationGS));
Min = Max = DotP;
for (int t = 1; t < this.Vertices.Count(); ++t)
{
DotP = Axis.Dot(motionData.PositionGS + (this.Vertices[t].Position * this.Model.Scale).Rotate(motionData.RotationGS));
Min = Math.Min(DotP, Min);
Max = Math.Max(DotP, Max);
}
}
/// <summary>
/// Projects two imaginary lines even with each edge,
/// equal to the width of each object while looking at
/// that edge, then checks to see if they intersect.
/// </summary>
/// <param name="B1"></param>
/// <param name="B2"></param>
/// <returns></returns>
public static bool DetectCollision(Body B1, Body B2, Double elapsedSeconds)
{
CollisionData collisionInfo = new CollisionData();
double lowestDistance = double.MaxValue;
double distance;
Vector2 normalB1ToB2 = (B2.MotionHandler.PositionGS - B1.MotionHandler.PositionGS).Normalized;
foreach (Edge edge in B1.Edges)
{
if (edge.Normal.RelativePosition.Dot(normalB1ToB2) >= 0.0)
{
double minA, minB, maxA, maxB;
B1.ProjectToAxis(edge.Normal.RelativePosition, B1.MotionHandler.MotionDataGet, out minA, out maxA);
B2.ProjectToAxis(edge.Normal.RelativePosition, B2.MotionHandler.MotionDataGet, out minB, out maxB);
if (minA < minB)
distance = minB - maxA;
else
distance = minA - maxB;
if (distance > 0.0f)
return false;
else if (Math.Abs(distance) < lowestDistance)
{
lowestDistance = Math.Abs(distance);
collisionInfo.Normal = edge.Normal.RelativePosition;
collisionInfo.Edge = edge;
}
}
}
Vector2 normalB2ToB1 = -normalB1ToB2;
foreach (Edge edge in B2.Edges)
{
if (edge.Normal.RelativePosition.Dot(normalB2ToB1) >= 0.0)
{
double minA, minB, maxA, maxB;
B1.ProjectToAxis(edge.Normal.RelativePosition, B1.MotionHandler.MotionDataGet, out minA, out maxA);
B2.ProjectToAxis(edge.Normal.RelativePosition, B2.MotionHandler.MotionDataGet, out minB, out maxB);
if (minA < minB)
distance = minB - maxA;
else
distance = minA - maxB;
if (distance > 0.0f)
return false;
else if (Math.Abs(distance) < lowestDistance)
{
lowestDistance = Math.Abs(distance);
collisionInfo.Normal = edge.Normal.RelativePosition;
collisionInfo.Edge = edge;
}
}
}
collisionInfo.Depth = lowestDistance;
/* Double lowHighSeconds = elapsedSeconds;
Double highLowSeconds = 0.0;
Double seconds;
IMotionData md1;
IMotionData md2;
bool collision;
do
{
md1 = B1.MotionHandler.MotionDataLastGet.Copy;
md2 = B2.MotionHandler.MotionDataLastGet.Copy;
collision = true;
lowestDistance = Double.MaxValue;
seconds = MathExtensions.MathExt.Lerp(highLowSeconds, lowHighSeconds, 0.5);
B1.MotionHandler.Simulate(seconds, ref md1);
B2.MotionHandler.Simulate(seconds, ref md2);
normalB1ToB2 = (md2.PositionGS - md1.PositionGS).Normalized;
foreach (Edge edge in B1.Edges)
{
if ((edge.Normal.Position * B1.Model.Scale).Rotate(md1.RotationGS).Dot(normalB1ToB2) >= 0.0)
{
double minA, minB, maxA, maxB;
B1.ProjectToAxis((edge.Normal.Position * B1.Model.Scale).Rotate(md1.RotationGS), md1, out minA, out maxA);
B2.ProjectToAxis((edge.Normal.Position * B1.Model.Scale).Rotate(md1.RotationGS), md2, out minB, out maxB);
if (minA < minB)
distance = minB - maxA;
else
distance = minA - maxB;
if (distance > 0.0f)
collision = false;
else if (Math.Abs(distance) < lowestDistance)
{
lowestDistance = Math.Abs(distance);
collisionInfo.Normal = (edge.Normal.Position * B1.Model.Scale).Rotate(md1.RotationGS);
collisionInfo.Edge = edge;
}
}
}
normalB2ToB1 = -normalB1ToB2;
foreach (Edge edge in B2.Edges)
{
if ((edge.Normal.Position * B2.Model.Scale).Rotate(md2.RotationGS).Dot(normalB2ToB1) >= 0.0)
{
double minA, minB, maxA, maxB;
B2.ProjectToAxis((edge.Normal.Position * B2.Model.Scale).Rotate(md2.RotationGS), md2, out minA, out maxA);
B1.ProjectToAxis((edge.Normal.Position * B2.Model.Scale).Rotate(md2.RotationGS), md1, out minB, out maxB);
if (minA < minB)
distance = minB - maxA;
else
distance = minA - maxB;
if (distance > 0.0f)
collision = false;
else if (Math.Abs(distance) < lowestDistance)
{
lowestDistance = Math.Abs(distance);
collisionInfo.Normal = (edge.Normal.Position * B2.Model.Scale).Rotate(md2.RotationGS);
collisionInfo.Edge = edge;
}
}
}
collisionInfo.Depth = lowestDistance;
if (!collision)
{
lowHighSeconds = seconds;
}
else
{
highLowSeconds = seconds;
}
} while (Math.Abs(highLowSeconds - lowHighSeconds) > 0.0001);
B1.MotionHandler.MotionDataSet = md1;
B2.MotionHandler.MotionDataSet = md2; */
// bool flip = false;
if (collisionInfo.Edge.Parent != B2.Model)
{
Body temp = B1;
B1 = B2;
B2 = temp;
}
//This is needed to make sure that the collision normal is pointing at B1
int Sign = Math.Sign(
collisionInfo.Normal.Dot(
B1.MotionHandler.MotionDataGet.PositionGS + (B1.Center * B1.Model.Scale).Rotate(B1.MotionHandler.MotionDataGet.RotationGS) -
B2.MotionHandler.MotionDataGet.PositionGS + (B2.Center * B2.Model.Scale).Rotate(B2.MotionHandler.MotionDataGet.RotationGS)
)
);
//Remember that the line equation is N*( R - R0 ). We choose B2->Center
//as R0; the normal N is given by the collision normal
if (Sign != 1)
collisionInfo.Normal = -collisionInfo.Normal; //Revert the collision normal if it points away from B1
double SmallestD = double.MaxValue; //Initialize the smallest distance to a high value
//Measure the distance of the vertex from the line using the line equation
for (int t = 0; t < B1.Vertices.Count(); ++t)
{
double Distance = collisionInfo.Normal.Dot(B1.Vertices[t].WorldPosition - B2.Center);
// If the measured distance is smaller than the smallest distance reported
// so far, set the smallest distance and the collision vertex
if (Distance < SmallestD)
{
SmallestD = Distance;
collisionInfo.Vertex = B1.Vertices[t];
}
}
if ((Body.CollisionType & CollisionType.Velocity) > 0)
{
Vector2 vab1 = B1.MotionHandler.VelocityGS - B2.MotionHandler.VelocityGS;
Vector2 rap = (B1.MotionHandler.PositionGS - collisionInfo.Normal);
Vector2 rbp = (B2.MotionHandler.PositionGS - collisionInfo.Normal);
Double rap2 = (rap.Cross(collisionInfo.Normal));
Double rbp2 = (rbp.Cross(collisionInfo.Normal));
Vector2 one = (collisionInfo.Vertex.WorldPosition - B1.MotionHandler.PositionGS).GetPerpendicular;
Vector2 two = (collisionInfo.Vertex.WorldPosition - B2.MotionHandler.PositionGS).GetPerpendicular;
Double j = (-(1 + 0.0) * vab1.Dot(collisionInfo.Normal)) /
((collisionInfo.Normal.Dot(collisionInfo.Normal) * (B1.MotionHandler.InverseMassGS + B2.MotionHandler.InverseMassGS)) +
(one.Dot(one) * B1.MotionHandler.InverseInertiaGS) + (two.Dot(two) * B2.MotionHandler.InverseInertiaGS));
B1.MotionHandler.AddImpulse = new Force(
collisionInfo.Normal,
j /* ,
one */
);
B2.MotionHandler.AddImpulse = new Force(
collisionInfo.Normal,
-(j) /* ,
two */
);
NewtonianMotionData data1 = (NewtonianMotionData)B1.MotionHandler.MotionDataGet;
NewtonianMotionData data2 = (NewtonianMotionData)B2.MotionHandler.MotionDataGet;
data1.AngularVelocity += (one.Dot(j * collisionInfo.Normal)) * data1.inverseInertia;
data2.AngularVelocity += (two.Dot(-j * collisionInfo.Normal)) * data2.inverseInertia;
B1.MotionHandler.MotionDataSet = data1;
B2.MotionHandler.MotionDataSet = data2;
}
return true;
}
最佳答案
你有两个问题。
1)代码有问题。你得把它修好。
2)你不知道如何找出什么是“某物”。
解决第一个问题取决于你解决第二个问题。你需要学习如何调试你刚刚编写的程序。
你已经测试过了,得到了一个你认为是荒谬的结果。这是很好的第一步。现在把它分解得更远。在这个领域选择一个简单的问题,你可以用铅笔和纸自己解决;这样做,然后看着你的算法在调试器中解决相同的问题,检查一路上的每一步。倾听无声的、喋喋不休的怀疑。当有任何事情看起来有点不对劲或出乎意料时,停止你正在做的事情并调查这个问题,直到你了解事情是否正常工作。最终你会发现一个步骤,那里的事情不是他们应该的,这就是错误所在。
是的,这很乏味。当你发现并修复了这个bug之后,停下来思考一下是什么原因导致你首先编写了这个bug,然后想办法不再编写这种bug。
更新:
回复:你最近的评论。
接受道歉。现在冷静下来。如果你搞砸了,你永远也找不到这个虫子。你的大脑不会让你。处于惊慌失措、精疲力竭状态的人失去了推理的能力。这就是为什么防火门是向外开的;从着火的建筑物里逃出来的人不会停下来想“我推着这扇门,它没有打开,也许我应该试试拉”。他们只是用力推。我猜你是在使劲推。
调试需要理性和对小细节的仔细关注。如果你们都对这个问题感到厌烦,那么这个问题就会变得更糟。从一个去过那里的人那里拿走。我们都去过那里。在你自己的程序中造成一个你找不到的错误是一件非常令人沮丧的事情。
没人帮你是因为…好吧,让我列出一组先决条件,我必须满足这些先决条件,才能帮助您解决一些含糊不清的陈词滥调,以及如何集中精力进行调试的建议:
1)我必须了解一些有关三维物理模拟的知识。1992年,我对牛顿力学中的简单微分方程有了相当好的理解,但此后我再也没有使用过。阻尼驱动弹簧方程与刚体碰撞方程有很大的不同。如果我花几个星期复习笔记,我可以把数学找回来,但那不现实。你需要有人谁是非常熟悉的三维碰撞物理模拟现在。
2)为了解决我不熟悉的问题,我必须能够阅读和理解你的代码,这些代码有几百行长,是由我以外的人编写的。更糟糕的是,有一百行代码被注释掉了。为什么?相关吗?虫子在里面吗?此外,我需要能够阅读和理解代码,而无需在调试器中运行它。见鬼,我甚至不能编译那段代码。这取决于我没有的图书馆。
更糟糕的是,其中一个库可能包含这个bug。据我所知,这个bug是某个代码中的一个错误,它计算了一个你没有向我们展示的正常值。显示的代码可能是完美的。
3)我需要有空闲时间来解决别人的难题;编写代码并理解物理的人在这个问题上毫无进展。
所有这些都是需求;如果缺少其中任何一个,读者就无法有效地帮助您。你在请求你不认识的人帮你在午夜的黑暗仓库里找到一只没有手电筒的黑猫——一只可能根本不在那里的猫。你很少有人接电话也就不足为奇了。在74个读过您的问题的堆栈溢出用户中,有多少人满足这三个要求?我一个也没见过。
如果你想在这个网站上得到帮助,那就发布一个更简单的问题。把问题缩小到一个需要较少的物理和模拟算法的专门知识,并且只有相关代码的问题,最好是可以编译和运行的代码。
关于c# - 我正在尝试使基本碰撞动力学起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2219809/
我有一个加号/减号按钮,希望用户不能选择超过 20 个但不知道如何让它工作。我尝试使用 min="1"max="5 属性,但它们不起作用。这是我的代码和一个 fiddle 链接。https://jsf
我正在尝试复制顶部底部图,如示例 here但它没有正确渲染(紫色系列有 +ve 和 -ve 值,绿色为负值)留下杂乱的人工制品。我也在努力创建一个玩具示例来复制这个问题,所以我希望尽管我缺乏数据,但有
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 6 年前。 社区去年审查了是
这个问题在这里已经有了答案: Adding two positive integers gives negative answer.Why? (4 个答案) 关闭 5 年前。 我遇到了一个奇怪的问题
有谁知道如何将字符串值类型 -4,5 或 5,4 转换为 double -4.5 或 5.4? 最佳答案 只需使用 Double.parseDouble(Locale, String); 糟糕,我很困
我正在尝试根据 TextBlob 分类插入一个仅包含“正”或“负”字符串的新数据框列:对于我的 df 的第一行,结果是 ( pos , 0.75, 0.2499999999999997)我想要' 正
我对 VBA 非常陌生,无法理解如何在一个循环中完成 2 个任务。我非常感谢您的帮助。 我已经能够根据第 3 列中的数据更改第 2 列中的数值,但我不明白如何将负值的字体更改为红色。 表格的大小每月都
欢迎, 我正在使用 jquery 通过 POST 发送表单。 这就是我获得值(value)的方式。 var mytext = $("#textareaid").val(); var dataStrin
double d = 0; // random decimal value with it's integral part within the range of Int32 and always p
我有这个字符串: var a='abc123#xyz123'; 我想构建 2 个正则表达式替换函数: 1) 用 '*' 替换所有确实有 future '#'的字符(不包括'#') 所以结果应该是这样的
我正在使用 DialogFragment。当用户从 Gmail 平板电脑应用程序的屏幕与下面示例图片中的编辑文本进行交互时,我希望正面和负面按钮保持在键盘上方。 在我的尝试中不起作用,这是我的 Dia
从组装艺术一书中,我复制了这句话: In the two’s complement system, the H.O. bit of a number is a sign bit. If the H.O
是否有更好更优雅的方法来实现下面的简单代码(diffYear、A 和 B 是数字): diffYear = yearA - yearB; if (diffYear == 0) { A = B
我正在设计一种语言,并尝试确定 true 应该是 0x01 还是 0xFF。显然,所有非零值都将转换为 true,但我正在尝试确定确切的内部表示。 每种选择的优点和缺点是什么? 最佳答案 没关系,只要
在我的 dialogfragment 类的 OnCreateDialog 中,我正在这样做: AlertDialog.Builder builder = new AlertDialog.Builder
这个问题在这里已经有了答案: Resolving ambiguous overload on function pointer and std::function for a lambda usin
我偶然发现了一个奇怪的 NSDecimalNumber 行为:对于某些值,调用 integerValue、longValue、longLongValue 等,返回意想不到的值(value)。示例: l
这个问题在这里已经有了答案: Resolving ambiguous overload on function pointer and std::function for a lambda using
我有这个正则表达式来测试用户输入是否有效: value.length === 0 || value === '-' || (!isNaN(parseFloat(value)) && /^-?\d+\.
我想用高斯混合模型拟合数据集,数据集包含大约 120k 个样本,每个样本有大约 130 个维度。当我使用 matlab 执行此操作时,我运行脚本(簇号为 1000): gm = fitgmdist(d
我是一名优秀的程序员,十分优秀!