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:
parent
6ea0ea6a1a
commit
a6a79620b4
@ -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;
|
||||||
|
@ -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',
|
||||||
|
@ -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">
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user