两个三维物体的碰撞方程

2024-09-27 07:35:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在maya中尝试一个脚本,看看我是否可以得到重力和其他一些球形物体,目前它工作得很好(尝试了使月球和地球按比例缩放并校准重力效果),但我想尝试更进一步,并添加碰撞,使对象彼此反弹,但是昨天在四处找了很久,我发现二维物体已经够难的了,更不用说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

Tags: inpytrueforlenrange物体mass1
3条回答

引用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);

假设存在弹性碰撞,则可以分别为每个标注进行碰撞计算。在

首先,它看起来更像是一个数学问题,而不是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

现在,据我所知,你想要弹跳物体。根据定义,这要求物体在任何时刻都具有速度特性,即具有方向和大小的向量。更新对象位置时,还必须更新其速度(很可能是从其先前的位置)。在

最后,当你反弹的时候,你必须考虑物体的位置,它的速度向量,以及一个规范化的向量,它指向另一个物体的中心。然后,你需要执行一些向量运算来得到新的速度向量。在

(更新):如果物体有不同的质量,你想要一个真实的反弹,那么使用托马斯的回答中的埃拉斯碰撞概念!在

因此,作为进一步研究的“方向”,我建议:

  • 学习一些基本的向量运算,特别是点积和叉积(你会很高兴你做了之后,你“得到”它)
  • 考虑强烈地使用Numpy,它以非常方便的方式实现向量和向量操作,这样您就不必实现很多东西,而且它比任何手工操作都要快。你不必把所有的东西都学完,只需要学会足够的知识就可以解决你的问题。在

希望这有帮助!在

虽然托马斯的碰撞是一个很好的,简单的弹性碰撞方程,但在行星体的尺度上,没有弹性碰撞这回事。或者,我应该说,行星本身并没有弹性碰撞。与其把行星想象成大而有弹性的球,更准确的类比是把它们想象成大的droplets of water。虽然不是完全相同,但水滴和行星在碰撞时的相互作用方式有很多相似之处。在

一个好的,快速的数学解释,将产生这种结果可以看到here。虽然这种模拟并不是针对天体的,但“粘性”碰撞背后的基本原理仍然适用。在

我还用不同的模拟参数为自己制作了一个版本,里面有构造活动和火山,尽管没有万有引力(使它滞后太多——我只有一个中心的重力井),所以它不会形成任何大卫星。如果你想的话,你可以下载它来研究/玩here(你可以用鼠标抓起行星的一大块碎片扔给它;g打开/关闭重力井)。请记住,在中心形成的围绕行星运行的“彗星”是巨大的。如果这颗行星有地球那么大,那么这些彗星至少有德克萨斯州那么大。在

虽然我链接到的两个模拟都是用java编写的,但同样的数学和物理可以应用于任何语言。在

相关问题 更多 >

    热门问题