2013-07-11 2 views
1

Я пытаюсь создать сценарий в майа, чтобы узнать, могу ли я получить гравитацию и этот участок, работающий со сферическими объектами, и в настоящее время он отлично работает (пытался сделать луну и землю масштабировать и откалибровать гравитацию к этому), но я хотел бы попытаться сделать это еще дальше и добавить коллизии, чтобы объекты отскакивали друг от друга, но, оглядевсь по сторонам вчера, я обнаружил, что это сложно с объектами 2d, не говоря уже о 3d.

Мне удалось написать бит, который может обнаружить столкновение, где он получает расстояние между обоими объектами и сравнивает его с радиусом обоих объектов, который, кажется, работает (требуется переписать хотя), но я не мог выяснить, что делать дальше. Честно говоря, я даже не уверен, что это возможно сделать с чем-то вроде этого без каких-либо передовых университетских знаний, поэтому я в конце концов отказался от этого: P

Просто для того, чтобы понять, как это работает, вот текущий этап основная часть - objSel [у] является текущим выбранным объектом, AllObjects все, кроме текущего выбранного объектаУравнение столкновений для двух 3D-объектов

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 

ответ

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

Предполагая, что упругое столкновение, вы можете выполнять вычисление столкновений для каждого размер отдельно.

+0

Эй, жаль, что так долго не было ответа, но спасибо большое, именно то, что я искал (я думаю): DI пытался сделать расчет m1 * v1 + m2 * v2, но не мог понять, как Чтобы решить эту проблему: p Сначала мне нужно переписать часть кода, но прежде чем я смогу ее протестировать, но это не должно быть слишком сложно, поэтому я надеюсь, что это сработает; D – Peter

0

Прежде всего, это больше похоже на математическую проблему, чем на проблему с python, поскольку такое же обоснование будет работать на любом языке.

Во-вторых, если все ваши объекты являются сферическими, вам не нужно фактически обнаруживать TRUE COLLISION, но на самом деле просто проверить, меньше ли расстояние между объектными центрами, чем сумма их радиуса. Вы можете быстро получить эту дистанцию ​​(если пространство евклидово) с этой функцией (который я видел нету определенных в коде):

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 

Теперь от того, что я понял, вы хотите, чтобы подпрыгнуть объекты. Это требует, по определению, чтобы в любой момент объект имел свойство VELOCITY, которое является вектором с направлением и величиной. Когда вы обновляете позицию объекта, вы также должны обновлять его скорость (скорее всего, из предыдущей позиции).

Наконец, когда вы отскакиваете, вам нужно рассмотреть положение объекта, его вектор скорости и нормированный вектор, который указывает на центр другого объекта, с которым он сталкивается. Затем вы можете выполнить некоторую векторную арифметику, чтобы получить новый вектор скорости.

(ОБНОВЛЕНИЕ): если объекты имеют разные массы, и вы хотите реалистичное подпрыгивание, используйте концепты Ellastic Collision в ответ Томаса!

Так что, как дальнейшие исследования «направления», я предлагаю:

  • Изучение некоторых основных векторных операций, специально скалярное произведение и векторное произведение (вы будете рады, что вы сделали после того, как вы «получить» это);
  • Рассмотрите СИЛЬНО, используя Numpy, который очень удобен для векторов и векторных операций, так что вам не придется реализовывать множество вещей, и это намного быстрее, чем все, что вы могли бы сделать вручную. Вам не нужно все это изучать, выучите достаточно, чтобы решить вашу проблему.

Надеюсь, это поможет!

+0

Эй, спасибо за ответ , способ, которым я получил расстояние, в значительной степени точно так же, как вы предложили ха-ха, но я также оставил значения x, y, z, если они были необходимы :) Скорость также вычисляется более или менее одинаково, пропуская назад кадр и вычитание значений из текущего кадра, досадно, я не знаю, как это сделать без ручного обновления рамки, поэтому объекты с 5+ имеют тенденцию занимать несколько секунд для 100 кадров: P Но да, спасибо, я проверю из продукта th которые вы предложили в ближайшее время, должны придерживаться python, хотя, поскольку он находится в пределах майи :) – Peter

+0

@Peter Когда я говорю о Numpy, это числовая библиотека, которая будет использоваться в python, вам нужно импортировать ее. Я видел значительное улучшение скорости с помощью Numpy, потому что, когда вы выполняете операцию с большим массивом точек, она как бы обрабатывает все точки одновременно, а не внутри цикла (это называется векторизация). Например, если у вас есть точка, представленная как массив 3x1, и набор из N точек, представленных как массив 3xN, вы можете выполнить операцию с точкой и вектором N точек и получить другой вектор с результатами (скажем, расстояний) с помощью одного вызова функции. – heltonbiker

+0

Ahh, извините, я просто посмотрел на него, ожидая загрузки, но, похоже, немного сложнее настроить ага, я определенно займусь этим еще, мои знания все еще немного базовые в данный момент, хотя на данный момент я Я просто попытался заставить его работать: D Что вы сказали об векторизации, хотя, только наполовину поняли это - просто скажем, что у меня было 20 000 значений, часть другого кода назначает цвета, пропустив один раз, получив высокий/низкие значения, а затем снова пробегает, чтобы правильно применить шейдеры, будет ли векторная обработка работать при первом вычислении, но не во втором? – Peter

1

В то время как столкновение Томаса - хорошее, простое упругое уравнение столкновения, в масштабах планетных тел, нет такого понятия, как упругое столкновение. Или, скажем так, сами планеты не сталкиваются упруго. Вместо того, чтобы думать о планетах, как если бы они были большими упругими шарами, более точная аналогия думает о них, как если бы они были большими droplets of water. Хотя они не полностью идентичны, существует много сходства между каплями воды и планетами в том, как они взаимодействуют, когда они сталкиваются.

Хорошая, быстрая иллюстрация математики, которая даст такой результат, можно увидеть here. Хотя эта симуляция не специфична для небесных тел, основные принципы, лежащие в основе «мягких» столкновений, по-прежнему применяются.

Я также сделал его версию для себя с различными параметрами симуляции, в комплекте с тектонической активностью и вулканами, хотя нет универсальной силы тяжести (это слишком сильно заглохлоло - все, что у меня есть, гравитационная скважина в центре), поэтому не образует больших лун. Вы можете загрузить его, чтобы изучить/сыграть с here, если хотите (вы можете использовать мышь, чтобы захватить куски планеты, чтобы бросить на нее: g включает и выключает гравитацию). Имейте в виду, что эти «кометы», вращающиеся вокруг планеты, которая формируется в центре, являются огромными. Если бы планета была размером с Землю, эти кометы были бы, по крайней мере, размером с техас.

Хотя оба симулятора, с которыми я связан, были написаны в java, одна и та же математика и физика могут применяться на любом языке.

+0

Эй, человек, большое спасибо за ответ, несколько раз, когда я использовал этот сайт, я был удивлен тем, насколько полезны вы, ребята, здесь: D Это скорее персональный проект, так что упругие столкновения должны (может быть, я сделаю что-то более необычное, как только я на самом деле заработаю), но да, тесто очень круто вместе с его другими проектами, и ваш тоже приличный, вы должны были уйти в возможность иметь универсальную гравитацию, хотя :) Я вернусь и посмотрю код, как только я получу лучшее понимание java и этой партии, немного на моей голове в настоящее время aha – Peter

+0

@Peter Я действительно пытался реализовать универсальный гравитация в нем (оригинальное тесто не имело его), но по какой-то причине, независимо от того, как я это сделал, он, похоже, не мог работать. Я понятия не имею, почему это ему не понравилось. Даже вероятностное гравитация (для каждой точки, выбирайте другую точку в случайном порядке и буксируйте первую точку к ней) заставили ее сломаться. Не удалось выяснить, как избавиться от ограничительной рамки на краю экрана, по тем же причинам. – AJMansfield

Смежные вопросы