Author Topic: How do I make a continuous Bezier spline  (Read 3031 times)

Offline backspace

  • Mr. Drawsprite
  • **
  • Posts: 53
    • View Profile
I took on the challenge to make a 3D splined path editor, to test out my new GLBasic skills, and I got a reasonable demo working.
However I have run into a brick wall with the QuadraticBezier3d, Not the function itself, that works brilliantly, but I'm rather stuck on how to make a continuous spline that runs through all 4 points that I use. The idea is to increase the key points on request, and generate splines as required. But alas my skills have dried up at this point.
I use the Bezier curves library from Hemlos to do the splines, but I am missing something along the way.
Any guidance will be most welcome

I've made certain arrays Global in the library in order to access them in my program.

Here's the program so far.
Code: (glbasic) [Select]
//SETCURRENTDIR("Media")

//LOADFONT "..smalfont.png", 1
//SETFONT 1

TYPE POINT
x#
y#
z#
ENDTYPE

GLOBAL points[] AS POINT
GLOBAL splines[] AS POINT
GLOBAL waypoints[] AS POINT
GLOBAL numPoints = 4  //Key points for generating bezier curve points
GLOBAL extent# = 300  //Set pixel graph size: 100 means from -100 to +100. Change to desired path scale
GLOBAL CALC = FALSE
GLOBAL maxPoints = 30 //Bexier points: MUST be divisable by 2, else the calculations will fall over
LOCAL keyPoint = 0    //current key point
LOCAL i
LOCAL steps#
LOCAL angle = 270
LOCAL UpAngle = 0
LOCAL distanceP# = 2.5
LOCAL help = 1


SetupPoints()

WHILE TRUE
IF KEY(203) THEN angle = angle - 1 //left arrow
IF KEY(205) THEN angle = angle + 1 //right arrow
IF KEY(200) THEN UpAngle = UpAngle +1 //up arrow
IF KEY(208) THEN UpAngle = UpAngle -1 //down arrow
IF KEY(59) THEN help = -help; WHILE KEY(59); WEND //F1
IF KEY(15) THEN keyPoint = keyPoint+1;WHILE KEY(15); WEND //Tab
IF keyPoint > numPoints-1 THEN keyPoint = 0

IF KEY(17) //W
INC points[keyPoint].z 
CALC = FALSE
ENDIF

IF KEY(31) //S
DEC points[keyPoint].z 
CALC = FALSE
ENDIF

IF KEY(30) //A
INC points[keyPoint].x   //Reverse this if you prefer
CALC = FALSE
ENDIF

IF KEY(32) //D
DEC points[keyPoint].x  //Reverse this if you prefer
CALC = FALSE
ENDIF

IF KEY(19) //R
INC points[keyPoint].y 
CALC = FALSE
ENDIF

IF KEY(33) //F
DEC points[keyPoint].y 
CALC = FALSE
ENDIF



X_MAKE3D 1, 10000, 45
X_CAMERA COS(angle)*extent*distanceP, SIN(UpAngle)*extent*distanceP, SIN(angle)*extent*distanceP,  0, 0, 0

//grid
steps = extent*2/20
FOR i = -extent TO extent STEP steps
// XY grid
X_LINE -extent,i,0, extent,i,0, 0.1, RGB(0,0,60)
X_LINE i,-extent,0, i,extent,0, 0.1, RGB(0,0,60)
// XZ grid
X_LINE -extent,0,i, extent,0,i, 0.1, RGB(60,0,0)
X_LINE i,0,-extent, i,0,extent, 0.1, RGB(60,0,0)
//YX grid
X_LINE 0,-extent,i, 0,extent,i, 0.1, RGB(0,60,0)
X_LINE 0,i,-extent, 0,i,extent, 0.1, RGB(0,60,0)
NEXT

//z=0 indicator
X_LINE 0,0,0, 0,0,extent, 3, RGB(255,0,0)

//draw points
FOR i = 0 TO numPoints-1
IF i <> keyPoint
X_DOT points[i].x, points[i].y, points[i].z,10, RGB(0,255,0) //10=size of keypoint: change as required
ENDIF
NEXT

//draw current key point
X_DOT points[keyPoint].x, points[keyPoint].y, points[keyPoint].z,10, RGB(255,0,255) //10=size of keypoint: change as required


BuildSplineArray()


//draw all spline points
FOR i = 0 TO LEN(splines)-1
X_DOT splines[i].x, splines[i].y, splines[i].z, 1, RGB(180,180,180)
NEXT

//Screen instructions
X_MAKE2D
PRINT "F1: Toggle help", 5,5, RGB(200,200,200)
IF help = 1
PRINT "LEFT ARROW: Rotate Left", 5,25,RGB(200,200,200)
PRINT "RIGHT ARROW: Rotate Right", 5,45,RGB(200,200,200)
PRINT "UP ARROW: Rotate Up", 5,65,RGB(200,200,200)
PRINT "DOWN ARROW: Rotate Down", 5,85,RGB(200,200,200)
PRINT "1: Add Key Point", 5,105,RGB(200,200,200)
PRINT "2: Remove Key Point", 5,125,RGB(200,200,200)
PRINT "TAB: Next Key Point",5,145,RGB(200,200,200)
PRINT "W: Move Z+", 5,165,RGB(200,200,200)
PRINT "S: Move Z-",5,185,RGB(200,200,200)
PRINT "A: Move X-",5,205,RGB(200,200,200)
PRINT "D: Move X+",5,225,RGB(200,200,200)
PRINT "R: Move Y+",5,245,RGB(200,200,200)
PRINT "F: Move Y-",5,265,RGB(200,200,200)


ENDIF
PRINT "Number of Key Points: "+numPoints, 5,580, RGB(200,200,200)
SHOWSCREEN
WEND

FUNCTION SetupPoints:
LOCAL point AS POINT
point.x = -extent/2; point.y=0; point.z=0; DIMPUSH points[],point
point.x = 0; point.y=-extent/2; point.z=0; DIMPUSH points[],point
point.x = extent/2; point.y=0; point.z=0; DIMPUSH points[],point
point.x = 0; point.y=extent/2; point.z=0; DIMPUSH points[],point
ENDFUNCTION



FUNCTION BuildSplineArray:
LOCAL i,j,n,m,mhf,tx,ty,tz
LOCAL spline AS POINT

IF CALC THEN RETURN
CALC = TRUE

//Empty the spline array for new spline points
FOR i = 0 TO LEN(splines)-1
DIMDEL splines[],0
NEXT

//Empty the waypoint array for new waypoints
FOR i = 0 TO LEN(waypoints)-1
DIMDEL waypoints[],0
NEXT

//build new spline array
i= -1
WHILE TRUE
//DEBUG i + "\n"
i = i+1
IF i <= numPoints - 3
QuadraticBezier3d(points[i].x,   points[i].y,   points[i].z, _
                  points[i+1].x, points[i+1].y, points[i+1].z, _
                  points[i+2].x, points[i+2].y, points[i+2].z, _
                  maxPoints)
FOR j = 0 TO LEN(QuadraticBezierArray3d) -1
spline.x = QuadraticBezierArray3d[j][0]
spline.y = QuadraticBezierArray3d[j][1]
spline.z = QuadraticBezierArray3d[j][2]
DIMPUSH splines[],spline
NEXT
ENDIF

IF i = numPoints -2
QuadraticBezier3d(points[i].x,   points[i].y,   points[i].z, _
                  points[i+1].x, points[i+1].y, points[i+1].z, _
                  points[0].x, points[0].y, points[0].z, _
                  maxPoints)
FOR j = 0 TO LEN(QuadraticBezierArray3d) -1
spline.x = QuadraticBezierArray3d[j][0]
spline.y = QuadraticBezierArray3d[j][1]
spline.z = QuadraticBezierArray3d[j][2]
DIMPUSH splines[],spline
NEXT
ENDIF

IF i = numPoints -1
QuadraticBezier3d(points[i].x,   points[i].y,   points[i].z, _
                  points[0].x, points[0].y, points[0].z, _
                  points[1].x, points[1].y, points[1].z, _
                  maxPoints)
FOR j = 0 TO LEN(QuadraticBezierArray3d) -1
spline.x = QuadraticBezierArray3d[j][0]
spline.y = QuadraticBezierArray3d[j][1]
spline.z = QuadraticBezierArray3d[j][2]
DIMPUSH splines[],spline
NEXT
ENDIF

IF i = numPoints THEN BREAK
WEND

ENDFUNCTION

The full project is attached as well



[attachment deleted by admin]
I came, I saw, I coded.

Offline backspace

  • Mr. Drawsprite
  • **
  • Posts: 53
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #1 on: 2013-Jan-20 »
I read up on beziers on the web and discovered that the function uses the second vertex as a control point. That's where I was going all wrong.
I've changed my approach and only "spline" every second "waypoint". This creates usable points with thir spline control points. This is a lot of fun.
I will need to study this Entity thingy to see how GLBasic handles 3D, so that I can one day move the objects with a mouse. Till then, I'm stuck with keys.
Anyway. I got it working now. Probably my biggest GLBasic program so far.

Here's the project.

Edit: Add and Remove keypoints not coded yet.

[attachment deleted by admin]
I came, I saw, I coded.

Offline Wampus

  • Prof. Inline
  • *****
  • Posts: 1004
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #2 on: 2013-Jan-20 »
Wow looking good. That could be very useful in all sorts of situations.

I was about to post that I know how to do smooth continuous lines with cubic Bezier curves in 3D since I've just done it with another little proggy. Not sure how it would be done with quadratic bezier curves. How did you do it? I'll look at the code. :)

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1621
  • Particle Hawk
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #3 on: 2013-Jan-21 »
In all the research(limited) ive done, i have not seen any solid algorithms to do this.
Unfortunetly, it might be dependant on your eyes only.

Ive done experiments with 4 separate beziers line to create a circle, this was a bit of work.
Basically all the control points went to 4 corners of a square, and the beziers lines all started halfway between these corners.
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3375
  • Integrated Brain
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #4 on: 2013-Jan-22 »
Hi in this link, I leave you, the Editor I did for the Black SUn, but sorry I don't rebenber nothing about how it's works... You have to add something to media, for load images audio, and this things...

Regards,
http://www.glbasic.com/forum/index.php?topic=8871.0

Offline backspace

  • Mr. Drawsprite
  • **
  • Posts: 53
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #5 on: 2013-Jan-22 »
@mentalthink: I'll certainly take a look at you code. Thank you

@Ocean: All of this OGL stuff is new to me, so I feel like a kid with a new Christmas toy. Thank you.
I came, I saw, I coded.

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1621
  • Particle Hawk
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #6 on: 2013-Jan-23 »

I think for your purposes you might want to play around with nurbs instead of beziers.

Computationally speaking, i think nurbs is easier to use.
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline backspace

  • Mr. Drawsprite
  • **
  • Posts: 53
    • View Profile
Re: How do I make a continuous Bezier spline
« Reply #7 on: 2013-Jan-24 »
I use Rhino Nurbs modeler to build most of  my models. I never thought I would one day be able to code nurbs. This is awesome. Well worth an investigation. OGL seems to hold many powerful features as well. I think I am going to have a few busy weeks ahead assimilating all this stuff into some useful code.
Again thanks - You guys rock.
I came, I saw, I coded.