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

terrain viewer: update to 64bit, SDL2, imgui

This commit is contained in:
dpethes 2020-06-13 11:54:46 +02:00
parent a6a79620b4
commit 909cfe5a97
3 changed files with 163 additions and 76 deletions

View File

@ -316,6 +316,8 @@ begin
else else
glDrawElements(GL_TRIANGLES, b.blocks * FacesPerBlock * 3, GL_UNSIGNED_INT, b.face_indices); glDrawElements(GL_TRIANGLES, b.blocks * FacesPerBlock * 3, GL_UNSIGNED_INT, b.face_indices);
end; end;
if opts.wireframe then
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
end; end;
end. end.

View File

@ -41,7 +41,7 @@
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item1> </Item1>
</RequiredPackages> </RequiredPackages>
<Units Count="5"> <Units Count="8">
<Unit0> <Unit0>
<Filename Value="terrain_viewer.pas"/> <Filename Value="terrain_viewer.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -62,6 +62,19 @@
<Filename Value="..\rs_units\rs_dat.pas"/> <Filename Value="..\rs_units\rs_dat.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
</Unit4> </Unit4>
<Unit5>
<Filename Value="imgui\fpimgui.pas"/>
<IsPartOfProject Value="True"/>
</Unit5>
<Unit6>
<Filename Value="imgui\fpimgui_impl_sdlgl2.pas"/>
<IsPartOfProject Value="True"/>
</Unit6>
<Unit7>
<Filename Value="sdl2\sdl2.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="SDL2"/>
</Unit7>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>
@ -72,7 +85,7 @@
</Target> </Target>
<SearchPaths> <SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/> <IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="..\rs_units"/> <OtherUnitFiles Value="..\rs_units;imgui;sdl2"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths> </SearchPaths>
</CompilerOptions> </CompilerOptions>

View File

@ -21,15 +21,12 @@ program terrain_viewer;
uses uses
sysutils, math, sysutils, math,
gl, glu, glext, sdl, gl, glu, glext, gvector, sdl2, fpimgui, fpimgui_impl_sdlgl2,
terrain_mesh, rs_dat, rs_world; terrain_mesh, rs_dat, rs_world;
const const
SCR_W_fscrn = 1024;
SCR_H_fscrn = 768;
SCR_W_INIT = 1280; SCR_W_INIT = 1280;
SCR_H_INIT = 720; SCR_H_INIT = 720;
SCREEN_BPP = 0;
RotationAngleIncrement = 1; RotationAngleIncrement = 1;
ZoomIncrement = 0.3; ZoomIncrement = 0.3;
MouseZoomDistanceMultiply = 0.15; MouseZoomDistanceMultiply = 0.15;
@ -37,12 +34,13 @@ const
MouseTranslateMultiply = 0.025; MouseTranslateMultiply = 0.025;
var var
g_window: PSDL_Window;
g_ogl_context: TSDL_GLContext;
g_rsdata: TRSDatFile; g_rsdata: TRSDatFile;
g_levels: TLevelList; g_levels: TLevelList;
g_selected_level_idx: integer = 0;
surface: PSDL_Surface;
done,
fullscreen: boolean;
terrain: TTerrainMesh; terrain: TTerrainMesh;
view: record view: record
@ -51,7 +49,7 @@ var
pitch: single; pitch: single;
x, y: single; x, y: single;
autorotate: boolean; autorotate: boolean;
opts: TRenderOpts; render: TRenderOpts;
end; end;
mouse: record mouse: record
@ -62,7 +60,7 @@ var
end; end;
procedure ReportError(s: string); procedure AppError(s: string);
begin begin
writeln(s); writeln(s);
halt; halt;
@ -104,7 +102,7 @@ end;
// function to reset our viewport after a window resize // function to reset our viewport after a window resize
procedure ResizeWindow( width, height : integer ); procedure SetGLWindowSize( width, height : integer );
begin begin
if ( height = 0 ) then if ( height = 0 ) then
height := 1; // Protect against a divide by zero height := 1; // Protect against a divide by zero
@ -118,11 +116,36 @@ begin
glLoadIdentity; // Reset The View glLoadIdentity; // Reset The View
end; end;
procedure DrawGui;
var
item: TLevelListItem;
i: Integer;
begin
Imgui.Begin_('Rendering options');
Imgui.Checkbox('points', @view.render.points);
Imgui.Checkbox('wireframe', @view.render.wireframe);
Imgui.End_;
Imgui.Begin_('Level list');
for i := 0 to g_levels.Size - 1 do begin
item := g_levels[i];
//some levels are broken atm
if i in [7, 9, 15] then
continue;
if Imgui.Selectable(item.name, g_selected_level_idx = i) then begin
g_selected_level_idx := i;
terrain.Free;
terrain := TTerrainMesh.Create;
terrain.Load(g_levels[i]);
terrain.InitGL;
end;
end;
Imgui.End_;
end;
// The main drawing function. // The main drawing function.
procedure DrawGLScene; procedure DrawTerrain;
begin begin
glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity; glLoadIdentity;
@ -138,24 +161,73 @@ begin
if view.rotation_angle > 360 then if view.rotation_angle > 360 then
view.rotation_angle -= 360; view.rotation_angle -= 360;
terrain.DrawGL(view.opts); terrain.DrawGL(view.render);
end;
SDL_GL_SwapBuffers; procedure BeginScene;
var
style: PImGuiStyle;
begin
ImGui_ImplSdlGL2_NewFrame(g_window);
style := Imgui.GetStyle();
style^.WindowRounding := 0;
glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );
end;
procedure EndScene;
begin
glDisable(GL_LIGHTING);
igRender;
glEnable(GL_LIGHTING);
SDL_GL_SwapWindow(g_window);
end; end;
procedure SetMode(w, h: word; fullscreen: boolean = false); procedure WindowInit(w_width, w_height: integer);
var var
flags: UInt32; ver: TSDL_Version;
x, y: integer;
flags: longword;
io: PImGuiIO;
begin begin
if fullscreen then SDL_GetVersion(@ver);
flags := SDL_OPENGL or SDL_FULLSCREEN writeln(format('SDL %d.%d.%d', [ver.major, ver.minor, ver.patch]));
else
flags := SDL_OPENGL or SDL_RESIZABLE; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
surface := SDL_SetVideoMode( w, h, SCREEN_BPP, flags); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
if surface = nil then SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
ReportError('SDL_SetVideoMode failed'); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_WM_SetCaption('HOB viewer', nil); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
WriteLn('init window: ', w_width, 'x', w_height);
x := SDL_WINDOWPOS_CENTERED;
y := SDL_WINDOWPOS_CENTERED;
flags := SDL_WINDOW_SHOWN or SDL_WINDOW_OPENGL or SDL_WINDOW_RESIZABLE;
g_window := SDL_CreateWindow('RS terrain viewer', x, y, w_width, w_height, flags);
if g_window = nil then
AppError ('SDL_CreateWindow failed. Reason: ' + SDL_GetError());
g_ogl_context := SDL_GL_CreateContext(g_window);
if g_ogl_context = nil then begin
writeln ('SDL_GL_CreateContext failed. Reason: ' + SDL_GetError());
halt;
end;
SDL_GL_SetSwapInterval(1); //enable VSync
//setup imgui
io := igGetIO();
io^.DisplaySize.x := w_width;
io^.DisplaySize.y := w_height;
ImGui_ImplSdlGL2_Init();
end;
procedure WindowFree;
begin
ImGui_ImplSdlGL2_Shutdown();
SDL_GL_DeleteContext(g_ogl_context);
SDL_DestroyWindow(g_window);
end; end;
@ -189,51 +261,46 @@ end;
procedure InitView; procedure InitView;
begin begin
view.rotation_angle := 0; view.rotation_angle := 0;
view.distance := 6; view.distance := 160;
view.pitch := 0; view.pitch := 36;
view.x := 0; view.x := 0;
view.y := 0; view.y := 10;
view.autorotate := false; view.autorotate := false;
view.opts.wireframe := false; view.render.wireframe := false;
view.opts.points := false; view.render.points := false;
view.opts.vcolors := true; view.render.vcolors := true;
view.opts.textures := true; view.render.textures := true;
end; end;
procedure HandleEvent; procedure HandleEvent(const event: TSDL_Event; var done: boolean);
var var
event: TSDL_Event; io: PImGuiIO;
begin begin
SDL_PollEvent( @event ); ImGui_ImplSdlGL2_ProcessEvent(@event);
io := igGetIO();
if ((event.type_ = SDL_MOUSEBUTTONDOWN) or
(event.type_ = SDL_MOUSEBUTTONUP) or
(event.type_ = SDL_MOUSEWHEEL) or
(event.type_ = SDL_MOUSEMOTION)) and io^.WantCaptureMouse then
exit;
if ((event.type_ = SDL_KEYDOWN) or (event.type_ = SDL_KEYUP)) and io^.WantCaptureKeyboard then
exit;
case event.type_ of case event.type_ of
SDL_QUITEV: SDL_QUITEV:
Done := true; Done := true;
SDL_WINDOWEVENT: begin
SDL_VIDEORESIZE: if event.window.event = SDL_WINDOWEVENT_RESIZED then
begin SetGLWindowSize(event.window.data1, event.window.data2);
SetMode (event.resize.w, event.resize.h); end;
ResizeWindow( surface^.w, surface^.h );
end;
SDL_KEYDOWN: SDL_KEYDOWN:
case event.key.keysym.sym of case event.key.keysym.sym of
SDLK_ESCAPE: SDLK_ESCAPE:
Done := true; Done := true;
SDLK_F1: begin
if not fullscreen then begin
SetMode(SCR_W_fscrn, SCR_H_fscrn, true);
fullscreen := true;
end else begin
SetMode(SCR_W_INIT, SCR_H_INIT, false);
fullscreen := false;
end;
InitGL;
terrain.InitGL;
ResizeWindow( surface^.w, surface^.h );
end;
SDLK_s: SDLK_s:
WindowScreenshot( surface^.w, surface^.h ); WindowScreenshot(g_window^.w, g_window^.h);
SDLK_PAGEUP: SDLK_PAGEUP:
view.distance += ZoomIncrement; view.distance += ZoomIncrement;
SDLK_PAGEDOWN: SDLK_PAGEDOWN:
@ -243,17 +310,17 @@ begin
//terrain rendering opts //terrain rendering opts
SDLK_w: SDLK_w:
view.opts.wireframe := not view.opts.wireframe; view.render.wireframe := not view.render.wireframe;
SDLK_v: SDLK_v:
view.opts.vcolors := not view.opts.vcolors; view.render.vcolors := not view.render.vcolors;
SDLK_p: SDLK_p:
view.opts.points := not view.opts.points; view.render.points := not view.render.points;
SDLK_t: SDLK_t:
view.opts.textures := not view.opts.textures; view.render.textures := not view.render.textures;
SDLK_LEFT: SDLK_LEFT:
view.opts.fg_to_draw := max(0, view.opts.fg_to_draw - 1); view.render.fg_to_draw := max(0, view.render.fg_to_draw - 1);
SDLK_RIGHT: SDLK_RIGHT:
view.opts.fg_to_draw += 1; view.render.fg_to_draw += 1;
end; end;
SDL_MOUSEBUTTONDOWN: begin SDL_MOUSEBUTTONDOWN: begin
@ -265,15 +332,17 @@ begin
mouse.last_y := event.button.y; mouse.last_y := event.button.y;
view.autorotate := false; view.autorotate := false;
end; end;
if event.button.button = 5 then
view.distance += view.distance * MouseZoomDistanceMultiply;
if event.button.button = 4 then
view.distance -= view.distance * MouseZoomDistanceMultiply;
end; end;
SDL_MOUSEBUTTONUP: begin SDL_MOUSEBUTTONUP: begin
mouse.drag := false; mouse.drag := false;
view.autorotate := mouse.resume_autorotate_on_release; view.autorotate := mouse.resume_autorotate_on_release;
end; end;
SDL_MOUSEWHEEL: begin
if event.wheel.y < 0 then
view.distance += view.distance * MouseZoomDistanceMultiply;
if event.wheel.y > 0 then
view.distance -= view.distance * MouseZoomDistanceMultiply;
end;
SDL_MOUSEMOTION: begin SDL_MOUSEMOTION: begin
if mouse.drag then begin if mouse.drag then begin
@ -348,6 +417,8 @@ end;
//****************************************************************************** //******************************************************************************
var var
sec, frames: integer; sec, frames: integer;
event: TSDL_Event;
done: boolean;
begin begin
if not (FileExists(RS_DATA_HDR) and FileExists(RS_DATA_DAT)) then begin if not (FileExists(RS_DATA_HDR) and FileExists(RS_DATA_DAT)) then begin
@ -362,16 +433,14 @@ begin
LoadLevelFilelist; LoadLevelFilelist;
terrain := TTerrainMesh.Create; terrain := TTerrainMesh.Create;
terrain.Load(g_levels[0]); terrain.Load(g_levels[g_selected_level_idx]);
writeln('Init SDL...'); writeln('Init SDL...');
SDL_Init( SDL_INIT_VIDEO ); SDL_Init(SDL_INIT_VIDEO or SDL_INIT_TIMER);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); WindowInit(SCR_W_INIT, SCR_H_INIT);
SetMode(SCR_W_INIT, SCR_H_INIT);
writeln('Init OpenGL...'); writeln('Init OpenGL...');
InitGL; InitGL;
ResizeWindow( surface^.w, surface^.h ); SetGLWindowSize(g_window^.w, g_window^.h);
InitView; InitView;
terrain.InitGL; terrain.InitGL;
@ -380,15 +449,18 @@ begin
frames := 0; frames := 0;
Done := False; Done := False;
while not Done do begin while not Done do begin
HandleEvent; BeginScene;
DrawGLScene; DrawTerrain;
DrawGui;
EndScene;
while SDL_PollEvent(@event) > 0 do
HandleEvent(event, done);
frames += 1; frames += 1;
if (SDL_GetTicks - sec) >= 1000 then begin if (SDL_GetTicks - sec) >= 1000 then begin
write(frames:3, ' dist: ', view.distance:5:1, ' rot: ', view.rotation_angle:5:1, #13); write(frames:3, ' dist: ', view.distance:5:1, ' rot: ', view.rotation_angle:5:1, #13);
frames := 0; frames := 0;
sec := SDL_GetTicks; sec := SDL_GetTicks;
//WindowScreenshot( surface^.w, surface^.h );
end; end;
SDL_Delay(10); SDL_Delay(10);
end; end;