我正在尝试玛雅的一个剧本,看看我是否可以获得重力和那个使用球形物体的那个,目前它工作正常(尝试制作月球和地球以扩展并校准重力效果),但我想尝试更进一步并添加碰撞以使物体互相反弹,但是在昨天看了好几年之后,我发现它很难用2d物体,更不用说3d了。
我设法编写了一个可以检测到碰撞的位,它可以获取两个对象之间的距离并将其与两个对象的半径进行比较,这似乎有效(虽然需要重写),但我无法弄清楚是什么做下一个。说实话,我甚至不确定是否有可能在没有一些高级大学知识的情况下做这样的事情,这就是我最终放弃的原因:P
只是想知道它是如何工作的,这里是主要部分的当前阶段 - objSel [j]是当前选择的对象,allObjects是除了当前所选对象之外的所有对象
def moveObjects(originalTime,objSel,objMultiplySize):
moveAmounts = []
crashed = False
for j in range(len(objSel)):
#get initial values
originalVelocity = getVelocity(objSel[j],originalTime,objMultiplySize)
objVolume = getVolume(objSel[j],objMultiplySize)
allObjects = selectAllOtherObjects(objSel[j], objSel)
#calculate gravity effect on object
xDist = 0
yDist = 0
zDist = 0
for i in range (0, len(allObjects) ):
attraction = calcuateForce(objSel[j],allObjects[i],objMultiplySize)
distanceFromObj = getDistance(allObjects[i],objSel[j],objMultiplySize)[1]
xDist += distanceFromObj[0] * attraction / (objVolume*2.15*math.pi)
yDist += distanceFromObj[1] * attraction / (objVolume*2.15*math.pi)
zDist += distanceFromObj[2] * attraction / (objVolume*2.15*math.pi)
gravityEffect = [xDist,yDist,zDist]
newX = (originalVelocity[0]+gravityEffect[0])/objMultiplySize
newY = (originalVelocity[1]+gravityEffect[1])/objMultiplySize
newZ = (originalVelocity[2]+gravityEffect[2])/objMultiplySize
newVelocity = [newX,newY,newZ]
moveAmounts.append( newVelocity )
#-----------this whole bit needs rewriting--------
py.currentTime( originalTime + 1, edit = True, update = True)
for j in range(len(moveAmounts)):
#collision detection
allObjects = selectAllOtherObjects(objSel[j], objSel)
originalRadius = getRadius(objSel[j],objMultiplySize)
for i in range (0, len(allObjects) ):
objRadius = getRadius(allObjects[i],objMultiplySize)
objDistance = getDistance(allObjects[i],objSel[j],objMultiplySize)
if objDistance[0] < objRadius + originalRadius:
force1 = moveAmounts[j][0]*objMultiplySize * objRadius
print "Crashed"
crashed = True
if crashed != True:
#move object
py.move( objSel[j], float(moveAmounts[j][0]), float(moveAmounts[j][1]), float(moveAmounts[j][2]), relative = True )
py.setKeyframe( objSel[j], attribute='translateX')
py.setKeyframe( objSel[j], attribute='translateY')
py.setKeyframe( objSel[j], attribute='translateZ')
else:
#dunno what to do here
for i in range (0, len(allObjects) ):
mass1 = getVolume(allObjects[i],objMultiplySize)
velocity1 = getVelocity(allObjects[i],originalTime,objMultiplySize)
mass2 = getVolume(objSel[j],objMultiplySize)
velocity2 = getVelocity(objSel[j],originalTime,objMultiplySize)
m1v1m2v2X = mass1*velocity1[0] + mass2*velocity2[0]
m1v1m2v2Y = mass1*velocity1[1] + mass2*velocity2[1]
m1v1m2v2Z = mass1*velocity1[2] + mass2*velocity2[2]
totalMass = mass1+mass2
答案 0 :(得分:2)
引用http://en.wikipedia.org/wiki/Elastic_collision:
for i in range (0, len(allObjects) ):
mass1 = getVolume(allObjects[i],objMultiplySize)
velocity1 = getVelocity(allObjects[i],originalTime,objMultiplySize)
mass2 = getVolume(objSel[j],objMultiplySize)
velocity2 = getVelocity(objSel[j],originalTime,objMultiplySize)
v1new = velocity1; //just initialization
v2new = velocity2; //just initialization
v1new[0] = (velocity1[0] *( mass1-mass2) + 2*mass2*velocity2[0])/(mass1 + mass2);
v2new[0] = (velocity2[0] *( mass2-mass1) + 2*mass1*velocity1[0])/(mass1 + mass2);
v1new[1] = (velocity1[1] *( mass1-mass2) + 2*mass2*velocity2[1])/(mass1 + mass2);
v2new[1] = (velocity2[1] *( mass2-mass1) + 2*mass1*velocity1[1])/(mass1 + mass2);
v1new[2] = (velocity1[2] *( mass1-mass2) + 2*mass2*velocity2[2])/(mass1 + mass2);
v2new[2] = (velocity2[2] *( mass2-mass1) + 2*mass1*velocity1[2])/(mass1 + mass2);
假设弹性碰撞,您可以分别对每个维度进行碰撞计算。
答案 1 :(得分:1)
虽然托马斯的碰撞是一个很好的,简单的弹性碰撞方程,但在行星体的尺度上,没有弹性碰撞这样的东西。或者,我应该说,行星本身不会弹性碰撞。而不是将行星视为大型弹力球,更准确的类比是将它们视为大而droplets of water。虽然不完全相同,但水滴和行星碰撞时的相互作用方式有很多相似之处。
可以看到能够产生这种结果的数学的快速例证here。虽然这种模拟不是天体特有的,但“柔软”碰撞背后的基本原理仍然适用。
我也为自己制作了一个版本,它有不同的模拟参数,完整的构造活动和火山,虽然没有万有引力,(使它滞后太多 - 我只有一个重力井在中心)所以它赢了不会形成任何大卫星。你可以下载它来检查/玩here,如果你愿意的话(你可以用鼠标抓住行星的大块扔掉它; g 打开/关闭重力井)。请记住,围绕中心形成的行星绕行的“彗星”巨大。如果地球的大小与地球大小相同,那么这些彗星至少会与德克萨斯大小相当。
虽然我链接的两个模拟都是用java编写的,但是相同的数学和物理可以用于任何语言。
答案 2 :(得分:0)
首先,它似乎更像是一个数学问题,而不是一个python问题,因为相同的基本原理适用于任何语言。
其次,如果你的所有物体都是球形的,那么你不需要实际检测到真正的碰撞,但实际上只是检查物体中心之间的距离是否小于它们的半径之和。你可以使用这个函数快速获得这个距离(如果你的空间是欧几里德)(我在你的代码中没有看到):
def get_distance(obj1, obj2):
# euclidean distance in three dimensions:
return ( (obj2.x-obj2.x)**2 + (obj2.y-obj2.y)**2 + (obj2.z-obj2.z)**2 ) ** 0.5
现在,根据我的理解,你想要BOUNCE对象。根据定义,这要求对象具有VELOCITY属性,该属性是具有方向和大小的向量。更新对象位置时,还必须更新其速度(很可能是从其先前位置)。
最后,当你弹跳时,你必须考虑物体位置,它的速度矢量,以及指向它碰撞的另一个物体中心的归一化矢量。然后,你将执行一些矢量算术来获得它的新速度矢量。
(更新):如果对象具有不同的质量,并且你想要一个逼真的弹跳,那么在托马斯的回答中使用Ellastic Collision概念!
所以,作为进一步的研究“方向”,我建议:
希望这有帮助!