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

View File

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

View File

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

View File

@ -22,7 +22,7 @@ program terrain_viewer;
uses uses
sysutils, math, sysutils, math,
gl, glu, glext, sdl, gl, glu, glext, sdl,
terrain_mesh; terrain_mesh, rs_dat, rs_world;
const const
SCR_W_fscrn = 1024; SCR_W_fscrn = 1024;
@ -37,6 +37,9 @@ const
MouseTranslateMultiply = 0.025; MouseTranslateMultiply = 0.025;
var var
g_rsdata: TRSDatFile;
g_levels: TLevelList;
surface: PSDL_Surface; surface: PSDL_Surface;
done, done,
fullscreen: boolean; fullscreen: boolean;
@ -298,19 +301,68 @@ begin
end; {case} end; {case}
end; 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 var
sec, frames: integer; sec, frames: integer;
in_file: integer;
begin begin
if Paramcount < 1 then begin if not (FileExists(RS_DATA_HDR) and FileExists(RS_DATA_DAT)) then begin
writeln('specify HMP file index'); writeln('RS data files not found!');
exit; exit;
end; 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 := TTerrainMesh.Create;
terrain.Load(14); terrain.Load(g_levels[0]);
writeln('Init SDL...'); writeln('Init SDL...');
SDL_Init( SDL_INIT_VIDEO ); SDL_Init( SDL_INIT_VIDEO );
@ -343,5 +395,7 @@ begin
terrain.Free; terrain.Free;
SDL_Quit; SDL_Quit;
g_levels.Free;
g_rsdata.Free;
end. end.