Следы от ног - Кватернионы)

Программирование на Юнити.

Следы от ног - Кватернионы)

Сообщение Slava 10 фев 2010, 04:44

Untitled1.jpg

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

var rotationL : Quaternion = leftFoot.rotation; и var positionL :Vector3 = leftFoot.position;

Начинаю инстансиировать - но сначала делаю рэйкаст вниз на небольшое расстояние и получаю точку на поверхности земли, ее положение hitL.point и ее вектор вверх hitL.normal:

var hitL : RaycastHit;
if (Physics.Raycast(positionL, -Vector3.up, hitL, distance, layerMask.value)) {
Instantiate(bloodFootprintL, hitL.point, rotationL);
}

Поставлен след в точке пересечения рэйкаста, а его вращение соответствует вращению ноги в момент касания с землей. Локомоушн конечно стремится выравнивать ноги по поверхности земли, но получается не всегда ровно. Но главное есть - направление вперед у следа.

А вот как теперь, а может еще до Instantiate, сохранив направление следа вперед, выровнять его с поверхностью земли, т.е. не трогая одну ось...??????????///
У кости стопы и у префаба соответственно - ось Х смотрит вверх, Y - вперед.
пробовал делать такую штуку - rotationL = Quaternion.FromToRotation(Vector3.right, -hitL.normal); - выравнивать ось Х с нормалью поверхности - но меняется направление следа - они всегда направлены в одну сторону - Y тоже выравнивается...
У вас нет доступа для просмотра вложений в этом сообщении.
Добавить slava-1234 в Skype
Slava
UNIт
 
Сообщения: 135
Зарегистрирован: 05 апр 2009, 05:14

Re: Следы от ног - Кватернионы)

Сообщение Paul Siberdt 10 фев 2010, 09:36

Вектор-нормаль всегда ориентирован по Z (или по Y, нипомнююю) в направлении мирового нуля. Если поверхность плоская, после переориентации по нормали, обьект нужно панировать (поворот вокруг вертикальной оси). Нужный угол придется запоминать из того же локомоушена (высчитывать из дирекшен-векторов).

Если поверхность кривая - придется строить проекцию дирекшен векторов на поверхность и снова получать угол панирования.
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Следы от ног - Кватернионы)

Сообщение Slava 10 фев 2010, 16:02

Я собственно щас так и делаю - сначала ставлю след в нормаль к поверхности, потом пытаюсь повернуть его в направлении движения.
Тут ведь дело в деталях, принцип то понятен.
Вот собственно сам скрипт, сейчас проблема в направлении следа - если бежать по кругу, направление следа незначительно меняется, но в основном смотрит в сторону мирового игрек. чтото не то с заданием угла, я думаю что пытаюсь найти угол между одним вращением в локальных а другим в мировых коорд - var angleL и var angleR. А как правильно то сделать...
Длинно получилось, незнаю, можно ли это осилить...))

Код: Выделить всё
var bloodFootprintL : GameObject; //prefab of left footprint
var bloodFootprintR : GameObject; //prefab of right footprint
var waterFootprintL : GameObject; //prefab of left footprint
var waterFootprintR : GameObject; //prefab of right footprint
var numberOfFootprints : int = 6;
var footprintLOffset = Vector3.zero;
var footprintROffset = Vector3.zero;
var layerMask : LayerMask = 0;   // select layers for your footprints here

private var leftFoot : Transform;   //left foot bone of your character
private var rightFoot : Transform;   //right foot bone of your character
private var controller : CharacterController;
private var distance : float = 0.5;
private var footprintLTimer = -1.0;
private var footprintRTimer = -1.0;
private var numberL : int;
private var numberR : int;
private var stepNrL : int = 0;
private var stepNrR : int = 0;
private var start : boolean = false;
private var blood : boolean;
private var water : boolean;
private var rotationL : Quaternion;
private var rotationR : Quaternion;

function Start () {
   controller = GetComponent(CharacterController);
   legAnimator = GetComponent("LegAnimator");
   for (var leg=0; leg<legAnimator.legs.Length; leg++) {
      if (leg == 0)
         leftFoot = legAnimator.legs[leg].ankle;
      if (leg == 1)
         rightFoot = legAnimator.legs[leg].ankle;
   }
   numberL = numberOfFootprints;
   numberR = numberL;
}

function Update () {
   legAnimator = GetComponent("LegAnimator");
   
   if (numberL == 0 && numberR == 0) {
      start = false;
   }
   if (start && controller.velocity.magnitude > 0.3) {
      for (var leg=0; leg<legAnimator.legs.Length; leg++) {
         if (leg == 0 && stepNrL == legAnimator.legStates[leg].stepNr-1 && numberL > 0 && Time.time > footprintLTimer) {
            rotationL = leftFoot.rotation;
            FootPrint (leftFoot);
            stepNrL++;
            numberL--;
            footprintLTimer = Time.time + 0.3;
         }
         if (leg == 1 && stepNrR == legAnimator.legStates[leg].stepNr-1 && numberR > 0 && Time.time > footprintRTimer) {
            rotationR = rightFoot.rotation;
            FootPrint (rightFoot);
            stepNrR++;
            numberR--;
            footprintRTimer = Time.time + 0.3;
         }
      }
   }
}

function FootPrint (from : Transform) {
   if (from == leftFoot) {
      var positionL = leftFoot.position + footprintLOffset;
      var hitL : RaycastHit;
      if (Physics.Raycast(positionL, -Vector3.up, hitL, distance, layerMask.value)) {
         var rotL = Quaternion.FromToRotation(Vector3.up, hitL.normal);
         var angleL= Quaternion.Angle(rotationL, rotL);
         var insL : GameObject;
         if (blood)
            insL = Instantiate(bloodFootprintL, hitL.point, rotL);
         if (water)
            insL = Instantiate(waterFootprintL, hitL.point, rotL);
         insL.transform.Rotate(Vector3.up, angleL);
      }
   } else {
      var positionR = rightFoot.position + footprintROffset;
      var hitR : RaycastHit;
      if (Physics.Raycast(positionR, -Vector3.up, hitR, distance, layerMask.value)) {
         var rotR = Quaternion.FromToRotation(Vector3.up, hitR.normal);
         var angleR= Quaternion.Angle(rotationR, rotR);
         var insR : GameObject;
         if (blood)
            insR = Instantiate(bloodFootprintR, hitR.point, rotR);
         if (water)
            insR = Instantiate(waterFootprintR, hitR.point, rotR);
         insR.transform.Rotate(Vector3.up, angleR);
      }
   }
}

function PrintsTrigger (com : String) {
   legAnimator = GetComponent("LegAnimator");

   for (var leg=0; leg<legAnimator.legs.Length; leg++) {
      if (leg == 0)
         stepNrL = legAnimator.legStates[leg].stepNr;
      if (leg == 1)
         stepNrR = legAnimator.legStates[leg].stepNr;
   }
   numberL = numberOfFootprints;
   numberR = numberL;
   
   if (com == "blood") {
   blood = true;
   water = false;
   }
   if (com == "water") {
   blood = false;
   water = true;
   }
   start = true;
}
Добавить slava-1234 в Skype
Slava
UNIт
 
Сообщения: 135
Зарегистрирован: 05 апр 2009, 05:14

Re: Следы от ног - Кватернионы)

Сообщение Paul Siberdt 10 фев 2010, 16:21

Сорри, скрипты я не умею с бравзеров читать... да и вчитываться не пытаюсь, если они больше пары строк :)

Если на момент создания декальки шага запоминать вектор направления ноги ( или хотя б персонажа ), всегда можно определить его проекцию на Y-плоскость и найти угол между этим вектором-проекцией и вектором-дирекшеном декальки, что ориентирована по нормали.

Далее, на полученный угол поворачиваем саму декальку. Конечно, придется решить вопрос с + и - поворота, но это делается простым сравнением знака координаты по оси этих двух дирекшен-векторов.
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Следы от ног - Кватернионы)

Сообщение Slava 11 фев 2010, 00:41

Собственно, весь код - на всякий случай. Все что нужно поменять - в function FootPrint, в верхней половине - сделать хотя бы для одной ноги.
Там мы выровняли вращение следа с нормалью поверхности - var rotL = Quaternion.FromToRotation(Vector3.up, hitL.normal);
Потом пытаемся найти угол между положением стопы и нормалью - var angleL= Quaternion.Angle(rotationL, rotL); - это неправильно совсем.
потом инстансиируем и выравниваем получившийся след с направлением - insL.transform.Rotate(Vector3.up, angleL);

Вот поподробней, как проецировать и правильно найти угол - без теории бы только, сухим языком формул))). Осталось то пара строчек, ё)))
Добавить slava-1234 в Skype
Slava
UNIт
 
Сообщения: 135
Зарегистрирован: 05 апр 2009, 05:14

Re: Следы от ног - Кватернионы)

Сообщение Paul Siberdt 11 фев 2010, 11:10

Эх... а как же чувство победы?

Такс..
0. У вас есть Т - трансформ декальки
1. У вас есть вектор A - направление стопы, то есть, единичный дирекшен-вектор.
2. У вас есть вектор В - направление декальки, что сориентирована по нормали .
Допускаю, что декалька создана так, чтобы ее локальная ось Z тоже является осью "вперед", а Y - ось "вверх"
Чтоб определить угол поворота, надо узнать угол между вектором В и проекцией ветора А на горизонтальную плоскость декальки ( допускаю, что это плоскость Y ).

Чтобы получить проекцию, надо из локальных координат вектора отрезать Y-компоненту.
Чтобы получить локальные координаты - нужно преобразовать A по Transform.InverseTransformPoint
Возможно, лучше это сделать по Transform.InverseTransformDirection, но я не проверял еще.

//// Для Transform.InverseTransformPoint:
Вектор A придется преобразовать из дирекшена в координату:
A = A + T.position;
и потом получить снова дирекшен:
A = Transform.InverseTransformPoint ( T )
////

Теперь мы имеем дирекшен-вектор в координатной системе декальки. Проецируем его на Y ---- А.y = 0

Теперь определяем угол между обновленным А и В функцией Vector3.Angle

Чтобы узнать направление поворота (угол не имеет знака), надо взять знак z-компоненты полученного вектора А

Вроде все, остается повернуть декальку в ее локальных координатах по оси Y на полученное значение.
Эта штука будет работать при любых ориентациях трансформов.... эээ.... если я ниче не напутал :D
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4