Ok, so this is a little bit longer than a code 'snippet', but it's probably better off here than Program Announcements
Basically, I made this program for a project with EVOLVED's Advanced Lighting, since 3D World Studio terrain doesn't seem to work well with it. It has most of the features of the 3D World Studio terrain editor, apart from texture painting, because I have NO idea how to do that
Feel free to play around with the code, edit it, use it however you want, etc! If you just want to use it to make terrains, you can just copy and paste it into a new project, and it should work fine. You can export terrains you've created as .dbo or .x objects.
+ Code SnippetRem Project: Terrain editor
Rem Created: Monday, September 09, 2013
Rem ***** Main Source File *****
rem CHANGE THESE TO ALTER THE TERRAIN SIZE/VERTEX COUNT!
global terrainwidth# = 1000.0
global terrainheight# = 1000.0
rem Note: Trying to save a terrain as .x with a row/column ratio of anything over 52x52 will probably cause a crash!
global terrainrows = 70
global terraincolumns = 70
rem loadname$ can be changed to a filename to load a saved .ter file, instead of creating a new terrain
loadname$ = ""
sync on : sync rate 375
autocam off
disable escapekey
oldcamangle = make vector3(1)
newcamangle = make vector3(2)
objposition = make vector3(3)
global pensize = 25
global mousex#
global mousey#
global movecamposx#
global movecamposz#
global yadjustvertex
global camangle# = 0
global camdistance# = 150.0
global camheight# = 100.0
global datainput
global xwidth
global zwidth
global rows
global columns
global currentlimb = 1
global limbx#
global limbz#
global xdifference
global zdifference
global changelimbtext
global disablecltext as boolean
intensity# = 5
set text font "Arial Bold"
set text size 40
coordimages(42, 42)
set text size 15
terrainmode = 1
camfollow = 1
enablethis = 0
wframe = 1
rem Initialise the array for smoothing the limb edges
dim vertexxz1#()
dim vertexy1#()
dim vertexxz2#()
dim vertexy2#()
if loadname$ = ""
terrainwidth# = terrainwidth# / 2
terrainheight# = terrainheight# / 2
else
open datafile to read 1, loadname$
terrainwidth# = datafile float(1)
terrainheight# = datafile float(1)
terrainrows = datafile integer(1)
terraincolumns = datafile integer(1)
endif
make object plain 1, terrainwidth#, terrainheight#, terrainrows, terraincolumns
make mesh from object 2, 1
delete object 1
rem Add the other 3 parts of the terrain
make object sphere 1, 0
for i = 1 to 4
add limb 1, i, 2
next i
offset limb 1, 1, -terrainwidth# / 2, 0, -terrainheight# / 2
offset limb 1, 2, -terrainwidth# / 2, 0, terrainheight# / 2
offset limb 1, 3, terrainwidth# / 2, 0, -terrainheight# / 2
offset limb 1, 4, terrainwidth# / 2, 0, terrainheight# / 2
scale limb 1, 0, 0, 0, 0
rem Each limb has it's own colour to distinguish it - Green is always the 'selected limb' colour
color limb 1, 1, RGB(0,192,0)
color limb 1, 2, RGB(255,0,255)
color limb 1, 3, RGB(0,255,255)
color limb 1, 4, RGB(255,0,0)
limbx# = limb offset x(1, currentlimb)
limbz# = limb offset z(1, currentlimb)
set object wireframe 1, 1
make object sphere 2, 100, 100, 100
scale object 2, pensize, 5, pensize
color object 2, RGB(255,192,0)
set alpha mapping on 2, 48
position object 2, -terrainwidth# / 2, 0, -terrainheight# / 2
make object sphere 7, 6
color object 7, rgb(255, 0, 0)
rem Make and position the coord plains
for i = 3 to 6
make object plain i, 35, 35
texture object i, i-2
set object light i, 0
next i
position object 3, limbx#, 30, limbz# + (terrainheight# / 2) + 20
position object 4, limbx#, 30, limbz# + (terrainheight# / -2) - 20
position object 5, limbx# + (terrainwidth# / 2) + 20, 30, limbz#
position object 6, limbx# + (terrainwidth# / -2) - 20, 30, limbz#
lock vertexdata for limb 1, currentlimb
meshno = get vertexdata vertex count()
calculatexcoords(meshno)
rem Load the terrain height data from a saved file
if loadname$ > ""
unlock vertexdata
for k = 1 to 4
lock vertexdata for limb 1, k
for i = 0 to meshno
vheight# = datafile float(1)
set vertexdata position i, get vertexdata position x(i), vheight#, get vertexdata position z(i)
next i
unlock vertexdata
next k
close datafile 1
lock vertexdata for limb 1, currentlimb
endif
position camera -100, 50, 0
do
position mouse screen width() / 2, screen height() / 2
if editmode <> 0
speed# = 0.40
if shiftkey() = 1 then speed# = 0.9
if keystate(17) = 1 then move camera speed#
if keystate(31) = 1 then move camera -speed#
if keystate(30) = 1 then move camera left speed#
if keystate(32) = 1 then move camera right speed#
else
rem Control the chase camera in Edit Mode
if camfollow = 1
if keystate(17) = 1 then dec camdistance#, 0.25
if keystate(31) = 1 then inc camdistance#, 0.25
if camdistance# < 1 then camdistance# = 1
if keystate(30) = 1 and keyhold = 0 then camside = wrapvalue(camside + 90) : keyhold = scancode()
if keystate(32) = 1 and keyhold = 0 then camside = wrapvalue(camside - 90) : keyhold = scancode()
camangle# = curveangle(camside, camangle#, 30)
if shiftkey() = 1 then inc camheight#, 0.22
if controlkey() = 1 then dec camheight#, 0.22
endif
endif
mousex# = mousemovex()
mousey# = mousemovey()
mousez# = mousemovez()
if val(inkey$()) = 1 then editmode = 0
if val(inkey$()) = 2 then editmode = 1
if mousez# <> 0
pensize = clamp(pensize + clamp(mousez#, -2, 2), 5, 120)
scale object 2, pensize * 2, 5, pensize * 2
endif
if editmode = 1 rem Start of the Edit Mode if block
text 0, 0, "Cam mode(1-2): Free flight mode"
rotate camera camera angle x() + mousey# / 4, camera angle y() + mousex# / 4, camera angle z()
else
text 0, 0, "Cam mode(1-2): Edit mode"
text 0, 20, "Shift-Ctrl to adjust cam height"
if camfollow = 1 : text 0, 40, "Cam follow on (f)" : else : text 0, 40, "Cam follow off (f)" : endif
text 0, 60, "Pen size(mousewheel): " + str$(pensize)
if penmode = 0 : text 0, 80, "Pen(Tabs): Round" : else : text 0, 80, "Pen(Tabs): Square" : endif
if keystate(33) = 1 and keyhold = 0 then camfollow = abs(camfollow - 1) : keyhold = scancode()
rem Change the pen from a circle to a square, and back again... Magic :3
if keystate(15) = 1 and keyhold = 0
set vector3 to object position 3, 2
delete object 2
if penmode = 0
make object box 2, 100, 100, 100 : penmode = 1
yrotate object 2, 45
fix object pivot 2
else
make object sphere 2, 100, 100, 100 : penmode = 0
endif
scale object 2, pensize * 2, 5, pensize * 2
color object 2, RGB(255,192,0)
set alpha mapping on 2, 48
position object 2, x vector3(3), y vector3(3), z vector3(3)
keyhold = scancode()
endif
rem Calculate what angle to move the selector from
if camside / 90 = 0 or camside / 90 = 2
if camside / 90 = 0 then mousey# = mousey# * -1
if camside / 90 = 2 then mousex# = mousex# * -1
position object 2, object position x(2) + mousex# / 4, object position y(2), object position z(2) + mousey# / 4
else
if camside / 90 = 1 then mousex# = mousex# * -1 : mousey# = mousey# * -1
position object 2, object position x(2) + mousey# / 4, object position y(2), object position z(2) + mousex# / 4
endif
limbselect(colourmode)
pointcamera(2, 20, camfollow)
rem Calculate the selector's height on the terrain
getcurrentheight(meshno)
if mouseclick() = 1 or mouseclick() = 2
position object 2, object position x(2), curvevalue(get vertexdata position y(yadjustvertex), object position y(2), 15), object position z(2)
else
position object 2, object position x(2), curvevalue(get vertexdata position y(yadjustvertex), object position y(2), 45), object position z(2)
endif
position object 7, get vertexdata position x(yadjustvertex) + limbx#, get vertexdata position y(yadjustvertex), get vertexdata position z(yadjustvertex) + limbz#
if terrainmode = 1
text 10, screen height() - 25, "Edit tool(z-x to change): Sculpt"
if mouseclick() = 1 or mouseclick() = 2
for i = 0 to meshno
x# = get vertexdata position x(i) + limbx#
z# = get vertexdata position z(i) + limbz#
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize)
if mouseclick() = 1
set vertexdata position i, get vertexdata position x(i), get vertexdata position y(i) + intensity# * 0.03, get vertexdata position z(i)
else
set vertexdata position i, get vertexdata position x(i), get vertexdata position y(i) - intensity# * 0.03, get vertexdata position z(i)
endif
endif
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
if terrainmode = 2
text 10, screen height() - 25, "Edit tool(z-x to change): Sculpt(smooth)"
if mouseclick() = 1 or mouseclick() = 2
for i = 0 to meshno
x# = get vertexdata position x(i) + limbx#
z# = get vertexdata position z(i) + limbz#
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize)
pensize# = pensize
dividenumber# = (pensize# - pensize# * 0.1) / 90
smoothsculpt# = sin(90 - distance# / dividenumber#) * (intensity# * 0.03)
if smoothsculpt# < 0 then smoothsculpt# = 0
if mouseclick() = 1
set vertexdata position i, get vertexdata position x(i), get vertexdata position y(i) + smoothsculpt#, get vertexdata position z(i)
else
set vertexdata position i, get vertexdata position x(i), get vertexdata position y(i) - smoothsculpt#, get vertexdata position z(i)
endif
endif
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
if terrainmode = 3
text 10, screen height() - 25, "Edit tool(z-x to change): Add noise"
if mouseclick() = 1
for i = 0 to meshno
x# = get vertexdata position x(i) + limbx#
y# = get vertexdata position y(i)
z# = get vertexdata position z(i) + limbz#
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize) then set vertexdata position i, get vertexdata position x(i), y# + sin((timer() + (i*(500 + (i * i)))) / 1.5) * (intensity# * 0.03), get vertexdata position z(i)
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
if terrainmode = 4
text 10, screen height() - 25, "Edit tool(z-x to change): Flatten"
if mouseclick() = 1
if lockedheight = 0 then lockedheight = yadjustvertex
for i = 0 to meshno
x# = get vertexdata position x(i) + limbx#
y# = get vertexdata position y(i)
z# = get vertexdata position z(i) + limbz#
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize) then set vertexdata position i, get vertexdata position x(i), curvevalue(get vertexdata position y(lockedheight), y#, 106 - (intensity# * 3)), get vertexdata position z(i)
next i
if penmode = 0 then yrotate object 2, 0
endif
if mouseclick() = 0 then lockedheight = 0
endif
if terrainmode = 5
text 10, screen height() - 25, "Edit tool(z-x to change): Smooth"
if mouseclick() = 1
if zgap# = 0
if xdifference > 0 then xgap# = abs(get vertexdata position x(meshno / 2) - get vertexdata position x((meshno / 2) + 1))
zgap# = abs(get vertexdata position z(meshno / 2) - get vertexdata position z(meshno / 2 + xdifference))
endif
for i = 0 to meshno
x# = get vertexdata position x(i) + limbx#
y# = get vertexdata position y(i)
z# = get vertexdata position z(i) + limbz#
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize)
rem Decide the smoothing method to be used, based on how many verticies are available to compare against
smoothmode = 0 : meanvertexheight# = 0
for n = 1 to 4
if n = 1 then vertex = i - xdifference
if n = 2 then vertex = i + xdifference
if n = 3 then vertex = i - 1
if n = 4 then vertex = i + 1
rem If the vertex is close enough, and actually exists...
if (xdifference > 0 and i > xdifference) or n > 2
if vertex => 0 and vertex <= meshno
if abs(get vertexdata position x(vertex) - get vertexdata position x(i)) < xgap# * 1.75 and abs(get vertexdata position z(vertex) - get vertexdata position z(i)) < zgap# * 1.75
meanvertexheight# = meanvertexheight# + get vertexdata position y(vertex) : inc smoothmode
endif
endif
endif
next n
meanvertexheight# = meanvertexheight# / smoothmode
if smoothmode > 0 then set vertexdata position i, get vertexdata position x(i), curvevalue(meanvertexheight#, y#, 110 - (intensity# * 3)), get vertexdata position z(i)
endif
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
rem Join the edges of the limbs to make smooth terrain
text 0, 100, "F1 to join limb edges"
if keystate(59) = 1 and keyhold = 0
for i = 1 to 2
smoothlimbedges(meshno, 0, 1, 2)
smoothlimbedges(meshno, 1, 1, 3)
smoothlimbedges(meshno, 1, 2, 4)
smoothlimbedges(meshno, 0, 3, 4)
next i
keyhold = 59
endif
text 250, screen height() - 50, "Limb: " + str$(currentlimb)
text 250, screen height() - 25, "Vertex: " + str$(yadjustvertex)
endif rem End of the Edit Mode if block
text 10, screen height() - 50, "Intensity(+/- keys to change): " + str$(intensity#)
if colourmode = 0 : text 450, screen height() - 25, "Limb colours(l): Multiple" : else : text 450, screen height() - 25, "Limb colours(l): Single" : endif
text 250, 0, "Press Escape to pause/save"
if wframe = 1 : text 250, 20, "Wireframe on (F5 to change)" : else : text 250, 20, "Wireframe off (F5 to change)" : endif
if keystate(44) = 1 and keyhold = 0 then terrainmode = wrap(terrainmode - 1, 1, 5) : keyhold = scancode()
if keystate(45) = 1 and keyhold = 0 then terrainmode = wrap(terrainmode + 1, 1, 5) : keyhold = scancode()
rem Change the editing intensity
if keystate(12) = 1 or keystate(13) = 1
if holdingkey = 0 then holdingkey = timer()
if disablekey = 0
if keystate(12) = 1 : intensity# = clamp(intensity# - 1, 1, 35) : else : intensity# = clamp(intensity# + 1, 1, 35) : endif
endif
disablekey = 1
if timer() - holdingkey > 400 and heldkey = 0 then heldkey = timer() : disablekey = 0
if heldkey > 0 and timer() - heldkey > 50 then disablekey = 0 : heldkey = timer()
else
if holdingkey > 0 then holdingkey = 0 : heldkey = 0 : disablekey = 0
endif
if keystate(63) = 1 and keyhold = 0 then wframe = abs(wframe - 1) : set object wireframe 1, wframe : keyhold = scancode()
if keystate(38) = 1 and keyhold = 0
colourmode = abs(colourmode - 1)
rem Recolour the limbs
if colourmode = 1
for i = 1 to 4
if i <> currentlimb then color limb 1, i, rgb(255, 40, 10)
next i
else
for i = 1 to 4
if i <> currentlimb
if i = 1 then color limb 1, i, RGB(255,255,0)
if i = 2 then color limb 1, i, RGB(255,0,255)
if i = 3 then color limb 1, i, RGB(0,255,255)
if i = 4 then color limb 1, i, RGB(255,0,0)
endif
next i
endif
keyhold = 38
endif
if escapekey() = 1 then saveandquit()
if timer() - checkfocus > 1300
if has focus() = 0 then saveandquit()
checkfocus = 0
endif
rem Disables a key until you've let it go
if keyhold > 0 and keystate(keyhold) = 0 then keyhold = 0
rem Point the coord icons so the camera can see them
for i = 3 to 6
point object i, camera position x(), camera position y(), camera position z()
next i
sync
loop
function pointcamera(object, speed, camfollow)
set vector3 1, camera angle x(), camera angle y(), camera angle z()
point camera object position x(object), object position y(object), object position z(object)
set vector3 2, camera angle x(), camera angle y(), camera angle z()
if mouseclick() = 1 or mouseclick() = 2 then speed = speed / 4
rotate camera curveangle(x vector3(2), x vector3(1), speed), curveangle(y vector3(2), y vector3(1), speed), z vector3(1)
if camfollow = 1 then set camera to follow object position x(2), object position y(2), object position z(2), camangle#, camdistance#, camheight#, speed * 4, 0
endfunction
function getcurrentheight(meshno)
olddistance# = 100
for i = 0 to meshno
x# = get vertexdata position x(i) + limbx#
z# = get vertexdata position z(i) + limbz#
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if distance# < olddistance# then : olddistance# = distance# : yadjustvertex = i
next i
endfunction
function coordimages(sizex, sizey)
for i = 1 to 4
if i = 1 then print "+Z"
if i = 2 then print "-Z"
if i = 3 then print "+X"
if i = 4 then print "-X"
for k = 1 to 2
sync
next k
get image i, 0.5, 0.5, sizex, sizey
cls
next i
endfunction
function calculatexcoords(meshno)
for k = meshno / 2 to meshno
if get vertexdata position x(k) = get vertexdata position x(meshno / 2) and k <> meshno / 2
xdifference = abs(meshno / 2 - k)
exit
endif
next k
endfunction
function saveandquit()
justsaved = 0
for i = 1 to 7
hide object i
next i
do
if screen = 0
text 50, 50, "F1 to save"
text 50, 100, "F2 to quit (discards unsaved changes)"
text 50, 150, "F3 to cancel"
if keystate(59) = 1 then pausekey(59) : screen = 1 : clear entry buffer
if keystate(60) = 1
if justsaved = 1 then end
do
text 50, 100, "Are you sure you want to quit without saving? TOTALLY sure? :P"
text 50, 125, "Y to quit, N to stay"
if keystate(21) = 1 then pausekey(21) : end
if keystate(49) = 1 then pausekey(49) : exit
sync
loop
endif
if keystate(61) = 1
for i = 1 to 7
show object i
next i
exitfunction
endif
endif
if screen = 1
saveinput$ = entry$(1)
text 50, 50, "Enter the filename to save the terrain as!"
text 50, 75, "Enter just the filename (with extension), or an absolute path"
text 50, 100, "You can export as either .x or .dbo, or save the project as .ter"
text 50, 125, saveinput$
text 50, 175, "Press F3 to go back"
if returnkey() = 1 and saveerror = 0
rem Check the string to make sure it's ok!
saveinput$ = trim$(saveinput$)
saveinput$ = replace all$(saveinput$, "\", "/")
stringdot = last instr(saveinput$, ".")
if stringdot = 0 then saveerror = timer() : reason$ = "Remember to put the file extension!"
if saveerror = 0 and right$(saveinput$, len(saveinput$) - stringdot) <> "x" and right$(saveinput$, len(saveinput$) - stringdot) <> "dbo" and right$(saveinput$, len(saveinput$) - stringdot) <> "ter" then saveerror = timer() : reason$ = "Wrong file extension!"
stringdash = last instr(saveinput$, "/")
if stringdash > 0 and path exist(left$(saveinput$, stringdash)) = 0 then saveerror = timer() : reason$ = "Path does not exist!"
pausekey(28)
rem If it was ok, save the terrain
if saveerror = 0
unlock vertexdata
sync
if file exist(saveinput$) = 1 then delete file saveinput$
make mesh from object 1, 1
if right$(saveinput$, 2) = ".x"
save mesh saveinput$, 1
endif
if right$(saveinput$, 4) = ".dbo"
save object saveinput$, 1
endif
rem Save terrain so it can be opened later
if right$(saveinput$, 4) = ".ter"
saveterrain(saveinput$)
endif
delete mesh 1
lock vertexdata for limb 1, currentlimb
if file exist(saveinput$) = 1
clear entry buffer
filesaved = timer()
justsaved = 1
else
saveerror = timer() : reason$ = "Can't seem to save for some reason :s"
endif
endif
endif
if saveerror > 0
text 50, 150, "Error saving file(" + reason$ + ")"
if timer() - saveerror > 2000 then saveerror = 0
endif
if filesaved > 0
text 50, 150, "File successfully saved!"
if timer() - filesaved > 2500 then filesaved = 0
endif
if keystate(61) = 1 then screen = 0 : pausekey(61)
endif
sync
loop
endfunction
function pausekey(key)
while keystate(key) = 1
endwhile
endfunction
function iswithinlimits(dist#, pensize)
distcompare = 0
pen# = pensize
sindist# = sin(object angle y(2)) * pen#
cosdist# = cos(object angle y(2)) * pen#
if dist# < sindist# + cosdist# or dist# < sindist# - cosdist# or dist# < sindist#*-1 + cosdist#*-1 or dist# < sindist#*-1 - cosdist#*-1 then inc distcompare
endfunction distcompare
function limbselect(colourmode)
objx# = object position x(2)
objy# = object position y(2)
objz# = object position z(2)
oldcurrentlimb = currentlimb
if objx# > limbx# + terrainwidth# / 2
if spacekey() = 0 or currentlimb > 2
if (currentlimb = 1 or currentlimb = 2) and disablecltext = 0 then changelimbtext = timer()
position object 2, limb offset x(1, currentlimb) + terrainwidth# / 2, objy#, objz#
else
inc currentlimb, 2
endif
endif
if objx# < limbx# - terrainwidth# / 2
if spacekey() = 0 or currentlimb < 3
if (currentlimb = 3 or currentlimb = 4) and disablecltext = 0 then changelimbtext = timer()
if not currentlimb < 2 then p = 1
position object 2, limbx# - terrainwidth# / 2, objy#, objz#
else
dec currentlimb, 2
endif
endif
if objz# > limbz# + terrainheight# / 2
if spacekey() = 0 or currentlimb = 2 or currentlimb = 4
if (currentlimb = 1 or currentlimb = 3) and disablecltext = 0 then changelimbtext = timer()
position object 2, objx#, objy#, limb offset z(1, currentlimb) + terrainheight# / 2
else
inc currentlimb
endif
endif
if objz# < limbz# - terrainheight# / 2
if spacekey() = 0 or currentlimb = 1 or currentlimb = 3
if (currentlimb = 2 or currentlimb = 4) and disablecltext = 0 then changelimbtext = timer()
position object 2, objx#, objy#, limb offset z(1, currentlimb) - terrainheight# / 2
else
dec currentlimb
endif
endif
if spacekey() = 1 then disablecltext = 1
rem Show text telling you how to change the current limb
if changelimbtext > 0
text 220, screen height() - 75, "Hold Spacebar to move between limbs!"
if timer() - changelimbtext > 900 or spacekey() = 1 then changelimbtext = 0
endif
if currentlimb <> oldcurrentlimb
unlock vertexdata
rem Colour the limbs
if colourmode = 0
select oldcurrentlimb
case 1
color limb 1, oldcurrentlimb, RGB(255,255,0)
endcase
case 2
color limb 1, oldcurrentlimb, RGB(255,0,255)
endcase
case 3
color limb 1, oldcurrentlimb, RGB(0,255,255)
endcase
case 4
color limb 1, oldcurrentlimb, RGB(255,0,0)
endcase
endselect
else
color limb 1, oldcurrentlimb, rgb(255, 40, 10)
endif
color limb 1, currentlimb, RGB(0,192,0)
lock vertexdata for limb 1, currentlimb
limbx# = limb offset x(1, currentlimb)
limbz# = limb offset z(1, currentlimb)
position object 3, limbx#, 30, limbz# + (terrainheight# / 2) + 20
position object 4, limbx#, 30, limbz# + (terrainheight# / -2) - 20
position object 5, limbx# + (terrainwidth# / 2) + 20, 30, limbz#
position object 6, limbx# + (terrainwidth# / -2) - 20, 30, limbz#
endif
endfunction
function smoothlimbedges(meshno, xorz, limb1, limb2)
empty array vertexxz1#()
empty array vertexy1#()
empty array vertexxz2#()
empty array vertexy2#()
if xdifference > 0 then xgap# = abs(get vertexdata position x(meshno / 2) - get vertexdata position x((meshno / 2) + 1))
zgap# = abs(get vertexdata position z(meshno / 2) - get vertexdata position z(meshno / 2 + xdifference))
for mode = 0 to 1
unlock vertexdata
lock vertexdata for limb 1, limb1
for k = 0 to meshno
if (xorz = 0 and get vertexdata position z(k) > (terrainheight# / 2) - zgap#) or (xorz = 1 and get vertexdata position x(k) > (terrainwidth# / 2) - xgap#)
if mode = 0
array insert at bottom vertexxz1#()
array insert at bottom vertexy1#()
if xorz = 0 : vertexxz1#() = round(get vertexdata position x(k), 0) : else : vertexxz1#() = round(get vertexdata position z(k), 0) : endif
vertexy1#() = get vertexdata position y(k)
else
array index to top vertexxz2#()
array index to top vertexy2#()
while array index valid(vertexxz2#()) = 1
if xorz = 0
if vertexxz2#() = round(get vertexdata position x(k), 0) then set vertexdata position k, get vertexdata position x(k), (vertexy2#() + get vertexdata position y(k)) / 2, get vertexdata position z(k)
else
if vertexxz2#() = round(get vertexdata position z(k), 0) then set vertexdata position k, get vertexdata position x(k), (vertexy2#() + get vertexdata position y(k)) / 2, get vertexdata position z(k)
endif
next array index vertexxz2#()
next array index vertexy2#()
endwhile
endif
endif
next k
unlock vertexdata
lock vertexdata for limb 1, limb2
for k = 0 to meshno
if (xorz = 0 and get vertexdata position z(k) < (terrainheight# / -2) + zgap#) or (xorz = 1 and get vertexdata position x(k) < (terrainwidth# / -2) + xgap#)
if mode = 0
array insert at bottom vertexxz2#()
array insert at bottom vertexy2#()
if xorz = 0 : vertexxz2#() = round(get vertexdata position x(k), 0) : else : vertexxz2#() = round(get vertexdata position z(k), 0) : endif
vertexy2#() = get vertexdata position y(k)
else
array index to top vertexxz1#()
array index to top vertexy1#()
while array index valid(vertexxz1#()) = 1
if xorz = 0
if vertexxz1#() = round(get vertexdata position x(k), 0) then set vertexdata position k, get vertexdata position x(k), (vertexy1#() + get vertexdata position y(k)) / 2, get vertexdata position z(k)
else
if vertexxz1#() = round(get vertexdata position z(k), 0) then set vertexdata position k, get vertexdata position x(k), (vertexy1#() + get vertexdata position y(k)) / 2, get vertexdata position z(k)
endif
next array index vertexxz1#()
next array index vertexy1#()
endwhile
endif
endif
next k
next mode
unlock vertexdata
lock vertexdata for limb 1, currentlimb
endfunction
function round(number#, upordown)
if upordown = 0
tempno = ceil(abs(number#))
else
tempno = floor(abs(number#))
endif
if number# < 0 then tempno = tempno * -1
endfunction tempno
function saveterrain(filename$)
open datafile to write 1, filename$
write datafile float 1, terrainwidth#
write datafile float 1, terrainheight#
write datafile integer 1, terrainrows
write datafile integer 1, terraincolumns
for i = 1 to 4
lock vertexdata for limb 1, i
if tempmeshno = 0 then tempmeshno = get vertexdata vertex count()
for k = 0 to tempmeshno
write datafile float 1, get vertexdata position y(k)
next k
unlock vertexdata
next i
close datafile 1
endfunction
+ Code SnippetRem Project: Terrain editor
Rem Created: Monday, September 09, 2013
Rem ***** Main Source File *****
rem CHANGE THESE TO ALTER THE TERRAIN SIZE/VERTEX COUNT!
terrainwidth# = 1024.0
terrainheight# = 1024.0
terrainrows = 80
terraincolumns = 80
sync on
autocam off
disable escapekey
oldcamangle = make vector3(1)
newcamangle = make vector3(2)
objposition = make vector3(3)
global pensize = 25
global mousex#
global mousey#
global movecamposx#
global movecamposz#
global yadjustvertex
global camangle# = 0
global camdistance# = 150.0
global camheight# = 100.0
global datainput
global xwidth
global zwidth
global rows
global columns
intensity# = 5
set text font "Arial Bold"
set text size 40
coordimages(42, 42)
set text size 15
terrainmode = 1
camfollow = 1
make object plain 1, terrainwidth#, terrainheight#, terrainrows, terraincolumns
color object 1, rgb(255, 100, 50)
set object wireframe 1, 1
make object sphere 2, 100, 100, 100
scale object 2, pensize, 5, pensize
color object 2, rgb(0, 255, 0)
ghost object on 2
make object sphere 7, 6
color object 7, rgb(255, 0, 0)
for i = 3 to 6
make object plain i, 35, 35
if i = 3 then position object i, 0, 30, (terrainheight# / 2) + 20
if i = 4 then position object i, 0, 30, (terrainheight# / -2) - 20
if i = 5 then position object i, (terrainwidth# / 2) + 20, 30, 0
if i = 6 then position object i, (terrainwidth# / -2) - 20, 30, 0
texture object i, i-2
set object light i, 0
next i
lock vertexdata for limb 1, 0
meshno = get vertexdata vertex count()
xdifference = calculatexcoords(meshno)
position camera -100, 50, 0
do
position mouse screen width() / 2, screen height() / 2
if editmode <> 0
speed# = 0.08
if shiftkey() = 1 then speed# = 0.25
if keystate(17) = 1 then move camera speed#
if keystate(31) = 1 then move camera -speed#
if keystate(30) = 1 then move camera left speed#
if keystate(32) = 1 then move camera right speed#
else
rem Control the chase camera in Edit Mode
if camfollow = 1
if keystate(17) = 1 then dec camdistance#, 0.25
if keystate(31) = 1 then inc camdistance#, 0.25
if camdistance# < 1 then camdistance# = 1
if keystate(30) = 1 and keyhold = 0 then camside = wrapvalue(camside + 90) : keyhold = scancode()
if keystate(32) = 1 and keyhold = 0 then camside = wrapvalue(camside - 90) : keyhold = scancode()
camangle# = curveangle(camside, camangle#, 30)
if shiftkey() = 1 then inc camheight#, 0.22
if controlkey() = 1 then dec camheight#, 0.22
endif
endif
mousex# = mousemovex()
mousey# = mousemovey()
mousez# = mousemovez()
if val(inkey$()) = 1 then editmode = 0
if val(inkey$()) = 2 then editmode = 1
if mousez# <> 0
pensize = clamp(pensize + clamp(mousez#, -2, 2), 5, 120)
scale object 2, pensize * 2, 5, pensize * 2
endif
if editmode = 1 rem Start of the Edit Mode if block
text 0, 0, "Cam mode(1-2): Free flight mode"
rotate camera camera angle x() + mousey# / 4, camera angle y() + mousex# / 4, camera angle z()
else
text 0, 0, "Cam mode(1-2): Edit mode"
text 0, 20, "Shift-Ctrl to adjust cam height"
if camfollow = 1 : text 0, 40, "Cam follow on (f key)" : else : text 0, 40, "Cam follow off (f to toggle)" : endif
text 0, 60, "Pen size(mousewheel): " + str$(pensize)
if penmode = 0 : text 0, 80, "Pen shape (Tabs key): Round" : else : text 0, 80, "Pen shape (Tabs key): Square" : endif
if keystate(33) = 1 and keyhold = 0 then camfollow = abs(camfollow - 1) : keyhold = scancode()
rem Change the pen from a circle to a square, and back again... Magic :3
if keystate(15) = 1 and keyhold = 0
set vector3 to object position 3, 2
delete object 2
if penmode = 0
make object box 2, 100, 100, 100 : penmode = 1
yrotate object 2, 45
fix object pivot 2
else
make object sphere 2, 100, 100, 100 : penmode = 0
endif
scale object 2, pensize * 2, 5, pensize * 2
color object 2, rgb(0, 255, 0)
ghost object on 2
position object 2, x vector3(3), y vector3(3), z vector3(3)
keyhold = scancode()
endif
rem Calculate what angle to move the selector from
if camside / 90 = 0 or camside / 90 = 2
if camside / 90 = 0 then mousey# = mousey# * -1
if camside / 90 = 2 then mousex# = mousex# * -1
position object 2, clamp(object position x(2) + mousex# / 4, terrainwidth# / -2, terrainwidth# / 2), object position y(2), clamp(object position z(2) + mousey# / 4, terrainheight# / -2, terrainheight# / 2)
else
if camside / 90 = 1 then mousex# = mousex# * -1 : mousey# = mousey# * -1
position object 2, clamp(object position x(2) + mousey# / 4, terrainwidth# / -2, terrainwidth# / 2), object position y(2), clamp(object position z(2) + mousex# / 4, terrainheight# / -2, terrainheight# / 2)
endif
pointcamera(2, 20, camfollow)
rem Calculate the selector's height on the terrain
getcurrentheight(meshno)
if mouseclick() = 1 or mouseclick() = 2
position object 2, object position x(2), curvevalue(get vertexdata position y(yadjustvertex), object position y(2), 15), object position z(2)
else
position object 2, object position x(2), curvevalue(get vertexdata position y(yadjustvertex), object position y(2), 45), object position z(2)
endif
position object 7, get vertexdata position x(yadjustvertex), get vertexdata position y(yadjustvertex), get vertexdata position z(yadjustvertex)
if terrainmode = 1
text 50, screen height() - 25, "Edit tool(z-x to change): Sculpt"
if mouseclick() = 1 or mouseclick() = 2
for i = 0 to meshno
x# = get vertexdata position x(i)
z# = get vertexdata position z(i)
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize)
if mouseclick() = 1
set vertexdata position i, x#, get vertexdata position y(i) + intensity# * 0.03, z#
else
set vertexdata position i, x#, get vertexdata position y(i) - intensity# * 0.03, z#
endif
endif
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
if terrainmode = 2
text 50, screen height() - 25, "Edit tool(z-x to change): Sculpt(smooth)"
if mouseclick() = 1 or mouseclick() = 2
for i = 0 to meshno
x# = get vertexdata position x(i)
z# = get vertexdata position z(i)
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize)
pensize# = pensize
dividenumber# = (pensize# - pensize# * 0.1) / 90
smoothsculpt# = sin(90 - distance# / dividenumber#) * (intensity# * 0.03)
if smoothsculpt# < 0 then smoothsculpt# = 0
if mouseclick() = 1
set vertexdata position i, x#, get vertexdata position y(i) + smoothsculpt#, z#
else
set vertexdata position i, x#, get vertexdata position y(i) - smoothsculpt#, z#
endif
endif
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
if terrainmode = 3
text 50, screen height() - 25, "Edit tool(z-x to change): Add noise"
if mouseclick() = 1
for i = 0 to meshno
x# = get vertexdata position x(i)
y# = get vertexdata position y(i)
z# = get vertexdata position z(i)
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize) then set vertexdata position i, x#, y# + sin((timer() + (i*(500 + (i * i)))) / 1.5) * (intensity# * 0.03), z#
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
if terrainmode = 4
text 50, screen height() - 25, "Edit tool(z-x to change): Flatten"
if mouseclick() = 1
if lockedheight = 0 then lockedheight = yadjustvertex
for i = 0 to meshno
x# = get vertexdata position x(i)
y# = get vertexdata position y(i)
z# = get vertexdata position z(i)
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize) then set vertexdata position i, x#, curvevalue(get vertexdata position y(lockedheight), y#, 106 - (intensity# * 3)), z#
next i
if penmode = 0 then yrotate object 2, 0
endif
if mouseclick() = 0 then lockedheight = 0
endif
if terrainmode = 5
text 50, screen height() - 25, "Edit tool(z-x to change): Smooth"
if mouseclick() = 1
for i = 0 to meshno
x# = get vertexdata position x(i)
y# = get vertexdata position y(i)
z# = get vertexdata position z(i)
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if penmode = 0
point object 2, x#, object position y(2), z#
distcompare = 0
distcompare = iswithinlimits(distance#, pensize)
endif
if (penmode = 0 and distcompare > 0) or (penmode = 1 and distance# < pensize)
rem If the xdifference variable hasn't been worked out, go for simple smoothing instead
if xdifference > 0 and i > xdifference
meanvertexheight# = (get vertexdata position y(i - 1) + get vertexdata position y(i + 1) + get vertexdata position y(i + xdifference) + get vertexdata position y(i - xdifference)) / 4
else
meanvertexheight# = (get vertexdata position y(i - 1) + get vertexdata position y(i + 1)) / 2
endif
set vertexdata position i, x#, curvevalue(meanvertexheight#, y#, 110 - (intensity# * 3)), z#
endif
next i
if penmode = 0 then yrotate object 2, 0
endif
endif
endif rem End of the Edit Mode if block
text 50, screen height() - 50, "Intensity(+/- keys to change): " + str$(intensity#)
text 250, 0, "Press Escape to pause/save"
if keystate(44) = 1 and keyhold = 0 then terrainmode = wrap(terrainmode - 1, 1, 5) : keyhold = scancode()
if keystate(45) = 1 and keyhold = 0 then terrainmode = wrap(terrainmode + 1, 1, 5) : keyhold = scancode()
if keystate(12) = 1 and keyhold = 0 then intensity# = clamp(intensity# - 1, 1, 35) : keyhold = scancode()
if keystate(13) = 1 and keyhold = 0 then intensity# = clamp(intensity# + 1, 1, 35) : keyhold = scancode()
if escapekey() = 1 then saveandquit()
rem Disables a key until you've let it go
if keyhold > 0 and keystate(keyhold) = 0 then keyhold = 0
rem Point the coord icons so the camera can see them
for i = 3 to 6
point object i, camera position x(), camera position y(), camera position z()
next i
sync
loop
function pointcamera(object, speed, camfollow)
set vector3 1, camera angle x(), camera angle y(), camera angle z()
point camera object position x(object), object position y(object), object position z(object)
set vector3 2, camera angle x(), camera angle y(), camera angle z()
if mouseclick() = 1 or mouseclick() = 2 then speed = speed / 4
rotate camera curveangle(x vector3(2), x vector3(1), speed), curveangle(y vector3(2), y vector3(1), speed), z vector3(1)
if camfollow = 1 then set camera to follow object position x(2), object position y(2), object position z(2), camangle#, camdistance#, camheight#, speed * 4, 0
endfunction
function getcurrentheight(meshno)
olddistance# = 100
for i = 0 to meshno
x# = get vertexdata position x(i)
z# = get vertexdata position z(i)
distance# = abs(x# - object position x(2)) + abs(z# - object position z(2))
if distance# < olddistance# then : olddistance# = distance# : yadjustvertex = i
next i
endfunction
function coordimages(sizex, sizey)
for i = 1 to 4
if i = 1 then print "+Z"
if i = 2 then print "-Z"
if i = 3 then print "+X"
if i = 4 then print "-X"
for k = 1 to 2
sync
next k
get image i, 0.5, 0.5, sizex, sizey
cls
next i
endfunction
function calculatexcoords(meshno)
for k = meshno / 2 to meshno
if get vertexdata position x(k) = get vertexdata position x(meshno / 2) and k <> meshno / 2
xdifference = abs(meshno / 2 - k)
exit
endif
next k
endfunction xdifference
function saveandquit()
justsaved = 0
for i = 1 to 7
hide object i
next i
do
if screen = 0
text 50, 50, "F1 to save"
text 50, 100, "F2 to quit (discards unsaved changes)"
text 50, 150, "F3 to cancel"
if keystate(59) = 1 then pausekey(59) : screen = 1 : clear entry buffer
if keystate(60) = 1
if justsaved = 1 then end
do
text 50, 100, "Are you sure you want to quit without saving? TOTALLY sure? :P"
text 50, 125, "Y to quit, N to stay"
if keystate(21) = 1 then pausekey(21) : end
if keystate(49) = 1 then pausekey(49) : exit
sync
loop
endif
if keystate(61) = 1
for i = 1 to 7
show object i
next i
exitfunction
endif
endif
if screen = 1
saveinput$ = entry$(1)
text 50, 50, "Enter the filename to save the terrain as!"
text 50, 75, "Enter just the filename (with extension), or an absolute path"
text 50, 100, "You can save as either .x or .dbo"
text 50, 125, saveinput$
text 50, 175, "Press F3 to go back"
if returnkey() = 1 and saveerror = 0
rem Check the string to make sure it's ok!
saveinput$ = trim$(saveinput$)
saveinput$ = replace all$(saveinput$, "\", "/")
stringdot = last instr(saveinput$, ".")
if stringdot = 0 then saveerror = timer() : reason$ = "Remember to put the file extension!"
if saveerror = 0 and right$(saveinput$, len(saveinput$) - stringdot) <> "x" and right$(saveinput$, len(saveinput$) - stringdot) <> "dbo" then saveerror = timer() : reason$ = "Wrong file extension!"
stringdash = last instr(saveinput$, "/")
if stringdash > 0 and path exist(left$(saveinput$, stringdash)) = 0 then saveerror = timer() : reason$ = "Path does not exist!"
pausekey(28)
rem If it was ok, save the terrain
if saveerror = 0
unlock vertexdata
sync
if file exist(saveinput$) = 1 then delete file saveinput$
make mesh from object 1, 1
if right$(saveinput$, 2) = ".x"
save mesh saveinput$, 1
else
make object 50, 1
save object saveinput$, 50
delete object 50
endif
delete mesh 1
lock vertexdata for limb 1, 0
if file exist(saveinput$) = 1
clear entry buffer
filesaved = timer()
justsaved = 1
else
saveerror = timer() : reason$ = "Can't seem to save for some reason :s"
endif
endif
endif
if saveerror > 0
text 50, 150, "Error saving file(" + reason$ + ") - check what you've written :P"
if timer() - saveerror > 2000 then saveerror = 0
endif
if filesaved > 0
text 50, 150, "File successfully saved!"
if timer() - filesaved > 2500 then filesaved = 0
endif
if keystate(61) = 1 then screen = 0 : pausekey(61)
endif
sync
loop
endfunction
function pausekey(key)
while keystate(key) = 1
endwhile
endfunction
function iswithinlimits(dist#, pensize)
distcompare = 0
pen# = pensize
sindist# = sin(object angle y(2)) * pen#
cosdist# = cos(object angle y(2)) * pen#
if dist# < sindist# + cosdist# or dist# < sindist# - cosdist# or dist# < sindist#*-1 + cosdist#*-1 or dist# < sindist#*-1 - cosdist#*-1 then inc distcompare
endfunction distcompare