Войти
ПрограммированиеФорум2D графика и изометрия

Скорость движения по сплайну (3 стр)

Страницы: 1 2 3
#30
13:37, 17 авг. 2012

Набросал подсказку для сплайна Катмулл-Рома:
http://www.gamedev.ru/code/tip/catmull_rom


#31
15:21, 17 авг. 2012

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

#32
17:46, 17 авг. 2012

я только что вставил класс он работает но выдает какие то дикие координаты причем обе координаты отрицательные

#33
21:42, 17 авг. 2012

Emissar
> у меня уже все дедлайны прогорели
Emissar
> А писать на паскале через пут пиксель это для 9 класса пардон)))
ИМХО Если горят дедлайны, то писать уже надо так как есть.

Кароче, аналитическое решение у меня не прошло, так как я запутался в выкладках. Сделал на контрольных точках и линейной интерполяции между ними с учетом расстояния между точками. Точность можно варьировать, прогонял тесты, вроде движется довольно стабильно.

Надеюсь садить самолеты никто не будет.

vec2f Lerp(const vec2f& a,const vec2f& b, float par){
  return a*(1.0f-par)+b*par;
}

struct spline{
  vec2f a;//Опорные
  vec2f b;//точки
  vec2f c;//для построения
  vec2f d;//сплайна

  std::vector<vec2f> pos;//маршрут
  std::vector<float> posT;//сколько расстояние прошли к данной точке
  float length;//полная длина маршрута

  int current;//текущая точка маршрута
  float curPos;//сколько пройдено пути на данный момент


  // Считаем точки сплайна
  vec2f Calc(float t){
    return vec2f(
      pow(1.0f-t,3)*a.x+3*pow(1.0f-t,2)*t*b.x+3*(1-t)*pow(t,2)*c.x+pow(t,3)*d.x,
      pow(1.0f-t,3)*a.y+3*pow(1.0f-t,2)*t*b.y+3*(1-t)*pow(t,2)*c.y+pow(t,3)*d.y
      );
  }

  //Подготовка маршрута с заданным шагом t, возвращает длину маршрута
  float Prepare(float prec){
    length=0.0f;
    int count=0;
    for(float t=0.0f; t<=1.0f; t+=prec){
      pos.push_back(Calc(t));
      posT.push_back(length);
      if(count>0)
        length+=Length(pos[count]-pos[count-1]);
      ++count;
    }
    pos.push_back(Calc(1.0f));
    posT.push_back(1.0f);
    Reset();

    return length;
  }

  //Двигаем вперед на расстояние t
  vec2f MoveForward(float t){
    curPos+=t;

    float a=(curPos-posT[current])/(posT[current+1]-posT[current]);

    while (a>1.0f){
      ++current;
      a=(curPos-posT[current])/(posT[current+1]-posT[current]);
    }

    return Lerp(pos[current],pos[current+1],a);
  }

  //Тоже самое, только назад
  vec2f MoveBackward(float t){
    curPos-=t;

    float a=(curPos-posT[current])/(posT[current+1]-posT[current]);

    while (a<0.0f){
      --current;
      a=(curPos-posT[current])/(posT[current+1]-posT[current]);
    }

    return Lerp(pos[current],pos[current+1],a);
  }

  //Приводим систему к новому запуску.
  void Reset(){
    curPos=0.0f;
    current=0;
  }

};
#34
0:50, 18 авг. 2012

Я перевёл на C++ и требую включить себя в список программистов игры ибо это было непросто. Пользуйся пока специалисты по C++ не пустили этот код на клочки по закоулочкам.

#include <stdio.h>
#include <math.h>

struct point {float x,y;};

class vector
 {
  public:
  float x,y;
  vector(float x,float y) {this->x=x; this->y=y;}
  vector(point p1,point p2) {x=p2.x-p1.x; y=p2.y-p1.y;}
  float abs() {return sqrt(x*x+y*y);}
  float abs2() {return x*x+y*y;}
 };

vector operator-(point p2,point p1) {return vector(p2.x-p1.x,p2.y-p1.y);}

float operator*(vector v1,vector v2) {return v1.x*v2.x+v1.y*v2.y;}

vector operator*(vector v,float a) {return vector(v.x*a,v.y*a);}

vector operator*(float a,vector v) {return vector(v.x*a,v.y*a);}

vector operator/(vector v,float d) {return vector(v.x/d,v.y/d);}

vector derivative(point (*f)(float),float p,float prec) {return (f(p+0.5*prec)-f(p-0.5*prec))/prec;}

float dist2(point p1,point p2)
 {
  float x=p2.x-p1.x;
  float y=p2.y-p1.y;
  return x*x+y*y;
 }

float cos2(point p1,point p2,point p3)
 {
  vector v1=p2-p1;
  vector v2=p3-p2;
  float mul=v1*v2;
  return mul*mul/v1.abs2()/v2.abs();
 }

class curve
 {
  public:
  float p,dp,v,t,dt,dtmax,DistLim,AngleLim;
  point (*r)(float);
  curve(point (*r)(float),float v,float dt=1.0,float DistLim=2.0,float AngleLim=1.5)
   {
    this->r=r; this->v=v; this->dt=dt; dtmax=dt;
    this->DistLim=DistLim*DistLim;
    this->AngleLim=cos(M_PI*AngleLim/180);
    this->AngleLim*=this->AngleLim;
   }
  void GetWay()
   {
    p=0; t=0;
    while (p<1)
     {
      dp=v*dt/derivative(r,p,0.001).abs();
      while (dist2(r(p),r(p+dp))>DistLim || cos2(r(p-dp),r(p),r(p+dp))>AngleLim) {dp/=2;}
      while (dist2(r(p),r(p+dp))<=DistLim/2 && cos2(r(p-dp),r(p),r(p+dp))<=AngleLim/2) {dp*=1.2;}
      dt=sqrt(dist2(r(p),r(p+dp)))/v;
      if (dt>dtmax) {dt=dtmax; dp=v*dt/derivative(r,p,0.001).abs();}
      printf("t=%.2f, dt=%.2f, p=%.2f, dp=%.4f, x=%.2f, y=%.2f, dist=%.2f, angle=%.2f\n",
             t,dt,p,dp,r(p).x,r(p).y,sqrt(dist2(r(p),r(p+dp))),acos(sqrt(cos2(r(p-dp),r(p),r(p+dp)))));
      p+=dp; t+=dt;
     }
   }
 };

point r(float p)
 {
  point rv;
  rv.x=p*(p-0.25)*(p-0.5)*(p-1)*1000+sin(2*M_PI*p+M_PI/4)*10;
  rv.y=p*(p-0.8)*(p-1)*100+cos(6*M_PI*p)*10;
  return rv;
 }

int main()
 {
  curve way(r,2.5);
  way.GetWay();
  return 0;
 }

#35
13:06, 18 авг. 2012

обьясни как тут задавать контрольные точки через которые проходит траектрия

#36
13:44, 18 авг. 2012

Контрольные точки не нужны. Вся траектория задаётся функцией r. Движением управляют параметры конструктора.

#37
13:47, 18 авг. 2012

Emissar
Задаешь a, b, c, d, потом Prepare. Потом MoveForward с тем, сколько надо пройти.

#38
13:49, 18 авг. 2012

это как, я совсем не понимаю мне нужно описать кривую определенную как в зумме что бы по ней шли мои обьекты это можно сделать при помощи твоего класса?

#39
14:27, 18 авг. 2012

Всё делает функция r. Ты рисуешь по миллиметровой бумаге или по клеточкам траекторию. Потом тыкаешь примерно равномерно или верёвочкой или курвиметром или через что ещё захочешь контрольные точки примерно на равном расстоянии пути (правильнее говоря дуговой координаты). Задаёшь функцию пути. При такой деятельности хорошо помогает программа KmPlot, которая на ходу рисует графики. Если совсем не знаешь, как превратить кривую в многочлен, то просто нарисуй картинку и я тебе посчитаю коэффициенты многочленов.

Страницы: 1 2 3
ПрограммированиеФорум2D графика и изометрия

Тема в архиве.