et voila...
sync on : sync rate 60
type vec2
x as float
y as float
endtype
global _vec2 as vec2
type vec3
x as float
y as float
z as float
endtype
global _vec3 as vec3
type bezier4
p0 as vec3
p1 as vec3
p2 as vec3
p3 as vec3
endtype
global _bezier4 as bezier4
type bezier3
p0 as vec3
p1 as vec3
p2 as vec3
endtype
global _bezier3 as bezier3
`------------------------------
`Tunables
`------------------------------
`Constants
#constant POINT_COUNT 32
#constant SHAPE_SIDES 8
#constant SHAPE_SIZE 0.2
`Set bezier curve control points:
_bezier4.p0.x = 0.0 : _bezier4.p0.y = 0.0 : _bezier4.p0.z = 0.0
_bezier4.p1.x = 10.0 : _bezier4.p1.y = 0.0 : _bezier4.p1.z = 0.0
_bezier4.p2.x = 10.0 : _bezier4.p2.y = 8.0 : _bezier4.p2.z = 0.0
_bezier4.p3.x = 10.0 : _bezier4.p3.y = 8.0 : _bezier4.p3.z = 12.0
`2D shape
dim shape(SHAPE_SIDES-1) as vec2
`Make a semicircular shape
for i = 0 to SHAPE_SIDES-1
angle# = i*180.0/(SHAPE_SIDES-1)
shape(i).x = cos(angle#)*SHAPE_SIZE
shape(i).y = sin(angle#)*SHAPE_SIZE
next i
`Up vector
global up as vec3
up.x = 0.0 : up.y = 1.0 : up.z = 0.0
`------------------------------
`Convert curve to line segments
`------------------------------
`Point array
dim points(POINT_COUNT-1) as vec3
a as vec3
b as vec3
`Sample curve at various points
for i = 0 to POINT_COUNT-1
f# = i*1.0/(POINT_COUNT-1)
getBezier4Point(f#)
points(i) = _vec3
next i
`Preview line segments
for i = 1 to POINT_COUNT-1
a = points(i-1)
b = points(i)
make object box i, 0.1, 0.1, vec3Dist(a, b)
vec3Lerp(0.5, a, b)
position object i, _vec3.x, _vec3.y, _vec3.z
point object i, b.x, b.y, b.z
next i
preview()
delete objects 1, POINT_COUNT-1
`Create new object
vertexCount = SHAPE_SIDES*POINT_COUNT
indexCount = SHAPE_SIDES*(POINT_COUNT-1)*3*2 `3 indices per triangle, 2 triangles per quad
make object new 1, vertexCount, indexCount
lock vertexdata for limb 1, 0
normalVec as vec3
v1 as vec3
v2 as vec3
curPoint as vec3
for i = 0 to POINT_COUNT-1
curPoint = points(i)
`Calculate normal vector
if i = 0
a = points(0)
b = points(1)
else
if i = POINT_COUNT-1
a = points(POINT_COUNT-2)
b = points(POINT_COUNT-1)
else
a = points(i-1)
b = points(i+1)
endif
endif
vec3Sub(b, a)
vec3Norm(_vec3)
normalVec = _vec3
`Calculate perpendicular vectors
vec3Cross(up, normalVec)
vec3Norm(_vec3)
v1 = _vec3
vec3Cross(v1, normalVec)
v2 = _vec3
`For each point in the 2D shape
for j = 0 to SHAPE_SIDES-1
vertex = i*SHAPE_SIDES+j
vec3Mul(v1, shape(j).x)
a = _vec3
vec3Mul(v2, shape(j).y)
b = _vec3
vec3Add(a, b)
vec3Add(_vec3, curPoint)
set vertexdata position vertex, _vec3.x, _vec3.y, _vec3.z
vec3Add(a, b)
vec3Norm(_vec3)
set vertexdata normals vertex, _vec3.x, _vec3.y, _vec3.z
next j
next i
for i = 0 to POINT_COUNT-2
for j = 0 to SHAPE_SIDES-1
index = (i*SHAPE_SIDES + j)*3*2
vert0 = i*SHAPE_SIDES+j
vert1 = i*SHAPE_SIDES+((j+1) mod SHAPE_SIDES)
vert2 = (i+1)*SHAPE_SIDES+j
vert3 = (i+1)*SHAPE_SIDES+((j+1) mod SHAPE_SIDES)
set indexdata index+0, vert0
set indexdata index+1, vert2
set indexdata index+2, vert1
set indexdata index+3, vert1
set indexdata index+4, vert2
set indexdata index+5, vert3
next j
next i
unlock vertexdata
set object cull 1, 0
preview()
end
`------------------------------
`Useful functions
`------------------------------
`Simple mouse-look function
global preview_w
global preview_wireframe
function preview()
while returnkey() = 0
if inkey$() = "w"
if preview_w = 0
preview_w = 1
preview_wireframe = 1-preview_wireframe
i = 1
while object exist(i)
set object wireframe i, preview_wireframe
inc i
endwhile
endif
else
preview_w = 0
endif
angx# = camera angle x()
angy# = camera angle y()
inc angx#, mousemovey()*0.5
inc angy#, mousemovex()*0.5
rotate camera angx#, angy#, 0
move camera (upkey() - downkey())*0.1
move camera right (rightkey() - leftkey())*0.1
text 0, 0, "Press enter to continue"
text 0, 20, "Press W to toggle wireframe"
sync
endwhile
while returnkey()
sync
endwhile
endfunction
function vec3Lerp(f#, a as vec3, b as vec3)
f2# = 1.0-f#
_vec3.x = f2#*a.x + f#*b.x
_vec3.y = f2#*a.y + f#*b.y
_vec3.z = f2#*a.z + f#*b.z
endfunction
function vec3Length(a as vec3)
l# = sqrt(a.x*a.x + a.y*a.y + a.z*a.z)
endfunction l#
function vec3Mul(a as vec3, f#)
_vec3.x = a.x*f#
_vec3.y = a.y*f#
_vec3.z = a.z*f#
endfunction
function vec3Norm(a as vec3)
vec3Mul(a, 1.0/vec3Length(a))
endfunction
function vec3Cross(a as vec3, b as vec3)
_vec3.x = a.y*b.z - a.z*b.y
_vec3.y = a.z*b.x - a.x*b.z
_vec3.z = a.x*b.y - a.y*b.x
endfunction
function vec3Add(a as vec3, b as vec3)
_vec3.x = a.x + b.x
_vec3.y = a.y + b.y
_vec3.z = a.z + b.z
endfunction
function vec3Sub(a as vec3, b as vec3)
_vec3.x = a.x - b.x
_vec3.y = a.y - b.y
_vec3.z = a.z - b.z
endfunction
function vec3Dist(a as vec3, b as vec3)
vec3Sub(a, b)
d# = vec3Length(_vec3)
endfunction d#
function getBezier4Point(f#)
vec3Lerp(f#, _bezier4.p0, _bezier4.p1)
_bezier3.p0 = _vec3
vec3Lerp(f#, _bezier4.p1, _bezier4.p2)
_bezier3.p1 = _vec3
vec3Lerp(f#, _bezier4.p2, _bezier4.p3)
_bezier3.p2 = _vec3
getBezier3Point(f#)
endfunction
function getBezier3Point(f#)
a as vec3
b as vec3
vec3Lerp(f#, _bezier3.p0, _bezier3.p1)
a = _vec3
vec3Lerp(f#, _bezier3.p1, _bezier3.p2)
b = _vec3
vec3Lerp(f#, a, b)
endfunction
Not completely plugin free - creating a fresh object with a set number of vertices and indices is a real pain in native dbp. IanM's plugins are practically part of dbp anyway
The first preview you see is just a simple mock-up of the curve using 3D boxes, after pressing enter it will generate a proper mesh using the 2D template (by default a semicircle).
Not bad for 280 lines of code
[b]
