2
0
mirror of https://github.com/dpethes/rerogue.git synced 2025-06-07 18:58:32 +02:00

terrain viewer: load directly from dat

This commit is contained in:
dpethes 2020-06-13 09:33:43 +02:00
parent 6ea0ea6a1a
commit a6a79620b4
4 changed files with 134 additions and 74 deletions

View File

@ -5,7 +5,7 @@ unit rs_world;
interface
uses
Classes, SysUtils;
Classes, SysUtils, gvector, rs_dat;
const
TEX_WIDTH = 64;
@ -37,6 +37,15 @@ type
texture_index_map: array of integer;
end;
TLevelListItem = record
name: string;
hmp: PRsDatFileNode;
texture: PRsDatFileNode;
texture_index: PRsDatFileNode;
end;
TLevelList = specialize TVector<TLevelListItem>;
{ TWorld }
TWorld = class
@ -44,8 +53,8 @@ type
world_texture: pbyte;
height_texture: pbyte;
procedure LoadTextures(const tex_fname, texidx_fname: string);
procedure LoadHeightmap(fname: string);
procedure LoadTextures(tex_node, texindex_node: PRsDatFileNode);
procedure LoadHeightmap(node: PRsDatFileNode);
public
heightmap: THeightmap;
@ -54,7 +63,7 @@ type
property TileWidth: word read heightmap.width;
property TileHeight: word read heightmap.height;
procedure LoadFromFiles(const hmp, tex, texmap: string);
procedure LoadFromNodes(level: TLevelListItem);
constructor Create;
destructor Destroy; override;
@ -135,9 +144,9 @@ end;
{ TWorld }
procedure TWorld.LoadTextures(const tex_fname, texidx_fname: string);
procedure TWorld.LoadTextures(tex_node, texindex_node: PRsDatFileNode);
var
f: file;
f: TMemoryStream;
buf: pbyte;
tex_size: integer;
i: Integer;
@ -146,12 +155,13 @@ var
palette_size: Integer;
texture_count: integer;
begin
AssignFile(f, tex_fname);
reset(f, 1);
f := TMemoryStream.Create;
f.WriteBuffer(tex_node^.Data^, tex_node^.size);
f.Seek(0, soBeginning);
palette_size := 48; //16x RGB
tex_size := TEX_WIDTH * TEX_HEIGHT div 2;
texture_count := filesize(f) div (tex_size + palette_size);
texture_count := f.Size div (tex_size + palette_size);
//writeln('texture_count: ', texture_count);
SetLength(heightmap.textures, texture_count);
@ -160,27 +170,28 @@ begin
buf := getmem(tex_size);
for i := 0 to texture_count - 1 do begin
image := getmem(TEX_WIDTH * TEX_HEIGHT * 3);
Blockread(f, buf^, tex_size);
Blockread(f, palette, palette_size);
f.Read(buf^, tex_size);
f.Read(palette, palette_size);
convert_4bit_to_24bit(buf, TEX_WIDTH, TEX_HEIGHT, image, palette);
heightmap.textures[i] := image;
end;
freemem(buf);
CloseFile(f);
f.Free;
AssignFile(f, texidx_fname);
Reset(f, 1);
f := TMemoryStream.Create;
f.WriteBuffer(texindex_node^.Data^, texindex_node^.size);
f.Seek(0, soBeginning);
texture_count := filesize(f) div 4 - 1;
texture_count := f.Size div 4 - 1; //should match previous texture_count from texture atlas?
SetLength(heightmap.texture_index_map, texture_count);
Blockread(f, heightmap.texture_index_map[0], texture_count * 4);
f.Read(heightmap.texture_index_map[0], texture_count * 4);
CloseFile(f);
f.Free;
end;
procedure TWorld.LoadHeightmap(fname: string);
procedure TWorld.LoadHeightmap(node: PRsDatFileNode);
var
f: file;
f: TMemoryStream;
buffer: array[0..15] of byte;
tile_offset: integer;
blk: pword;
@ -188,44 +199,45 @@ var
tile_count: word;
i: integer;
begin
AssignFile(f, fname);
reset(f, 1);
f := TMemoryStream.Create;
f.WriteBuffer(node^.Data^, node^.size);
f.Seek(0, soBeginning);
//header
Blockread(f, buffer, 12);
Blockread(f, buffer, 4);
Blockread(f, heightmap.y_scale, 4);
Blockread(f, buffer, 4);
Blockread(f, tile_count, 2); //tile count
Blockread(f, buffer, 2); //2B?
Blockread(f, tile_offset, 4); //tile offset
Blockread(f, buffer, 4); //offset?
Blockread(f, heightmap.width, 2);
Blockread(f, heightmap.height, 2);
f.Read(buffer, 12);
f.Read(buffer, 4);
f.Read(heightmap.y_scale, 4); //float
f.Read(buffer, 4);
tile_count := f.ReadWord;
f.Read(buffer, 2);
tile_offset := f.ReadDWord;
f.Read(buffer, 4);
heightmap.width := f.ReadWord;
heightmap.height := f.ReadWord;
//blocks / tile indices
blk_size := heightmap.width * heightmap.height * 2;
blk := getmem(blk_size);
Blockread(f, blk^, blk_size);
f.Read(blk^, blk_size);
heightmap.blk := blk;
//tiles
//writeln('filepos: ', FilePos(f)); writeln('tile pos: ', tile_offset);
Seek(f, tile_offset);
f.Seek(tile_offset, soBeginning);
heightmap.tile_count := tile_count;
heightmap.tiles := getmem(tile_count * 30);
for i := 0 to tile_count - 1 do
Blockread(f, heightmap.tiles[i], 30);
f.Read(heightmap.tiles[i], 30);
CloseFile(f);
f.Free;
end;
procedure TWorld.LoadFromFiles(const hmp, tex, texmap: string);
procedure TWorld.LoadFromNodes(level: TLevelListItem);
var
i: Integer;
begin
LoadHeightmap(hmp);
LoadTextures(tex, texmap);
LoadHeightmap(level.hmp);
LoadTextures(level.texture, level.texture_index);
for i := 0 to heightmap.tile_count - 1 do begin
heightmap.tiles[i].texture_index := heightmap.texture_index_map[heightmap.tiles[i].texture_index];
end;

View File

@ -48,7 +48,7 @@ type
procedure InitBlockStaticData;
public
destructor Destroy; override;
procedure Load(level_idx: integer);
procedure Load(level: TLevelListItem);
procedure InitGL;
procedure DrawGL(opts: TRenderOpts);
end;
@ -78,6 +78,7 @@ const
h_scale = 0.5;
var
x, y, idx: integer;
vx, vy, vz: single;
v_scale: single;
begin
result.texture_index := tile.texture_index;
@ -88,11 +89,11 @@ begin
for y := 0 to 4 do
for x := 0 to 4 do begin
idx := y * 5 + x;
result.vertices[idx].init( //x,y,z, rotated by 180 around z
(basex + x) * h_scale * -1,
tile.heights[idx] * v_scale * -1,
(basey + y) * h_scale
);
//x,y,z, rotated by 180 around z
vx := (basex + x) * h_scale * -1;
vy := tile.heights[idx] * v_scale * -1;
vz := (basey + y) * h_scale;
result.vertices[idx].init(vx, vy, vz);
end;
end;
@ -186,19 +187,10 @@ begin
inherited Destroy;
end;
procedure TTerrainMesh.Load(level_idx: integer);
const
LevelIds = '0123456789abcdefgh';
var
c: char;
procedure TTerrainMesh.Load(level: TLevelListItem);
begin
terrain := TWorld.Create;
level_idx := level_idx mod length(LevelIds);
c := LevelIds[1 + level_idx];
terrain.LoadFromFiles(
'data\hmp_' + c,
'data\lv_'+c+'.text',
'data\lv_'+c+'.tex');
terrain.LoadFromNodes(level);
TransformTiles;
InitBlockStaticData;
WriteLn(Format('terrain size: %dx%d, tris: %d',

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<Version Value="11"/>
<PathDelim Value="\"/>
<General>
<Flags>
@ -17,9 +17,6 @@
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
@ -28,36 +25,43 @@
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
<CommandLineParams Value="1"/>
</local>
<FormatVersion Value="2"/>
<Modes Count="1">
<Mode0 Name="default">
<local>
<CommandLineParams Value="1"/>
</local>
</Mode0>
</Modes>
</RunParams>
<RequiredPackages Count="1">
<Item1>
<PackageName Value="LCL"/>
</Item1>
</RequiredPackages>
<Units Count="4">
<Units Count="5">
<Unit0>
<Filename Value="terrain_viewer.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="terrain_viewer"/>
</Unit0>
<Unit1>
<Filename Value="terrain_mesh.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="terrain_mesh"/>
</Unit1>
<Unit2>
<Filename Value="rs_world.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="rs_world"/>
</Unit2>
<Unit3>
<Filename Value="vector_util.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="vector_util"/>
</Unit3>
<Unit4>
<Filename Value="..\rs_units\rs_dat.pas"/>
<IsPartOfProject Value="True"/>
</Unit4>
</Units>
</ProjectOptions>
<CompilerOptions>
@ -68,11 +72,9 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="..\rs_units"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="2">

View File

@ -22,7 +22,7 @@ program terrain_viewer;
uses
sysutils, math,
gl, glu, glext, sdl,
terrain_mesh;
terrain_mesh, rs_dat, rs_world;
const
SCR_W_fscrn = 1024;
@ -37,6 +37,9 @@ const
MouseTranslateMultiply = 0.025;
var
g_rsdata: TRSDatFile;
g_levels: TLevelList;
surface: PSDL_Surface;
done,
fullscreen: boolean;
@ -298,19 +301,68 @@ begin
end; {case}
end;
//we only care about HOB and HMT files
procedure LoadLevelFilelist;
procedure AddFile(const map, level: PRsDatFileNode);
var
item: TLevelListItem;
fnode: PRsDatFileNode;
begin
item.name := map^.Name; //lv_0
for fnode in map^.nodes do
if fnode^.name = 'hmp' then
item.hmp := fnode;
for fnode in level^.nodes do begin
if fnode^.name = item.name + '_TEX' then //lv_0_TEX
item.texture_index := fnode;
if fnode^.name = item.name + '_TEXT' then //lv_0_TEXT
item.texture := fnode;
end;
g_levels.PushBack(item);
end;
var
rs_files: TRsDatFileNodeList;
fnode: TRsDatFileNode;
data_dir, level_dir, map_dir: PRsDatFileNode;
begin
//go to data/level/
rs_files := g_rsdata.GetStructure();
for fnode in rs_files do begin
if fnode.is_directory and (fnode.Name = 'data') then begin
data_dir := @fnode;
break;
end;
end;
Assert(data_dir <> nil);
for level_dir in data_dir^.nodes do begin
if level_dir^.is_directory and (level_dir^.Name = 'level') then
break;
end;
Assert(level_dir <> nil);
for map_dir in level_dir^.nodes do
if map_dir^.is_directory then
AddFile(map_dir, level_dir);
end;
//******************************************************************************
var
sec, frames: integer;
in_file: integer;
begin
if Paramcount < 1 then begin
writeln('specify HMP file index');
if not (FileExists(RS_DATA_HDR) and FileExists(RS_DATA_DAT)) then begin
writeln('RS data files not found!');
exit;
end;
in_file := StrToInt( ParamStr(1) );
writeln('loading data');
g_rsdata := TRSDatFile.Create(RS_DATA_HDR, RS_DATA_DAT);
g_rsdata.Parse();
g_levels := TLevelList.Create;
LoadLevelFilelist;
terrain := TTerrainMesh.Create;
terrain.Load(14);
terrain.Load(g_levels[0]);
writeln('Init SDL...');
SDL_Init( SDL_INIT_VIDEO );
@ -343,5 +395,7 @@ begin
terrain.Free;
SDL_Quit;
g_levels.Free;
g_rsdata.Free;
end.