ok, still been working on this, and I think I've made some improvements. Frame rate greatly improved by making each turn its own object. To use the function, you just declare the globals at the top of the code, initialize them, then call the drawroad function. You must alternate between left and right turns for now, still haven't fixed two turns in the same direction back t back yet. Any comments greatly appreciated.
Oh, if you want, you can adjust the z values inside the function to create hilly roads. Have fun.
REM Project: Curved Roads Function
REM Created: 3/7/2007 8:15:47 PM
REM Created by Mike Shihrer
REM ***** Main Source File *****
REM
REM demonstrates function to draw curved roads.
REM at this time, turns must alternate between left and right, it'll screw up if you try to draw two left turns or two right turns in a row
REM for simplicity sake for me, the -z coordinate is actually the height value
REM feel free to use this code, a credit to me would be cool though, thanks
autocam off
load image "road.jpg",1
dim coordinatearray#(4,16) REM array stores x,y coords for triangles to be drawn, first dimension for x,y coordinates, second dimension for max segments per section
Global objectcount as integer rem keeps track of number of road sections
Global xcenter as float rem center of radius of turn x position
Global ycenter as float rem center of radius of turn y position
Global prevangle as float rem the angle of the end of the last curve section
Global lastradius as float rem the outside radius of the last curve section
Global limbcount as integer rem keeps running total of limbs
Global lastdirection as integer rem keeps track of last direction
rem initialize variables
xcenter = 0 rem pick somewhere way out in space to avoid negative numbers
ycenter = 0 rem pick somewhere way out in space to avoid negative numbers
prevangle = 0 rem start angle of first turn, set to zero
lastradius = 0 rem should start at zero here
limbcount = 0 rem stores limbcount per road section
lastdirection = 0 rem last road section direction
objectcount = 500 rem starting road section object number
rem parameters are : drawroad(direction 0 for left, 1 for right,x pos of radius center, y pos of radius center, inside radius, outside radius, segments per curve, angle of turn, last turn ending angle, object number)
rem this routine will draw a random road with 250 turns, with random radius angle from 0 to 90 degrees
rem road width is set at 40 units, the difference between outside radius and inside radius
rem there are 8 segments, or 16 triangles per section
rem so total polygon count should be 16 x 250
rem you can just keep calling the function and by changing the angle of the turn, and alternating the direction, you can design your own roads
rem 8 segments per 90 degrees of turn seems to be pretty good
a = 0
for i = 500 to 750 rem this will make 250 turns
drawroad(a,xcenter,ycenter,300,340,8,rnd(90),prevangle,objectcount)
if a = 0
a = 1
else
a = 0
endif
next i
position camera coordinatearray#(1,1),coordinatearray#(2,1),-10
xrotate camera 270
Do
movecamera()
displaydata()
Loop
function drawroad(direction as integer,centerx as float, centerY as float, insideradius as float, outsideradius as float, segments as integer, angle as float,lastangle as float,objects as integer)
xpi as float
ypi as float
xpo as float
ypo as float
a as float
calcangle as float
calcangle = angle / segments
if direction = 0 rem this is for left turns
rem Calculate radius centerx and centery between turns
xcenter = centerx + (insideradius + lastradius) * cos(lastangle)
ycenter = centery + (insideradius + lastradius) * sin(lastangle)
if lastdirection = 1
a = wrapvalue(lastangle - 180)
else
a = lastangle
endif
rem plot the x and y positions on the curves
for b = 1 to (segments + 1)
xpi = xcenter + insideradius * cos(a)
ypi = ycenter + insideradius * sin(a)
xpo = xcenter + outsideradius * cos(a)
ypo = ycenter + outsideradius * sin(a)
REM store the segment coordinate positions in an array so we can have the positions for the triangles
coordinatearray#(1,b) = xpi
coordinatearray#(2,b) = ypi
coordinatearray#(3,b) = xpo
coordinatearray#(4,b) = ypo
a = a + calcangle
next b
rem update prevangle with ending angle of curve, update lastradius so can calculate next radius centerx and centery
if lastdirection = 1
prevangle = wrapvalue((angle + lastangle)+ 180)
else
prevangle = wrapvalue((angle + lastangle))
endif
lastradius = outsideradius
lastdirection = 0
endif
if direction = 1 rem this is for right turns
xcenter = centerx + (insideradius + lastradius) * cos(lastangle)
ycenter = centery + (insideradius + lastradius) * sin(lastangle)
a = lastangle + 180
for b = 1 to (segments + 1)
xpi = xcenter + insideradius * cos(a)
ypi = ycenter + insideradius * sin(a)
xpo = xcenter + outsideradius * cos(a)
ypo = ycenter + outsideradius * sin(a)
REM store the segment coordinate positions in an array so we can have the positions for the triangles
coordinatearray#(1,b) = xpi
coordinatearray#(2,b) = ypi
coordinatearray#(3,b) = xpo
coordinatearray#(4,b) = ypo
a = a - calcangle
next b
prevangle = wrapvalue(a + calcangle)
lastradius = outsideradius
lastdirection = 1
endif
rem loop through the coordinatearray and draw the triangles
for i = 1 to segments
if object exist(1) = 0
if direction = 0
make object triangle 1,coordinatearray#(1,i),coordinatearray#(2,i),0,coordinatearray#(3,i + 1),coordinatearray#(4,i + 1),0,coordinatearray#(3,i),coordinatearray#(4,i),0
else
make object triangle 1,coordinatearray#(1,i),coordinatearray#(2,i),0,coordinatearray#(3,i),coordinatearray#(4,i),0,coordinatearray#(3,(i+1)),coordinatearray#(4,(i+1)),0
endif
i = 0
else
if direction = 0
make object triangle 2,coordinatearray#(1,i),coordinatearray#(2,i),0,coordinatearray#(3,i + 1),coordinatearray#(4,i + 1),0,coordinatearray#(3,i),coordinatearray#(4,i),0
else
make object triangle 2,coordinatearray#(1,i),coordinatearray#(2,i),0,coordinatearray#(3,i),coordinatearray#(4,i),0,coordinatearray#(3,(i+1)),coordinatearray#(4,(i+1)),0
endif
make mesh from object 1,2
add limb 1, limbcount + i ,1
delete object 2
delete mesh 1
endif
next i
limbcount = limbcount + segments
for ii = 1 to segments
if direction = 0
make object triangle 2 ,coordinatearray#(3,ii + 1 ),coordinatearray#(4,ii + 1 ),0,coordinatearray#(1,ii),coordinatearray#(2,ii),0,coordinatearray#(1,ii + 1 ),coordinatearray#(2,ii + 1 ),0
else
make object triangle 2 ,coordinatearray#(3,ii + 1 ),coordinatearray#(4,ii + 1 ),0,coordinatearray#(1,ii + 1),coordinatearray#(2,ii + 1),0,coordinatearray#(1,ii ),coordinatearray#(2,ii ),0
endif
make mesh from object 1, 2
add limb 1, limbcount + ii ,1
delete object 2
delete mesh 1
next ii
limbcount = 0 rem reset limbcount to zero for next object
make mesh from object 1,1
make object objects,1,1
delete mesh 1
delete object 1
inc objectcount
endfunction
function movecamera()
if upkey() then move camera .25
if downkey() then move camera -.5
if leftkey() then turn camera left .075
if rightkey() then turn camera right .075
endfunction
function displaydata()
text 40,20, "FPS: " + Str$(screen fps())
text 40,60, "leftkey/rightkey to turn, upkey/downkey for forward or reverse"
endfunction