Probably bindun, but I'm learning it at the moment so figured I'd share. Currently very sloppy code, but it works and I'll call back a few times to fix it up and add features and things to it. Uses Matrix1Utils, but you can get round having to use it by getting rid of the "random(?)" bits and replacing them with "(rnd(?*10.0)/10.0)" or something.
Move mouse to orbit camera, scroll mousewheel to zoom in/out. Press control to re-randomize the points, hold shift to slide the middle point along x/y (quick and easy visualisation aid-y thing), or hold space to watch the bezier being traced. Lower cBezierSamples to make the curve less smooth/faster to draw, and vice versa.
set display mode desktop width(), desktop height(), 32, 1
sync on
sync rate 60
#constant cBezierSamples 50.0
type tInputKey
Old
New
endtype
type tVec3D
x as float
y as float
z as float
endtype
type tBezierPoint
pos as tVec3D
handleprev as tVec3D
handlenext as tVec3D
endtype
type tBezierLineThree
start as tBezierPoint
mid as tBezierPoint
last as tBezierPoint
endtype
global gBezier as tBezierLineThree
global Bezier as tBezierLineThree
global gCtrl as tInputKey
// Make Bezier Handles.
for a = 1 to 3
make object cube ((a - 1) * 3) + 1, 2
make object cube ((a - 1) * 3) + 2, 1
make object cube ((a - 1) * 3) + 3, 1
next a
// Make Temp Object.
make object cube 100, 1
`hide object 100
BezierRnd(100.0)
gBezier = Bezier
UpdateBezier()
do
// update input.
gCtrl.Old = gCtrl.New
gCtrl.New = controlkey()
if gCtrl.New
if gCtrl.Old = 0
// Randomize Bezier Line
BezierRnd(100.0)
gBezier = Bezier
UpdateBezier()
endif
endif
if shiftkey()
inc gBezier.Mid.Pos.X, 0.1
inc gBezier.Mid.Pos.Y, 0.1
UpdateBezier()
endif
// Update camera.
rotate camera camera angle x() + mousemovey(), camera angle y() + mousemovex(), 0
position camera 0, 0, 0
move camera -384 + (mousez()/10.0)
// Draw Non-Bezier Line
startx = object screen x(1)
starty = object screen y(1)
midx = object screen x(4)
midy = object screen y(4)
lastx = object screen x(7)
lasty = object screen y(7)
ink rgb(255, 255, 255)
line startx, starty, midx, midy
line midx, midy, lastx, lasty
// DRAW 3D BEZIER.
// We draw two bezier curves: The curve Start-Mid, and the curve Mid-Last.
ink rgb(255, 0, 255)
DrawBezier(gBezier.Start, gBezier.Mid)
DrawBezier(gBezier.Mid, gBezier.Last)
// Draw Handles
starthandleprevx = object screen x(2)
starthandleprevy = object screen y(2)
starthandlenextx = object screen x(3)
starthandlenexty = object screen y(3)
midhandleprevx = object screen x(5)
midhandleprevy = object screen y(5)
midhandlenextx = object screen x(6)
midhandlenexty = object screen y(6)
lasthandleprevx = object screen x(8)
lasthandleprevy = object screen y(8)
lasthandlenextx = object screen x(9)
lasthandlenexty = object screen y(9)
ink rgb(0, 0, 245)
line startx, starty, starthandleprevx, starthandleprevy
line startx, starty, starthandlenextx, starthandlenexty
line midx, midy, midhandleprevx, midhandleprevy
line midx, midy, midhandlenextx, midhandlenexty
line lastx, lasty, lasthandleprevx, lasthandleprevy
line lastx, lasty, lasthandlenextx, lasthandlenexty
set cursor 0, 0
ink rgb(255, 255, 255)
print screen fps()
sync
loop
function BezierRnd(PosRndMax)
Bezier.Start.Pos.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.Pos.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.Pos.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.HandlePrev.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.HandlePrev.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.HandlePrev.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.HandleNext.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.HandleNext.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Start.HandleNext.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.Pos.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.Pos.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.Pos.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.HandlePrev.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.HandlePrev.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.HandlePrev.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.HandleNext.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.HandleNext.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Mid.HandleNext.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.Pos.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.Pos.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.Pos.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.HandlePrev.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.HandlePrev.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.HandlePrev.Z = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.HandleNext.X = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.HandleNext.Y = -(PosRndMax / 2) + (random(PosRndMax))
Bezier.Last.HandleNext.Z = -(PosRndMax / 2) + (random(PosRndMax))
endfunction
function UpdateBezier()
position object 1, gBezier.Start.Pos.X, gBezier.Start.Pos.Y, gBezier.Start.Pos.Z
position object 4, gBezier.Mid.Pos.X, gBezier.Mid.Pos.Y, gBezier.Mid.Pos.Z
position object 7, gBezier.Last.Pos.X, gBezier.Last.Pos.Y, gBezier.Last.Pos.Z
position object 2, gBezier.Start.HandlePrev.X, gBezier.Start.HandlePrev.Y, gBezier.Start.HandlePrev.Z
position object 5, gBezier.Mid.HandlePrev.X, gBezier.Mid.HandlePrev.Y, gBezier.Mid.HandlePrev.Z
position object 8, gBezier.Last.HandlePrev.X, gBezier.Last.HandlePrev.Y, gBezier.Last.HandlePrev.Z
position object 3, gBezier.Start.HandleNext.X, gBezier.Start.HandleNext.Y, gBezier.Start.HandleNext.Z
position object 6, gBezier.Mid.HandleNext.X, gBezier.Mid.HandleNext.Y, gBezier.Mid.HandleNext.Z
position object 9, gBezier.Last.HandleNext.X, gBezier.Last.HandleNext.Y, gBezier.Last.HandleNext.Z
endfunction
function DrawBezier(A as tBezierPoint, B as tBezierPoint)
local AHandlePos as tVec3D
local BHandlePos as tVec3D
ax as float : ay as float : az as float
bx as float : by as float : bz as float
cx as float : cy as float : cz as float
local drawxold = 0
local drawyold = 0
position object 100, A.Pos.X, A.Pos.Y, A.Pos.Z
local drawxnew : drawxnew = object screen x(100)
local drawynew : drawynew = object screen y(100)
`backdrop off
for t = 0 to cBezierSamples
// Get Position along the Next Handle of A.
ax = ((A.HandleNext.X - A.Pos.X) / cBezierSamples) * (t*1.0) + A.Pos.X
ay = ((A.HandleNext.Y - A.Pos.Y) / cBezierSamples) * (t*1.0) + A.Pos.Y
az = ((A.HandleNext.Z - A.Pos.Z) / cBezierSamples) * (t*1.0) + A.Pos.Z
// Get Position along the Prev Handle of B.
bx = ((B.HandlePrev.X - B.Pos.X) / cBezierSamples) * ((cBezierSamples-t)*1.0) + B.Pos.X
by = ((B.HandlePrev.Y - B.Pos.Y) / cBezierSamples) * ((cBezierSamples-t)*1.0) + B.Pos.Y
bz = ((B.HandlePrev.Z - B.Pos.Z) / cBezierSamples) * ((cBezierSamples-t)*1.0) + B.Pos.Z
// Get Position along the Line ax,ay,az - bx,by,bz.
cx = ((bx - ax) / cBezierSamples) * (t*1.0) + ax
cy = ((by - ay) / cBezierSamples) * (t*1.0) + ay
cz = ((bz - az) / cBezierSamples) * (t*1.0) + az
position object 100, cx, cy, cz
drawxold = drawxnew
drawyold = drawynew
drawxnew = object screen x(100)
drawynew = object screen y(100)
// Draw Bezier Curve Section.
line drawxold, drawyold, drawxnew, drawynew
f = f + 1 : if f = 4 and spacekey() then sync : f = 0
next t
`backdrop on
endfunction