Oxygen Basic
Programming => Problems & Solutions => Topic started by: Frankolinox on June 10, 2014, 08:29:27 AM
-
lalala :)
-
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.
-
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. :)
.
-
Nice Tutorial on Bezier curves:
http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/
-
The SDL_gfx library provides a bezier function. Here is the Script BASIC GFX extension module version of it.
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_alpha_bezier.png)
' 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
-
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.
-
there was only missing one line
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.
-
Generating Bezier curves from scratch:
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
.
-
Oh ya ...
I'm working on a BrainFuck bezier version. :D :D
-
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
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
-
How about a PIE function?
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_alpha_pie.png)
' 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
-
Controlling the curved regions:
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
.
-
Painted:
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
.
-
One further shape:
.