Here's another method: create a grid whose vertices are shared, so you can adjust one vertex - rather than a group - to manipulate a point on the landscape. (Requires Matrix1.)
This image details how it works.
set display mode desktop width(), desktop height(), 32, 1
sync on : sync rate 30 : sync
global scrW, scrH
scrW = screen width()
scrH = screen height()
// generate image for texture.
// the texture has noise, and red and blue lines which will indicate
// the scene x and z axes when applied to the object.
cls rgb(255,255,255)
for n = 1 to 300 : c = 96+rnd(64) : dot rnd(64), rnd(64), rgb(c,c,c) : next n
dot 0, 0, 0xffff0000 : dot 63, 0, 0xff00ff00 : dot 0, 63, 0xff0000ff : dot 63, 63, 0xff000000
line 4, 60, 60, 60, 0xffff0000 : line 4, 60, 4, 4, 0xff0000ff
get image 1, 0, 0, 64, 64
cls 0
// setup grid: gridW tiles by gridH tiles, with each tile gridTileW by gridTileH.
gridW = 3
gridH = 3
gridTileW = 10
gridTileH = 10
// [enter grid dimensions or skip to leave default]
input "grid width: ", tempW
input "grid height: ", tempH
input "tile width: ", tempTileW
input "tile height: ", tempTileH
if tempW <> 0 then gridW = tempW
if tempH <> 0 then gridH = tempH
if tempTileW <> 0 then gridTileW = tempTileW
if tempTileH <> 0 then gridTileH = tempTileH
cls 0
// work out the number of verts, tris and indices the object will have.
numV = (gridW+1) * (gridH+1)
numT = gridW * gridH * 2
numI = numT * 3
// make new blank object and apply the texture.
make object new 1, numV, numI, FVF_XYZ || FVF_DIFFUSE || FVF_NORMAL || FVF_TEX1
texture object 1, 1
// arrange object into grid.
lock vertexdata for limb 1, 0
// setup vertices.
V = -1
for Z = 0 to gridH
for X = 0 to gridW
inc V
set vertexdata position V, X*gridTileW, 0, Z*gridTileH
set vertexdata uv V, 1.0/gridW * X, 1.0 - (1.0/gridH * Z)
text X*35, gridH*35-Z*35, str$(V) // [debug info]
next X
next Z
// [debug info]
cursx = (gridW+2)*35
cursy = 20
text cursx, 0, "T: i1..i3 [v1, v2, v3] for each triangle T"
text 0, (gridH+2)*35, "numV: " + str$(numV)
text 0, (gridH+2)*35+15, "numT: " + str$(numT)
text 0, (gridH+2)*35+30, "numI: " + str$(numI)
text 0, (gridH+2)*35+45, "Press key..."
// setup triangles/indices.
for T = 1 to numT step 2
V = ceil((T*1.0)/2.0) + floor((T-1.0)*1.0/(gridW*2.0)) - 1
// odd tri.
I = (T-1)*3 - 1
set indexdata I+1, V
set indexdata I+2, V+gridW+1
set indexdata I+3, V+1
// even tri.
set indexdata I+4, V+gridW+1
set indexdata I+5, V+gridW+2
set indexdata I+6, V+1
// [debug info]
if cursy < scrH
text cursx, cursy, padleft$(str$(T),2) + ": " + str$(I+1) + ".." + str$(I+3) + " [" + str$(V) + ", " + str$(V+gridW+1) + ", " + str$(V+1) + "]"
text cursx, cursy+14, padleft$(str$(T),2) + ": " + str$(I+4) + ".." + str$(I+6) + " [" + str$(V+gridW+1) + ", " + str$(V+gridW+2) + ", " + str$(V+1) + "]"
inc cursy, 30
endif
next T
unlock vertexdata
// wait for key press.
sync
nice wait no key
nice wait key
// setup and view scene.
set ambient light 50
position camera 0, 15, -25
point camera 0,0,0
// main loop.
do
// update camera
rotate camera camera angle x() + mousemovey(), camera angle y() + mousemovex(), 0
move camera upkey()-downkey()
move camera right rightkey()-leftkey()
// [ press w to toggle grid wireframe. ]
// [ hold r to distort grid. ]
oi$ = i$
i$ = inkey$()
if oi$ <> i$
if i$ = "w"
wire = 1-wire
set object wireframe 1, wire
endif
endif
if i$ = "r"
lock vertexdata for limb 1, 0
for n = 1 to 20
v = rnd(numV-1)
x# = get vertexdata position x(v) + RndSign()*0.1
y# = get vertexdata position y(v) + RndSign()*0.4
z# = get vertexdata position z(v) + RndSign()*0.1
set vertexdata position v, x#, y#, z#
next n
unlock vertexdata
set object normals 1
endif
// info
set cursor 0,0
print "w: toggle wire, r: distort"
print "polygons ", statistic(1)
print "drawcalls ", statistic(5)
print "numV: ", numV
print "numT: ", numT
print "numI: ", numI
print "fps: ", screen fps()
sync
nice wait 15
loop
function RndSign()
out = rnd(1)*2-1
endfunction out
#constant FVF_XYZ = 0x002
#constant FVF_XYZRHW = 0x004
#constant FVF_XYZB1 = 0x006
#constant FVF_XYZB2 = 0x008
#constant FVF_XYZB3 = 0x00a
#constant FVF_XYZB4 = 0x00c
#constant FVF_XYZB5 = 0x00e
#constant FVF_NORMAL = 0x010
#constant FVF_PSIZE = 0x020
#constant FVF_DIFFUSE = 0x040
#constant FVF_SPECULAR = 0x080
#constant FVF_TEX0 = 0x000
#constant FVF_TEX1 = 0x100
#constant FVF_TEX2 = 0x200
#constant FVF_TEX3 = 0x300
#constant FVF_TEX4 = 0x400
#constant FVF_TEX5 = 0x500
#constant FVF_TEX6 = 0x600
#constant FVF_TEX7 = 0x700
#constant FVF_TEX8 = 0x800
notes:
- spent a while trying to get it to look nice with standard dbp lights, gave me some trouble so I gave up. Should work like any other object in a shader though?
- sharing vertices is like having everything be in one 3dsmax smoothing group; each triangle having its own unshared verts is the only way to get hard edges (I may have once read that this may not be true if you use a normal map in a shader, but I don't know) (note that its not a limitation of using vertexdata stuff, just of this particular approach).
On repeat reads, this probably wasn't what you were after, but hope it may be of use