Реализация кривых Безье - PullRequest
0 голосов
/ 30 марта 2011

Я пытаюсь реализовать кривые Безье для задания. Я пытаюсь переместить шар (используя кривые Безье), предоставив моей функции массив ключевых кадров. Функция должна выдавать мне все кадры между ключевыми кадрами ... или контрольными точками ... но хотя я использую формулу, найденную в wikipedia ..., она на самом деле не работает: s

это мой код:

  private void interpolate(){
      float x,y,b, t = 0;
      frames = new Frame[keyFrames.length];
      for(int i =0;i<keyFrames.length;++i){   
         t+=0.001;
         b = Bint(i,keyFrames.length,t);   
         x = b*keyFrames[i].x;
         y = b*keyFrames[i].y;
         frames[i] = new Frame(x,y);     
      }
  }

private float Bint(int i, int n, float t){
  float Cni = fact(n)/(fact(i) * fact(n-i));
  return Cni * pow(1-t,n-i) * pow(t,i);
}

Также я заметил, что массив frames [] должен быть намного больше, но я не могу найти другой текст, более удобный для программиста

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 30 марта 2011

Есть много вещей, которые выглядят не совсем правильно.

  1. Делая это таким образом, ваша интерполяция будет проходить точно через первую и последнюю контрольные точки, но не черездругие.Это то, что вы хотите?

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

  3. Если предположить, что вы действительно делаете хотите сделать это,ваше значение t должно перейти от 0 в начале до 1 в конце.У вас случайно есть 1001 из этих ключевых кадров?Если нет, то вы будете поступать неправильно.

  4. Оценка этих многочленов с большим количеством обращений к fact и pow может оказаться неэффективной, особенно если nбольшой.

Я не хочу вдаваться в подробности о том, что вы должны делать, не зная больше о масштабах вашего задания - это не поможетодин хороший товар для Stack Overflow, который сделает вашу домашнюю работу за вас!Что вы уже сказали о кривых Безье?Что именно ваше задание просит вас сделать?

ИЗМЕНЕНО, чтобы добавить:

Простейший способ выполнить интерполяцию с использованием кривых Безье, вероятно, таков.Иметь одну (кубическую) кривую Безье между каждой парой ключевых точек.Конечные точки (первая и последняя контрольные точки) каждой кривой Безье являются этими ключевыми точками.Вам нужно еще две контрольные точки.Чтобы движение было плавным при перемещении через заданную ключевую точку, вам необходимо (ключевая точка минус предыдущая контрольная точка) = (следующая контрольная точка минус ключевая точка).Таким образом, вы выбираете один вектор в каждой ключевой точке, который будет определять, куда идут предыдущие и последующие контрольные точки.При перемещении через каждую ключевую точку вы будете двигаться в направлении этого вектора, и чем длиннее вектор, тем быстрее вы будете двигаться.(Если вектор равен нулю, то ваш кубический Безье вырождается в простой прямолинейный путь.)

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

0 голосов
/ 30 марта 2011

Наконец-то получил то, что мне было нужно!Вот что я сделал:

private void interpolate() {    
  float t = 0;
  float x,y,b;
  for(int f =0;f<frames.length;f++) {      
    x=0;
    y=0;
    for(int i = 0; i<keyFrames.length; i++) {       
      b = Bint(i,keyFrames.length-1,map(t,0,time,0,1));   
      x += b*keyFrames[i].x;
      y += b*keyFrames[i].y;
    }    
  frames[f] = new Frame(x,y); 
  t+=partialTime;     
}

}

private void createInterpolationData() {
     time = keyFrames[keyFrames.length-1].time -
     keyFrames[0].time;
     noOfFrames = 60*time;
     partialTime = time/noOfFrames;
     frames = new Frame[ceil(noOfFrames)];  
}
...