This post will probably be long. I want to make a motorcycle simulation, not like a racing a game, but something like riding through the mountains here in California. I've been studying pictures and video I have taken while riding my motorcycle, and realized to simulate this that square matrixs, advanced terrains, or any other terrain system that I have seen will not work. One of the biggest drawbacks I have seen with any terrain system is, the bigger it gets, the slower the frame rates get. This seems to be because if you have a terrain size that is large, DX draws all the polygons regardless if they are on the screen or not, since they are one object. In fact, this is the case with any object, according to my tests. So, even the method for making a sky sphere, inverting the normals on a big sphere, may not be the best method. Modeling a track and or terrain and loading it will give great results, but, I suspect you will still have a frame rate hit because it is still one large object. I verified this with my first attempt at curved roads. The longer the road got, as one object, the slower my frame rate got. So, I started thinking, what is the MAIN thing I want to acheive? I want to create realistic roads. So then, I started thinking about what kind of properties roads have. They have width, they have a turn radius, they have grade (hills), they have shoulders. Everytime I ride my motorcycle, I'm constantly thinking, how can I simulate all this in 3D? Then it hit me. What if I could make the road, and draw the terrain around the road? After looking at my pictures and videos, I realized that you don't see too much terrain besides the actual road and the shoulder and the trees and hills alongside the road. So why do you need all that extra terrain you are never going to see? So, I modified my original curved road function, added the ability to make uphill turns and downhill turns, and I think I'm heading in the right direction. I learned you can use plains and paste images on them to point at you as you move along this road. So trees, rock outcroppings, roadsigns, etc, are no problem, and no big deal, and look 3D when you do them. I learned also that the code I created could also be used for long distance billboards, for mountain scenary. So, instead of creating a sphere and texturing the inside of it, you could place a strip around the road, and texture it. You save all the polys that you never see below you. Here is the function I came up with.
function bands(objcount,group,direction,segments,angle#,radius#,width#,yhi#,yho#,ysv#,cx#,cy#,cz#,sa#,texture)
rem the calc angle is just the total angle divided by the number of segments per turn (resolution)
ca# = angle# / segments
rem variables to store and place y coordinate values (height)
yhoa# = yho#
yhob# = yho# + ysv#
yhia# = yhi#
yhib# = yhi# + ysv#
if direction = 0
a = 2
for I = 2 to segments + 1
rem draws the triangles in a ccw direction, from start angle to angle of turn
make object triangle 1,newxvalue(cx#,sa#,radius#),yhia#,newzvalue(cz#,sa#,radius#),newxvalue(cx#,sa# - ca#,radius# + width#),yhob#,newzvalue(cz#,sa# - ca#,radius# + width#),newxvalue(cx#,sa#,radius# + width#),yhoa#,newzvalue(cz#,sa#,radius# + width#)
make mesh from object a,1
delete object 1
inc a,1
make object triangle 1,newxvalue(cx#,sa#,radius#),yhia#,newzvalue(cz#,sa#,radius#),newxvalue(cx#,sa# - ca#,radius#),yhib#,newzvalue(cz#,sa# - ca#,radius#),newxvalue(cx#,sa# - ca#,radius# + width#),yhob#,newzvalue(cz#,sa# - ca#,radius# + width#)
make mesh from object a ,1
delete object 1
inc a,1
dec sa#,ca#
inc yhia#,ysv#
inc yhib#,ysv#
inc yhoa#,ysv#
inc yhob#,ysv#
next I
else
a = 2
for I = 2 to segments + 1
rem draws the triangles in a cw direction, from start angle to angle of turn
make object triangle 1,newxvalue(cx#,sa# + ca#,radius#),yhib#,newzvalue(cz#,sa# + ca#,radius#),newxvalue(cx#,sa#,radius# + width#),yhoa#,newzvalue(cz#,sa#,radius# + width#),newxvalue(cx#,sa# + ca#,radius# + width#),yhob#,newzvalue(cz#,sa# + ca#,radius# + width#)
make mesh from object a,1
delete object 1
inc a,1
make object triangle 1,newxvalue(cx#,sa# + ca#,radius#),yhib#,newzvalue(cz#,sa# + ca#,radius#),newxvalue(cx#,sa#,radius#),yhia#,newzvalue(cz#,sa#,radius#),newxvalue(cx#,sa#,radius# + width#),yhoa#,newzvalue(cz#,sa#,radius# + width#)
make mesh from object a ,1
delete object 1
inc a,1
inc sa#,ca#
inc yhia#,ysv#
inc yhib#,ysv#
inc yhoa#,ysv#
inc yhob#,ysv#
next I
endif
rem reformat the vertex UV so textures tile properly
lock vertexdata for mesh 2
for a = 3 to (segments * 2) + 1
add mesh to vertexdata a
delete mesh a
next a
VU = get vertexdata index count()
a = 0
for b = 1 to (VU / 6)
set vertexdata uv a + 0,1,0
set vertexdata uv a + 1,0,1
set vertexdata uv a + 2,1,1
set vertexdata uv a + 3,1,0
set vertexdata uv a + 4,0,0
set vertexdata uv a + 5,0,1
inc a,6
next b
unlock vertexdata
rem make it all one object
if group = 0
make object objcount,2,texture
delete mesh 2
else
make mesh from object 1,objcount
delete object objcount
lock vertexdata for mesh 1
add mesh to vertexdata 2
unlock vertexdata
delete mesh 2
make object objcount,1,texture
delete mesh 1
endif
endfunction
By repeating calls to this function, you can make radiating bands of curved segments. If you want a complete circle, make it 360 degrees. If you want a corkscrew, make it greater than 360 degrees and adjust the ysv#( y step value)
Here is a code snippet of it in use, where it creates a a 720 degree hi resolution corkscrew uphill turn, and the camera code to follow it.
autocam off
sync rate 60
set display mode 1024,768,16
set camera range 1,5000
rem load your own texture here, or download mine and point to it
load image "grass.jpg",2
ch = 8
bands(10,0,0,64,720,500,50,0,0,16,0,0,0,0,2)
bands(10,1,0,64,720,550,50,0,4,16,0,0,0,0,2)
bands(10,1,0,64,720,600,50,4,12,16,0,0,0,0,2)
bands(10,1,0,64,720,650,50,12,8,16,0,0,0,0,2)
bands(10,1,0,64,720,700,50,8,24,16,0,0,0,0,2)
position camera 10,ch,520
rem //// main loop ////////////////////////////////////////////////////////
do
lasty# = movecam_on_object(10,ch)
text 0,0, "last y for move height: " + str$(lasty#)
text 0,10, "FPS: " + str$(screen fps())
text 0,20,"polys drawn: " + str$(statistic(1))
loop
rem ////////////////////////////////////////////////////////////////////////
function bands(objcount,group,direction,segments,angle#,radius#,width#,yhi#,yho#,ysv#,cx#,cy#,cz#,sa#,texture)
rem the calc angle is just the total angle divided by the number of segments per turn (resolution)
ca# = angle# / segments
rem variables to store and place y coordinate values (height)
yhoa# = yho#
yhob# = yho# + ysv#
yhia# = yhi#
yhib# = yhi# + ysv#
if direction = 0
a = 2
for I = 2 to segments + 1
rem draws the triangles in a ccw direction, from start angle to angle of turn
make object triangle 1,newxvalue(cx#,sa#,radius#),yhia#,newzvalue(cz#,sa#,radius#),newxvalue(cx#,sa# - ca#,radius# + width#),yhob#,newzvalue(cz#,sa# - ca#,radius# + width#),newxvalue(cx#,sa#,radius# + width#),yhoa#,newzvalue(cz#,sa#,radius# + width#)
make mesh from object a,1
delete object 1
inc a,1
make object triangle 1,newxvalue(cx#,sa#,radius#),yhia#,newzvalue(cz#,sa#,radius#),newxvalue(cx#,sa# - ca#,radius#),yhib#,newzvalue(cz#,sa# - ca#,radius#),newxvalue(cx#,sa# - ca#,radius# + width#),yhob#,newzvalue(cz#,sa# - ca#,radius# + width#)
make mesh from object a ,1
delete object 1
inc a,1
dec sa#,ca#
inc yhia#,ysv#
inc yhib#,ysv#
inc yhoa#,ysv#
inc yhob#,ysv#
next I
else
a = 2
for I = 2 to segments + 1
rem draws the triangles in a cw direction, from start angle to angle of turn
make object triangle 1,newxvalue(cx#,sa# + ca#,radius#),yhib#,newzvalue(cz#,sa# + ca#,radius#),newxvalue(cx#,sa#,radius# + width#),yhoa#,newzvalue(cz#,sa#,radius# + width#),newxvalue(cx#,sa# + ca#,radius# + width#),yhob#,newzvalue(cz#,sa# + ca#,radius# + width#)
make mesh from object a,1
delete object 1
inc a,1
make object triangle 1,newxvalue(cx#,sa# + ca#,radius#),yhib#,newzvalue(cz#,sa# + ca#,radius#),newxvalue(cx#,sa#,radius#),yhia#,newzvalue(cz#,sa#,radius#),newxvalue(cx#,sa#,radius# + width#),yhoa#,newzvalue(cz#,sa#,radius# + width#)
make mesh from object a ,1
delete object 1
inc a,1
inc sa#,ca#
inc yhia#,ysv#
inc yhib#,ysv#
inc yhoa#,ysv#
inc yhob#,ysv#
next I
endif
rem reformat the vertex UV so textures tile properly
lock vertexdata for mesh 2
for a = 3 to (segments * 2) + 1
add mesh to vertexdata a
delete mesh a
next a
VU = get vertexdata index count()
a = 0
for b = 1 to (VU / 6)
set vertexdata uv a + 0,1,0
set vertexdata uv a + 1,0,1
set vertexdata uv a + 2,1,1
set vertexdata uv a + 3,1,0
set vertexdata uv a + 4,0,0
set vertexdata uv a + 5,0,1
inc a,6
next b
unlock vertexdata
rem make it all one object
if group = 0
make object objcount,2,texture
delete mesh 2
else
make mesh from object 1,objcount
delete object objcount
lock vertexdata for mesh 1
add mesh to vertexdata 2
unlock vertexdata
delete mesh 2
make object objcount,1,texture
delete mesh 1
endif
endfunction
function movecam_on_object(obj,height#)
if upkey()
move camera 2
camy# = intersect object(obj,camera position x() ,camera position y() , camera position z() , camera position x(), 0, camera position z())
position camera camera position x(),camera position y() + (height# - camy#),camera position z()
lasty# = camera position y()
endif
if downkey()
move camera -2
camy# = intersect object(obj,camera position x() ,camera position y() , camera position z() , camera position x(), 0, camera position z())
position camera camera position x(),camera position y() + (height# - camy#),camera position z()
lasty# = camera position y()
endif
if leftkey() then turn camera left 2
if rightkey() then turn camera right 2
endfunction lasty#
This is a good test for the polys drawn issue. Make some other turns in different locations and different sizes. As individual objects, if the camera isn't pointing at them, they won't be drawn, and it won't affect your frame rate. I guess what I think is, for large terrains, maybe it's best to break them up into smaller chunks. I have alot of ideas to expand this concept, like create a type to keep track of all the vertex positions for each object. This would be handy for placing trees an rocks and such. Other applications could be train tracks, roller coasters, anything on a track, really.
sorry so long, but, I need some input on if anything like this has been done, I've searched but haven't found anything yet. I guess in it's most basic form I've created a different primitive.
Let me know what you think.