Author Topic: bezier (petzold) example  (Read 4543 times)

0 Members and 1 Guest are viewing this topic.

Frankolinox

  • Guest
bezier (petzold) example
« on: June 10, 2014, 08:29:27 AM »
lalala :)
« Last Edit: October 01, 2014, 08:35:59 AM by Frankolinox »

JRS

  • Guest
Re: bezier (petzold) example
« Reply #1 on: June 10, 2014, 09:17:06 AM »
Outstanding Frank!

It would be great to get a list of differences when porting a PowerBASIC applications to OxygenBasic. I think more folks would take O2 seriously if they could see what looks like PowerBASIC code running in a modern compiler. Charles has put a lot of work into O2 to be adaptable to traditional BASIC, PowerBASIC and C. I view O2 like a nuclear power plant that only generates electricity for it's own use. Lets all get connected and stop using coal.

 

« Last Edit: June 10, 2014, 11:33:34 AM by John »

Mike Lobanovsky

  • Guest
Re: bezier (petzold) example
« Reply #2 on: June 10, 2014, 01:08:59 PM »
Hi Frank,

Four observations that will make your script work better:

1. OxygenBasic array indices start with 1 on default. You should specify INDEXBASE 0 explicitly at the beginning of your code if you're dealing with C-style arrays.

2. STATIC AS POINT apt(3) is not correct. Your array stores four elements (indexed 0 through 3) and should be declared as STATIC AS POINT apt(4). Oxygen wouldn't check the validity of array bounds for you.

3. InvalidateRect hwnd, BYVAL %NULL, %TRUE in CASE %WM_PAINT is redundant and should be commented out.

4. ..., BYREF Point apt(10)) in SUB DrawBezier() is both incorrect and redundant. apt is a reference that can also be indexed as an array, as a side effect of Oxygen's refusal to check the array bounds (see Item 2). ..., BYREF Point apt) would be a better solution IMHO.


Hope this helps. :)

.

Charles Pegge

  • Guest
Re: bezier (petzold) example
« Reply #3 on: June 11, 2014, 08:36:53 AM »

JRS

  • Guest
Re: bezier (petzold) example
« Reply #4 on: June 11, 2014, 08:50:50 AM »
The SDL_gfx library provides a bezier function. Here is the Script BASIC GFX extension module version of it.



Code: [Select]
' ScriptBasic GFX - Alpha Bezier Curve

IMPORT gfx.inc

' Random Value Arrays
gfx::Window 640, 480, "ScriptBasic GFX - Alpha Bezier"
RANDOMIZE(gfx::Time())
FOR i = 0 TO 512
  rx[i] = RND() % 640/2
  rxx[i] = 640/2 + rx[i] 
  ry[i] = 60 + RND() % 480 - 80
  lw[i] = 2 + RND() % 7
  rr[i] = RND() AND  255
  rg[i] = RND() AND  255
  rb[i] = RND() AND  255
  af = rx[i] / 640
  ra[i] = INT(255 * af)
NEXT

ts = gfx::Time()
gfx::SDL_SetClipRect 0, 0, 640, 480
FOR i = 0 TO 512-3 STEP 3
  a1[0] = rxx[i]
  a1[1] = rxx[i + 1]
  a1[2] = rxx[i + 2]
  a2[0] = ry[i]
  a2[1] = ry[i + 1]
  a2[2] = ry[i + 2]
  gfx::bezierRGBA(a1, a2, 3, 100, rr[i], rg[i], rb[i], ra[i])
NEXT
te = gfx::Time()
gfx::stringColor 20, 15,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
gfx::Update
WHILE gfx::KeyName(1) <> "-escape"
WEND
gfx::Close
« Last Edit: June 11, 2014, 08:59:19 AM by John »

Mike Lobanovsky

  • Guest
Re: bezier (petzold) example
« Reply #5 on: June 11, 2014, 09:48:01 AM »
Nice Tutorial on Bezier curves:

Yes Charles,

A very well-presented, minimalistic and practical tutorial indeed. I'd only add one more not-so-uncommon application field to the palette: bezier paths for a "spectator"-mode third-person camera that can follow 3D game characters in a game or explore the associated scenery; also very useful for cut-scenes (pre-animated non-interactive pieces of game scenario). 3D cameras are not subject to simulated physical inertia so bezier paths are the only means to ensure sufficient smoothness of camera motion that can't be approximated with straight lines.

Mike Lobanovsky

  • Guest
Re: bezier (petzold) example
« Reply #6 on: June 11, 2014, 10:57:43 AM »
there was only missing one line
Code: [Select]
indexbase 0

Whilst this isn't exactly so Frank (there are at least three changes that you've made to your original script and I really don't see the reason why you neglected my advice to also get rid of redundant InvalidateRect()) but I am glad you are happy with what you finally got.

You are welcome.

Charles Pegge

  • Guest
Re: bezier (petzold) example
« Reply #7 on: June 11, 2014, 06:08:06 PM »

Generating Bezier curves from scratch:

Code: [Select]
  includepath $\inc\
  % title     "Bezier Closed Shape Plot"
  % width     600
  % height    600
  include     "OpenglSceneFrame.inc"

  sub initialize(sys hWnd)
  ========================
  end sub


  sub Release(sys hwnd)
  =====================
  DeleteAllGlCompiled
  end sub

  type vector float x,y

  function InterpLine(float f1,vector *p1,*p2,*rr)
  ================================================
  float f2=1-f1
  rr.x=p1.x*f1 + p2.x*f2
  rr.y=p1.y*f1 + p2.y*f2
  end function


  function DrawCurve(vector *r1,*rc,*r2)
  ======================================
  vector r3,r4,rr
  int    i,n
  float  q,f
  indexbase 0
  n=100  'steps
  f=1/n  'increment
  glBegin GL_LINE_STRIP
  for i=0 to n 'plot curve
    q=i*f 'successive ooints
    InterpLine q,r1,rc,r3
    InterpLine q,rc,r2,r4
    InterpLine q,r3,r4,rr
    glVertex2f rr.x,rr.y
  next
  glEnd
  end function


  function DrawRoundShape()
  =========================
  vector pt={ {-1,-1},{1,-1},{1,1},{-1,1} } 'SQUARE
  vector r1,r2
  int    j
  int    j1,j2,j3
  float  q,f
  indexbase 0
  for j=0 to 3 'each pair of control lines
    j1=j    and 3
    j2=j1+1 and 3
    j3=j2+1 and 3
    q=.5  'for midpoints
    InterpLine q,pt[j1],pt[j2],r1
    InterpLine q,pt[j2],pt[j3],r2
    DrawCurve r1,pt[j2],r2
  next
  end function


  sub scene(sys hWnd)
  ===================
  StillFrame
  glClearColor  0.3, 0.0, 0.0, 0.0
  glTranslatef  0.0, 0.0,-1.0
  glScalef      0.3, 0.3, 0.3
  glColor3f     0.5, 1.0, 1.0 ' color 14
  glLinewidth   2.0
  '
  BeginGlCompile shape
  DrawRoundShape
  EndGlCompile
  go shape
  end sub



.

JRS

  • Guest
Re: bezier (petzold) example
« Reply #8 on: June 11, 2014, 07:26:54 PM »
Oh ya ...

I'm working on a BrainFuck bezier version.  :D  :D

Charles Pegge

  • Guest
Re: bezier (petzold) example
« Reply #9 on: June 11, 2014, 07:41:15 PM »
That sounds a little complicated, John. Like producing a magazine in morse code :)

Anyway, these are the key functions for generating the curves (extracted from the above example).

Each curve is generated from using a pair of control lines which share a common point

Code: [Select]
type vector float x,y

  function InterpLine(float f1,vector *p1,*p2,*rr)
  ================================================
  float f2=1-f1
  rr.x=p1.x*f1 + p2.x*f2
  rr.y=p1.y*f1 + p2.y*f2
  end function


  function DrawCurve(vector *r1,*rc,*r2)
  ======================================
  vector r3,r4,rr
  int    i,n
  float  q,f
  indexbase 0
  n=100  'steps
  f=1/n  'increment
  glBegin GL_LINE_STRIP
  for i=0 to n 'plot curve
    q=i*f 'successive ooints
    InterpLine q,r1,rc,r3
    InterpLine q,rc,r2,r4
    InterpLine q,r3,r4,rr
    glVertex2f rr.x,rr.y
  next
  glEnd
  end function
« Last Edit: June 11, 2014, 07:50:17 PM by Charles Pegge »

JRS

  • Guest
Re: bezier (petzold) example
« Reply #10 on: June 11, 2014, 09:09:39 PM »
How about a PIE function?



Code: [Select]
' ScriptBasic GFX - Alpha Pie

IMPORT gfx.inc

gfx::Window 640, 480, "ScriptBasic GFX - Alpha Pie"
' Random Value Arrays
RANDOMIZE(gfx::Time())
FOR i = 0 TO 512
  rx[i] = RND() % 640
  ry[i] = 60 + RND() % 480 - 80
  rz[i] = RND() % 100
  a1[i] = RND() % 360
  a2[i] = RND() % 360
  rr[i] = RND() AND  255
  rg[i] = RND() AND  255
  rb[i] = RND() AND  255
  af = rx[i] / 640
  ra[i] = INT(255 * af)
NEXT
ts = gfx::Time()
gfx::SDL_SetClipRect 0, 0, 640, 480
FOR i = 0 TO 512 STEP 2
  gfx::filledPieRGBA rx[i], ry[i], rz[i], a1[i], a2[i], rr[i], rg[i], rb[i], ra[i]
NEXT 
te = gfx::Time()
gfx::stringColor 20, 15,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
gfx::Update
WHILE gfx::KeyName(1) <> "-escape"
WEND
gfx::Close

Charles Pegge

  • Guest
Re: bezier (petzold) example
« Reply #11 on: June 11, 2014, 11:44:39 PM »

Controlling the curved regions:

Code: [Select]
  function DrawRoundShape(float q)
  ================================
  vector pt={ {-1,-1},{1,-1},{1,1},{-1,1} } 'SQUARE
  vector r1,r2,r3
  int    j
  int    j1,j2,j3
  float  q1,q2,f
  q1=q : q2=1-q
  indexbase 0
  for j=0 to 3 'each pair of control lines
    j1=j    and 3
    j2=j1+1 and 3
    j3=j2+1 and 3
    InterpLine q1,pt[j1],pt[j2],r1
    InterpLine q2,pt[j2],pt[j3],r2
    InterpLine q1,pt[j2],pt[j3],r3
    DrawCurve r1,pt[j2],r2
    'FLAT
    glBegin GL_LINE_STRIP
    glVertex2f r2.x,r2.y
    glVertex2f r3.x,r3.y
    glEnd
  next
  end function

.

Charles Pegge

  • Guest
Re: bezier (petzold) example
« Reply #12 on: June 12, 2014, 01:03:35 AM »

Painted:

Code: [Select]
  function DrawRoundShape(float q)
  ================================
  vector pt={ {-1,-1},{1,-1},{.5,1},{-.5,1} }
  vector r1,r2,r3,rc
  int    j
  int    j1,j2,j3
  float  q1,q2,f
  q1=q
  q2=1-q
  indexbase 0
  for j=0 to 3 'each pair of control lines
    j1=j    and 3
    j2=j1+1 and 3
    j3=j2+1 and 3
    InterpLine q1,pt[j1],pt[j2],r1
    InterpLine q2,pt[j2],pt[j3],r2
    InterpLine q1,pt[j2],pt[j3],r3
    rc.x=0
    rc.y=0
    glBegin GL_TRIANGLE_FAN
    glVertex2f rc.x,rc.x
    DrawCurve r1,pt[j2],r2
    'IN-FILL
    glBegin GL_TRIANGLES
    glVertex2f rc.x, rc.y
    glVertex2f r2.x, r2.y
    glVertex2f r3.x, r3.y
    glEnd
  next
  end function


.

Charles Pegge

  • Guest
Re: bezier (petzold) example
« Reply #13 on: June 13, 2014, 08:03:34 AM »

One further shape:



.