Author Topic: good spline tutorial  (Read 8128 times)

0 Members and 1 Guest are viewing this topic.

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
good spline tutorial
« on: July 05, 2007 »
Hi all

I really need a good tutorial For Spline , my idea is to put some control point for not only translation but for translation and rotation and scaling and may be color to be smooth interplated.

so the first step is to know a good on for translation , any help ?

Offline slippy

  • Atari ST
  • ***
  • Posts: 172
  • Karma: 42
    • View Profile
Re: good spline tutorial
« Reply #1 on: July 05, 2007 »
Hey,

perhaps you might want to check this one here.

Spline-Tutorial

Cheers,
SLiPPY

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: good spline tutorial
« Reply #2 on: July 05, 2007 »
Any idea what kind of splines you want?  Easiest is Bezier, but they might not do what you want.

Jim
Challenge Trophies Won:

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #3 on: July 05, 2007 »
@slippy

thanks for your post , but in this tutorial the object didnot move on control point.

@Jim

i think the catmull_rom or Bezier will be nice.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: good spline tutorial
« Reply #4 on: July 05, 2007 »
I wrote a bezier routine, you can have it if you like, it's in the lib attached to this post;

http://dbfinteractive.com/index.php?topic=1455.0

Catmull Rom might be more useful to you though if you need more control.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #5 on: July 05, 2007 »
thanks shocky very much.  :)

did you mean the CURVE rotine by a bezier, because i did not find any bezier routine there.

could you point me to a Catmull Rom toturial please ?

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #6 on: July 06, 2007 »

ok , I have changed my mind , so I will use a Linear interpolated instead of spline , but still have a small problem , I want my Object to smooth move when it reachs to control points.

For Example. suppose you have 10 points , p1,p2,p3 .......... so on.

first we will interpolat btween P1 and p2 and when object reachs to p2 we will interpolat btween P2 and p3 , and so on.

the problem is when the object reachs to p2 it will change the path from P1-p2 to P2-P3 in non smooth change .

any idea to solve this problem please ?

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Re: good spline tutorial
« Reply #7 on: July 06, 2007 »
Catmull-Rom spline:

Code: [Select]
#ifndef Tcoord
type Tcoord
x as single
y as single
End Type
#endif


type Tspline2d

Public:
'' constructors and destructors
declare constructor()
declare constructor(byval _maxpoints as integer)
declare destructor()

'' properties

'' getters
declare property x() as single
declare property y() as single
declare property t() as single
declare property speed() as single
declare property index() as integer
declare property maxindex() as integer
declare property p(byval _index as integer) as Tcoord

'' setters
declare property x(byval _n as single)
declare property y(byval _n as single)
declare property t(byval _n as single)
declare property speed(byval _n as single)
declare property index(byval _n as integer)
declare property maxindex(byval _n as integer)
declare property p(byval _index as integer, byval _value as Tcoord)

'' methods
declare sub initcoords(byval _maxpoints as integer)
declare sub update()
 
  '' members
private:
m_x           as single
m_y           as single
    m_t           as single
    m_speed       as single
    m_index       as integer
    m_maxindex    as integer
    p_coords   as Tcoord ptr
   
end type


constructor Tspline2d()
m_t = 0
m_speed = 0.001
m_index = 0
m_maxindex = 0
end constructor

constructor Tspline2d(byval _maxpoints as integer)
m_t = 0
m_speed = 0.001
m_index = 0
m_maxindex = _maxpoints
p_coords = new Tcoord[_maxpoints]
end constructor


destructor Tspline2d()
delete[] p_coords
end destructor

'' properties

'' getters
property Tspline2d.x() as single
property = m_x
End Property

property Tspline2d.y() as single
property = m_y
End Property


property Tspline2d.t() as single
property = m_t
End Property


property Tspline2d.speed() as single
property = m_speed
End Property


property Tspline2d.index() as integer
property = m_index
End Property


property Tspline2d.maxindex() as integer
property = m_maxindex
End Property


property Tspline2d.p(byval _index as integer) as Tcoord
if _index > -1 and _index < m_maxindex then
property = p_coords[_index]
end if
End Property



'' setters
property Tspline2d.x(byval _n as single)
m_x = _n
End Property


property Tspline2d.y(byval _n as single)
m_y = _n
End Property


property Tspline2d.t(byval _n as single)
m_t = _n
End Property


property Tspline2d.speed(byval _n as single)
m_speed = _n
End Property



property Tspline2d.index(byval _n as integer)
m_index = _n
End Property


property Tspline2d.maxindex(byval _n as integer)
m_maxindex = _n
End Property



property Tspline2d.p(byval _index as integer, byval _n as Tcoord)
if _index > -1 and _index < m_maxindex then
p_coords[_index].x = _n.x
p_coords[_index].y = _n.y
end if
End Property



'' methods
sub Tspline2d.initcoords(byval _maxpoints as integer)
m_maxindex = _maxpoints
p_coords = new Tcoord[_maxpoints]
End Sub


sub Tspline2d.update()

dim as single  t1 = m_t
dim as single  t2 = t * t
dim as single  t3 = t2 * t
dim as Tcoord p0, p1, p2, p3

    p0.x = p_coords[m_index].x
    p0.y = p_coords[m_index].y
    p1.x = p_coords[(m_index + 1) mod m_maxindex].x
    p1.y = p_coords[(m_index + 1) mod m_maxindex].y
    p2.x = p_coords[(m_index + 2) mod m_maxindex].x
    p2.y = p_coords[(m_index + 2) mod m_maxindex].y
    p3.x = p_coords[(m_index + 3) mod m_maxindex].x
    p3.y = p_coords[(m_index + 3) mod m_maxindex].y       

     
m_x = 0.5 * ( ( 2.0 * p1.x ) +_
    ( -p0.x + p2.x ) * t1 +_
( 2.0 * p0.x - 5.0 * p1.x + 4 * p2.x - p3.x ) * t2 +_
( -p0.x + 3.0 * p1.x - 3.0 * p2.x + p3.x ) * t3 )
m_y = 0.5 * ( ( 2.0 * p1.y ) +_
( -p0.y + p2.y ) * t1 +_
( 2.0 * p0.y - 5.0 * p1.y + 4 * p2.y - p3.y ) * t2 +_
( -p0.y + 3.0 * p1.y - 3.0 * p2.y + p3.y ) * t3 )
   
    '' increment t   
    m_t += m_speed
    if m_t > 1.0 then     
    m_t -= 1.0
    m_index = (m_index + 1) mod m_maxindex
    endif     
       
End Sub







cls
screen 18,,2
randomize timer

const MAXPOINTS = 10
dim as Tspline2d catmull '= Tspline2d(MAXPOINTS)
catmull.initcoords(MAXPOINTS)

for i as integer = 0 to catmull.maxindex-1
dim as Tcoord p
p.x = rnd * 640
p.y = rnd * 480
catmull.p(i) = p
next i 


dim as integer current_color = 1, colorchanged = 0

catmull.speed = 0.005
screenset 0,1

for i as integer = 0 to catmull.maxindex-1
dim as Tcoord p
p = catmull.p(i)
circle (p.x,p.y), 3,i + 1
next i
do

'line (0,0)-(639,479),0,bf


catmull.update
'circle (catmull.x,catmull.y),15, current_color
pset (catmull.x,catmull.y),15

if catmull.index = 0 and colorchanged = 0  then
current_color = 1 + rnd * 15
colorchanged = -1
elseif catmull.index = 1 then
colorchanged = 0
end if   

screensync
screencopy

Loop until inkey<>""


Challenge Trophies Won:

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #8 on: July 06, 2007 »

thanks  relsoft for your code.

I will study it.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: good spline tutorial
« Reply #9 on: July 07, 2007 »
Quote
the problem is when the object reachs to p2 it will change the path from P1-p2 to P2-P3 in non smooth change .

any idea to solve this problem please ?
Well, obviously not, since two lines don't form a continuous function.  Perhaps you want to stop at P2 for a whlie and rotate the camera/object around to the new orientation?  You probably want a curve which goes through the control points, which Bezier doesn't, but Cubic splines and Catmull-Rom splines do.

Jim
Challenge Trophies Won:

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #10 on: July 07, 2007 »

Ok Jim, i have tested the Catmull-Rom Spline that posted by relsoft and found that it is very useful, and did not see any Cubic splines.

Only the Littile thing about  the Catmull-Rom Spline is that the path is a curve not a strait line between each points.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: good spline tutorial
« Reply #11 on: July 07, 2007 »
So you don't want the movement to curve?
That seems strange to me but then I don't know what you're using this for.

Btw the curve in my library is a bezier routine and it is also a cubic spline. You can render beziers in other ways (quadratic etc)  of course.

You'll be better off using Rels Catmull rom routine. The movement is much nicer and you have the fact that hitting the control points is guaranteed.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #12 on: July 07, 2007 »
Yes shocky , I want that the pass is a strait line and at the same time at the control points the change in path is smooth.

But I think this is impossible , so I will use relsoft Catmull-Rom Spline.

I want that routine to allow my Library users to define a path that control the translation and rotation and scaling and may be the color of sprite in the animation scene. So first I was searching for good translation spline then I will modify it suit my needs.

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #13 on: July 11, 2007 »
Relsoft:

Your spline code is very helpful and very close to my coding style. So thank you very much for your help.

Just I want an other thing , suppose you have a ship space that follows this spline ,so how to control the rotation of the ship to insure that it face the next point, I.E if our ship face to left hand and the next point is in the right direction so can you adjust your update routine to allow the ship smoothly change the rotation to face to next point?   

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: good spline tutorial
« Reply #14 on: July 11, 2007 »
Emil_halim: Easy. Compute the angle between the current point and next ( or previous ) one using something like Math.atan2( nextX-currentX, nextY-currentY ).you can of course interpolate the ship's current angle to the new one, but I doubt it's necessary.
« Last Edit: July 12, 2007 by p01 »

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #15 on: July 12, 2007 »
Nice p01.

It is really easy , and you open my mind for new idea , which is you did not have to interpolate the angle instead you calculate the angle between each interpolated point and the previous one.

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: good spline tutorial
« Reply #16 on: July 12, 2007 »
Ok, I have made it with C++  :) , big thanks must go to Relsoft and P01.

Here are my OgreMagic functions , may be it useful for someone else.

Code: [Select]

/**********************************************************
        2 D  p a t h  s t u f f
***********************************************************/

  struct Tcoord
   {
        float x,y;
   };

  struct Path2D
   {
       float   m_x;
       float   m_y;
       float   m_t;
       float   m_speed;
       int     m_index;
       int     m_maxindex;
       Tcoord* p_coords;
       float   m_old_x;
       float   m_old_y;
       double  m_angle;
       double  m_RotOffset;
   };


  DLL_EXPORT Path2D* ML_Create2DPath(int MaxPoints,float Speed,float RotOffset)
   {
       Path2D* path = new Path2D;
       path->m_maxindex = MaxPoints;
       path->p_coords = new Tcoord[MaxPoints];
       path->m_speed = Speed;
       path->m_x = path->m_y = path->m_t =
       path->m_index = path->m_old_x = path->m_old_y =
       path->m_angle = 0;
       path->m_RotOffset = RotOffset;
       return  path;
   }

  DLL_EXPORT void ML_AddpointTo2DPath(Path2D* path,float x,float y)
   {
       if(path->m_maxindex>path->m_index && path->m_index>=0)
        {
          path->p_coords[path->m_index].x = x;
          path->p_coords[path->m_index].y = y;
          path->m_index++;
        }
   }

  DLL_EXPORT void ML_AddpointTo2DPathByIndex(Path2D* path,int index,float x,float y)
   {
       if(path->m_maxindex>index && path->m_index>=0)
        {
          path->p_coords[index].x = x;
          path->p_coords[index].y = y;
        }
   }

  DLL_EXPORT void ML_SetPathSpeed(Path2D* path,float speed)
   {
       path->m_speed = speed;
   }

  // big thanks to Relsoft for catmull
  DLL_EXPORT void ML_Update2DPath(Path2D* path)
   {
       float  t1 = path->m_t;
   float  t2 = t1 * t1;
   float  t3 = t2 * t1;
   Tcoord p0, p1, p2, p3;

       p0.x = path->p_coords[path->m_index].x;
       p0.y = path->p_coords[path->m_index].y;
       p1.x = path->p_coords[(path->m_index + 1) % path->m_maxindex].x;
       p1.y = path->p_coords[(path->m_index + 1) % path->m_maxindex].y;
       p2.x = path->p_coords[(path->m_index + 2) % path->m_maxindex].x;
       p2.y = path->p_coords[(path->m_index + 2) % path->m_maxindex].y;
       p3.x = path->p_coords[(path->m_index + 3) % path->m_maxindex].x;
       p3.y = path->p_coords[(path->m_index + 3) % path->m_maxindex].y;

   path->m_x = 0.5 * ( ( 2.0 * p1.x ) + ( -p0.x + p2.x ) * t1 +
( 2.0 * p0.x - 5.0 * p1.x + 4 * p2.x - p3.x ) * t2 +
( -p0.x + 3.0 * p1.x - 3.0 * p2.x + p3.x ) * t3 );

   path->m_y = 0.5 * ( ( 2.0 * p1.y ) + ( -p0.y + p2.y ) * t1 +
( 2.0 * p0.y - 5.0 * p1.y + 4 * p2.y - p3.y ) * t2 +
( -p0.y + 3.0 * p1.y - 3.0 * p2.y + p3.y ) * t3 );

       path->m_t += path->m_speed;
       if(path->m_t > 1.0)
        {
       path->m_t -= 1.0;
       path->m_index = (path->m_index + 1) % path->m_maxindex;
        }

        path->m_angle = atan2(path->m_x - path->m_old_x , path->m_y - path->m_old_y)- path->m_RotOffset;
        path->m_old_x = path->m_x;
        path->m_old_y = path->m_y;

   }

« Last Edit: July 12, 2007 by Emil_halim »