Inspired by reading Visigoth's threads about using USGS terrain data in DBP long ago, I've decided to try my hand at doing so without external tools...to both learn how to build objects in DBP and generate terrains for my project.
Progress has gone well, the program builds a flat mesh, reads a USGS .flt file, sets the height of each vertex accordingly, generates normals, and produces an object from the data.
There is a slight problem however, the root of which I believe is that I'm not constructing the mesh the "correct way"...which would be to define a bunch of vertex data then define triangle strips. The problem is that the object sometimes appears transparent. I think the cause is that each triangle is defined by its own set of verts, and even though the data for neighboring verts is identical. I'm sure that minuscule float errors during rendering cause the problem.
The question is, is there a way in DBP to construct triangle strips? Before you say use this tool, that tool, or whatever plugin remember that I'm doing this to learn...not fix my problem with another person's code.
I've included the code and a sample terrain for the hills behind my house. Use the code however you want. The EXE uses Sparky's DLL, so change you'll need to change the pertinent flag in the source if you don't have Sparky's installed. Instructions on how to d/l USGS data are also included in the source file. The code has a few bugs, irrelevant to its purpose, and doesn't care much for terrains larger than about 500 x 500 points.
remstart
USGS Float To Object
By Nateholio (or Sigh...depends on which account I remember login info for that day)
NOTES
This program takes a USGS .flt file and generates a terrain object from it.
To obtain USGS data:
1) Visit seamless.usgs.gov
2) Click on "Seamless Viewer" under the "Tools to Access Data" header on the left side of the page
3) Not req'd, but makes viewing easier: make sure the page opens up in a maximized window. If it doesn't, maximize the new window and refresh the page
4) Use the "Zoom" tool to zoom into an area of interest. You need to click-drag to zoom. Repeat as necessary.
5) Once youve found something interesting, click on the "Define Rectangular Download Area" tool. Click-drag to define the area you want to download.
It's important to keep the area small, about 1MB (you'll see the size on the screen that pops up)
6) On the window that pops up, click "Modify Data Request"
7) Select the "National Elevation Dataset (NED) 1/3 Arc Second and deselect the option directly above it
8) Change the data format from "ArcGRID" to "GridFloat" in the dropdown menu to the right of the option in step 7
9) Click "Save Changes & Return to Summary" at the bottom of the page.
10) The data size will increase about 3x, but this should be ok even if larger than 1MB
11) Click the download button, make some English Breakfast Tea, have a smoke
12) Open the zip file you downloaded and open the .hdr file and enter the ncols/nrows data into this program
13) Copy the .flt file to wherever you want it to be
14) Compile/Run the program
remend
sync on
sync rate 0
autocam off
a = make vector3(1)
a = make vector3(2)
a = make vector3(3)
`Change to 0 if you don't have Sparky's DLL installed
UseSparkys = 1
`Path of required/output files...change to your liking
Path$ = "c:\k96\model\terrain\"
Rows = 257
`The number of rows in the .flt file. This can be found in the .hdr file included in the package downloaded from the USGS
Columns = 388
`The number of colums in the .flt file. This can be found in the .hdr file included in the package downloaded from the USGS
QuadSize# = 32.808399
`The X/Z size of each quad in feet, 32.808399ft ~ 10m = USGS 1/3 arcsecond resolution
`QuadSize# = 3
Index = 12
dim HeightField(Columns, Rows) as float
make memblock 2, (Rows + 1) * (Columns + 1) * 384 + 12
`write the FVF header
write memblock dword 2, 0, 274
write memblock dword 2, 4, 32
write memblock dword 2, 8, (Rows - 1) * (Columns - 1) * 4
open to read 1, Path$ + "test.flt"
`read the heightfield into memory
`next feature is to add code which splits a flt into multiple 1mi x 1mi chunks (160 x 160 verts)
text 10, 10, "Reading heightfield into memory"
sync
for Z = 1 to Rows
for X = 1 to Columns
read float 1, HeightField(X, Z)
next X
next Z
close file 1
`Step 1 - Steal Underpants...or build a flat mesh
text 10, 10, "Building mesh"
sync
Total = Rows * Columns * 2
for SZ = 0 to Rows - 1
for SX = 0 to Columns - 1
`position the first triangle's first vertex
write memblock float 2, Index, SX * QuadSize#
write memblock float 2, Index + 4, 0.0
write memblock float 2, Index + 8, SZ * QuadSize#
`position the first triangle's second vertex
write memblock float 2, Index + 32, SX * QuadSize#
write memblock float 2, Index + 36, 0.0
write memblock float 2, Index + 40, (SZ + 1) * QuadSize#
`position the first triangle's third vertex
write memblock float 2, Index + 64, (SX + 1) * QuadSize#
write memblock float 2, Index + 68, 0.0
write memblock float 2, Index + 72, SZ * QuadSize#
`position the second triangle's first vertex
write memblock float 2, Index + 96, (SX + 1) * QuadSize#
write memblock float 2, Index + 100, 0.0
write memblock float 2, Index + 104, SZ * QuadSize#
`position the second triangle's second vertex
write memblock float 2, Index + 128, SX * QuadSize#
write memblock float 2, Index + 132, 0.0
write memblock float 2, Index + 136, (SZ + 1) * QuadSize#
`position the second triangle's third vertex
write memblock float 2, Index + 160, (SX + 1) * QuadSize#
write memblock float 2, Index + 164, 0.0
write memblock float 2, Index + 168, (SZ + 1) * QuadSize#
Index = Index + 192
next SX
next SZ
Index = 12
`Step 2 - ...or set the height of each vertex
text 10, 10, "Setting heights"
sync
for SZ = 0 to Rows - 1
for SX = 0 to Columns - 1
`set the height of the first triangle's first vertex
write memblock float 2, Index + 4, HeightField(SX, SZ) * 3
`set the height of the first triangle's second vertex
write memblock float 2, Index + 36, HeightField(SX, SZ + 1) * 3
`set the height of the first triangle's third vertex
write memblock float 2, Index + 68, HeightField(SX + 1, SZ) * 3
`set the height of the second triangle's first vertex
write memblock float 2, Index + 100, HeightField(SX + 1, SZ) * 3
`set the height of the second triangle's first vertex
write memblock float 2, Index + 132, HeightField(SX, SZ + 1) * 3
`set the height of the second triangle's first vertex
write memblock float 2, Index + 164, HeightField(SX + 1, SZ + 1) * 3
Index = Index + 192
next SX
next SZ
Index = 12
`Step 3 - Profit...or set each triangle's normals
text 10, 10, "Setting normals"
sync
for Z = 0 to Rows - 1
for X = 0 to Columns - 1
V1X# = memblock float(2, Index)
V1Y# = memblock float(2, Index + 4)
V1Z# = memblock float(2, Index + 8)
V2X# = memblock float(2, Index + 32)
V2Y# = memblock float(2, Index + 36)
V2Z# = memblock float(2, Index + 40)
V3X# = memblock float(2, Index + 64)
V3Y# = memblock float(2, Index + 68)
V3Z# = memblock float(2, Index + 72)
set vector3 1, V1X#, V1Y#, V1Z#
set vector3 2, V2X#, V2Y#, V2Z#
set vector3 3, V3X#, V3Y#, V3Z#
subtract vector3 2, 2, 1
subtract vector3 3, 3, 1
normalize vector3 2,2
normalize vector3 3,3
cross product vector3 1, 2,3
normalize vector3 1,1
write memblock float 2, Index + 12, x vector3(1)
write memblock float 2, Index + 16, y vector3(1)
write memblock float 2, Index + 20, z vector3(1)
write memblock float 2, Index + 44, x vector3(1)
write memblock float 2, Index + 48, y vector3(1)
write memblock float 2, Index + 52, z vector3(1)
write memblock float 2, Index + 76, x vector3(1)
write memblock float 2, Index + 80, y vector3(1)
write memblock float 2, Index + 84, z vector3(1)
`for second triangle
V1X# = memblock float(2, Index + 96)
V1Y# = memblock float(2, Index + 100)
V1Z# = memblock float(2, Index + 104)
V2X# = memblock float(2, Index + 128)
V2Y# = memblock float(2, Index + 132)
V2Z# = memblock float(2, Index + 136)
V3X# = memblock float(2, Index + 160)
V3Y# = memblock float(2, Index + 164)
V3Z# = memblock float(2, Index + 168)
set vector3 1, V1X#, V1Y#, V1Z#
set vector3 2, V2X#, V2Y#, V2Z#
set vector3 3, V3X#, V3Y#, V3Z#
subtract vector3 2, 2, 1
subtract vector3 3, 3, 1
normalize vector3 2,2
normalize vector3 3,3
cross product vector3 1, 2,3
normalize vector3 1,1
write memblock float 2, Index + 108, x vector3(1)
write memblock float 2, Index + 112, y vector3(1)
write memblock float 2, Index + 116, z vector3(1)
write memblock float 2, Index + 140, x vector3(1)
write memblock float 2, Index + 144, y vector3(1)
write memblock float 2, Index + 148, z vector3(1)
write memblock float 2, Index + 172, x vector3(1)
write memblock float 2, Index + 176, y vector3(1)
write memblock float 2, Index + 180, z vector3(1)
Index = Index + 192
next X
next Z
remstart
`set each triangle's UV coordinates - not important right now
for Z = 0 to Rows - 1
for X = 0 to Columns - 1
V1X# = memblock float(2, Index)
V1Y# = memblock float(2, Index + 4)
V1Z# = memblock float(2, Index + 8)
V2X# = memblock float(2, Index + 32)
V2Y# = memblock float(2, Index + 36)
V2Z# = memblock float(2, Index + 40)
V3X# = memblock float(2, Index + 64)
V3Y# = memblock float(2, Index + 68)
V3Z# = memblock float(2, Index + 72)
set vector3 1, V1X#, V1Y#, V1Z#
set vector3 2, V2X#, V2Y#, V2Z#
set vector3 3, V3X#, V3Y#, V3Z#
subtract vector3 2, 2, 1
subtract vector3 3, 3, 1
normalize vector3 2,2
normalize vector3 3,3
cross product vector3 1, 2,3
normalize vector3 1,1
write memblock float 2, Index + 12, x vector3(1)
write memblock float 2, Index + 16, y vector3(1)
write memblock float 2, Index + 20, z vector3(1)
write memblock float 2, Index + 44, x vector3(1)
write memblock float 2, Index + 48, y vector3(1)
write memblock float 2, Index + 52, z vector3(1)
write memblock float 2, Index + 76, x vector3(1)
write memblock float 2, Index + 80, y vector3(1)
write memblock float 2, Index + 84, z vector3(1)
`for second triangle
V1X# = memblock float(2, Index + 96)
V1Y# = memblock float(2, Index + 100)
V1Z# = memblock float(2, Index + 104)
V2X# = memblock float(2, Index + 128)
V2Y# = memblock float(2, Index + 132)
V2Z# = memblock float(2, Index + 136)
V3X# = memblock float(2, Index + 160)
V3Y# = memblock float(2, Index + 164)
V3Z# = memblock float(2, Index + 168)
set vector3 1, V1X#, V1Y#, V1Z#
set vector3 2, V2X#, V2Y#, V2Z#
set vector3 3, V3X#, V3Y#, V3Z#
subtract vector3 2, 2, 1
subtract vector3 3, 3, 1
normalize vector3 2,2
normalize vector3 3,3
cross product vector3 1, 2,3
normalize vector3 1,1
write memblock float 2, Index + 108, x vector3(1)
write memblock float 2, Index + 112, y vector3(1)
write memblock float 2, Index + 116, z vector3(1)
write memblock float 2, Index + 140, x vector3(1)
write memblock float 2, Index + 144, y vector3(1)
write memblock float 2, Index + 148, z vector3(1)
write memblock float 2, Index + 172, x vector3(1)
write memblock float 2, Index + 176, y vector3(1)
write memblock float 2, Index + 180, z vector3(1)
Index = Index + 192
next X
next Z
remend
`Future update...slap code right here to save terrain as .x so it can be edited later
remstart
open to write 1, Path$ + "FLT Test Terrain.x"
write string 1, "xof 0303txt 0032"
write string 1, "// DirectX - TestTerrain"
write string 1, "Frame testFrame{"
write string 1, "FrameTransformMatrix{"
write string 1, "1.000000,0.000000,0.000000,0.000000,"
write string 1, "0.000000,1.000000,0.000000,0.000000,"
write string 1, "0.000000,0.000000,1.000000,0.000000,"
write string 1, "0.000000,0.000000,0.000000,1.000000" + chr$(59) + chr$(59)
write string 1, "}"
write string 1, "Mesh testMesh{"
write string 1, str$(Rows * Columns) + chr$(59)
Index = 12
`Write the vertex data
for Z = 0 to Rows - 1
for X = 0 to Columns - 1
if X = Columns - 1 and Z = Rows - 1
write string 1, str$(memblock float(2, Index)) + chr$(59) + str$(memblock float(2, Index + 4)) + chr$(59) + str$(memblock float(2, Index + 8)) + chr$(59) + chr$(59)
else
write string 1, str$(memblock float(2, Index)) + chr$(59) + str$(memblock float(2, Index + 4)) + chr$(59) + str$(memblock float(2, Index + 8)) + chr$(59) + ","
endif
Index = Index + 192
next X
next Z
`Write the triangle data
write string 1, str$(Rows * Columns * 2) + chr$(59)
for Z = 0 to Rows - 1
for X = 0 to Columns - 1
`Write data for the first triangle
write string 1, str$(3) + chr$(59) + str$(Z * Columns + X + 1) + chr$(59) + str$((Z + 1) * Columns + X + 1) + chr$(59) + str$(Z * Columns + X + 2) + chr$(59) + ","
`Write data for the second triangle
if X = Columns - 1 and Z = Rows - 1
write string 1, str$(3) + chr$(59) + str$(Z * Columns + X + 2) + chr$(59) + str$((Z + 1) * Columns + X + 1) + chr$(59) + str$((Z + 1) * Columns + X + 2) + chr$(59) + chr$(59)
else
write string 1, str$(3) + chr$(59) + str$(Z * Columns + X + 2) + chr$(59) + str$((Z + 1) * Columns + X + 1) + chr$(59) + str$((Z + 1) * Columns + X + 2) + chr$(59) + ","
endif
next X
next Z
`Write the normal data
write string 1, "MeshNormals{"
write string 1, "1" + chr$(59)
write string 1, "0.000000" + chr$(59) + "1.000000" + chr$(59) + "0.000000" + chr$(59) + chr$(59)
write string 1, str$(Rows * Columns * 2) + chr$(59)
Index = 12
for Z = 0 to Rows - 1
for X = 0 to Columns - 1
`Write normal for the first triangle
write string 1, str$(3) + chr$(59) + str$(memblock float(2, Index + 12)) + chr$(59) + str$(memblock float(2, Index + 16)) + chr$(59) + str$(memblock float(2, Index + 20)) + chr$(59) + ","
`Write normal for the second triangle
if X = Columns - 1 and Z = Rows - 1
write string 1, str$(3) + chr$(59) + str$(memblock float(2, Index + 108)) + chr$(59) + str$(memblock float(2, Index + 112)) + chr$(59) + str$(memblock float(2, Index + 116)) + chr$(59) + chr$(59)
else
write string 1, str$(3) + chr$(59) + str$(memblock float(2, Index + 108)) + chr$(59) + str$(memblock float(2, Index + 112)) + chr$(59) + str$(memblock float(2, Index + 116)) + chr$(59) + ","
endif
Index = Index + 192
next X
next Z
write string 1, "}"
write string 1, "}"
write string 1, "}"
close file 1
remend
set camera range 0, 0.0001, 1000000
position light 0, 100000, 10000, 100000
color light 0, rgb(192, 128, 64)
make mesh from memblock 1, 2
make object 1, 1, 1
`load object Path$ + "FLT Test Terrain.x", 1
set object light 1, 1
set object cull 1, 1
position object 1, 0, 0, 0
if UseSparkys
sc_setupcomplexobject 1, 1, 2
sc_updateobject 1
endif
position camera 0, object size x(1) / 2, 80, object size z(1) / 2
do
text 0, 10, str$(screen fps())
text 0, 20, str$(statistic(1))
text 0, 30, str$(object size x(1))
text 0, 40, str$(object size y(1))
text 0, 50, str$(object size z(1))
control camera using arrowkeys 0, 10, 1
if UseSparkys
Y# = 30000 - sc_intersectobject(1, camera position x(0), 30000, camera position z(0), camera position x(0), -30000, camera position z(0))
else
Y# = 30000 - intersect object(1, camera position x(0), 30000, camera position z(0), camera position x(0), -30000, camera position z(0))
text 0, 0, "Get with the times sucka...use Sparky's Collision DLL!"
endif
position camera camera position x(0), Y# + 6, camera position z(0)
fastsync
loop

In Development: K96 - Combat Simulation