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

model viewer: keep list of objects and their parts, render per-part vertices

This commit is contained in:
dpethes 2020-07-28 12:02:52 +02:00
parent 0dfa3b5e08
commit aa723776ba
2 changed files with 94 additions and 54 deletions

View File

@ -35,8 +35,8 @@ type
TMaterialArray = array of TMaterial; TMaterialArray = array of TMaterial;
TRenderOpts = record TRenderOpts = record
fg_to_draw: integer; part_to_draw: integer;
fg_all: boolean; show_all_parts: boolean;
obj_to_draw: integer; obj_to_draw: integer;
wireframe: boolean; wireframe: boolean;
points: boolean; points: boolean;
@ -48,6 +48,17 @@ type
export_png_textures: boolean; export_png_textures: boolean;
end; end;
TObjectPart = record
vertices: TVertexList;
triangles: TTriangleList;
end;
TObjectPartList = specialize TVector<TObjectPart>;
TRenderObject = record
parts: TObjectPartList;
end;
TRenderObjectList = specialize TVector<TRenderObject>;
{ TModel { TModel
single HOB mesh single HOB mesh
} }
@ -57,13 +68,16 @@ type
_vertices: TVertexList; _vertices: TVertexList;
_triangles: TTriangleListListList; _triangles: TTriangleListListList;
_materials: TMaterialArray; _materials: TMaterialArray;
_objects: TRenderObjectList;
_hmt: THmtFile; _hmt: THmtFile;
_hmt_loaded: boolean; _hmt_loaded: boolean;
procedure HmtRead(stream: TMemoryStream); procedure HmtRead(stream: TMemoryStream);
procedure HobRead(stream: TMemoryStream); procedure HobRead(stream: TMemoryStream);
procedure HobReadMesh(const mesh: THobObject); procedure HobTransform(const hobject: THobObject);
procedure SaveMaterials(const mtl_name: string; const png_textures: boolean); procedure SaveMaterials(const mtl_name: string; const png_textures: boolean);
public public
constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure Load(hob, hmt: TMemoryStream); procedure Load(hob, hmt: TMemoryStream);
procedure InitGL; procedure InitGL;
@ -92,17 +106,16 @@ end;
{ rearrange HOB data, triangulate quads { rearrange HOB data, triangulate quads
} }
procedure TModel.HobReadMesh(const mesh: THobObject); procedure TModel.HobTransform(const hobject: THobObject);
var var
i: Integer; i: Integer;
fg: THobFaceGroup; fg: THobFaceGroup;
v: TVertex; v: TVertex;
group_vertices: TVertexList; current_block_vertices: TVertexList;
triangle: TTriangle; triangle: TTriangle;
fg_idx: integer; fg_idx: integer;
tris: TTriangleList; tris: TTriangleList;
mesh_tris: TTriangleListList; mesh_tris: TTriangleListList;
last_idx: integer;
function InitVertex(face: THobFace; offset: integer): TTriangle; function InitVertex(face: THobFace; offset: integer): TTriangle;
var var
@ -110,7 +123,7 @@ var
begin begin
for i := 0 to 2 do begin for i := 0 to 2 do begin
k := (i + offset) and $3; k := (i + offset) and $3;
result.vertices[i] := group_vertices[face.indices[k]]; result.vertices[i] := current_block_vertices[face.indices[k]];
result.colors[i] := face.vertex_colors[k]; result.colors[i] := face.vertex_colors[k];
result.tex_coords[i, 0] := FixUvRange(face.tex_coords[k].u); result.tex_coords[i, 0] := FixUvRange(face.tex_coords[k].u);
result.tex_coords[i, 1] := FixUvRange(face.tex_coords[k].v); result.tex_coords[i, 1] := FixUvRange(face.tex_coords[k].v);
@ -118,12 +131,21 @@ var
result.material_index := face.material_index; result.material_index := face.material_index;
end; end;
var
robject: TRenderObject;
robjpart: TObjectPart;
begin begin
group_vertices := TVertexList.Create; current_block_vertices := TVertexList.Create; //todo just offset to vertex list
mesh_tris := TTriangleListList.Create; mesh_tris := TTriangleListList.Create;
fg_idx := 0; fg_idx := 0;
last_idx:=0; robject.parts := TObjectPartList.Create;
for fg in mesh.face_groups do begin
for fg in hobject.object_parts do begin
current_block_vertices.Clear;
robjpart.triangles := TTriangleList.Create;
robjpart.vertices := TVertexList.Create;
for i := 0 to fg.vertex_count - 1 do begin for i := 0 to fg.vertex_count - 1 do begin
v.x := FixRange(fg.vertices[i].x); v.x := FixRange(fg.vertices[i].x);
v.y := FixRange(fg.vertices[i].y); v.y := FixRange(fg.vertices[i].y);
@ -140,25 +162,30 @@ begin
v.y := -v.y; v.y := -v.y;
v.x := -v.x; v.x := -v.x;
_vertices.PushBack(v); // TODO(?): _vertices per object (not all) robjpart.vertices.PushBack(v);
group_vertices.PushBack(v); current_block_vertices.PushBack(v);
end; end;
tris := TTriangleList.Create; tris := TTriangleList.Create;
for i := 0 to fg.face_count - 1 do begin for i := 0 to fg.face_count - 1 do begin
triangle := InitVertex(fg.faces[i], 0); triangle := InitVertex(fg.faces[i], 0);
tris.PushBack(triangle); tris.PushBack(triangle);
robjpart.triangles.PushBack(triangle);
if fg.faces[i].ftype <> 3 then begin if fg.faces[i].ftype <> 3 then begin
triangle := InitVertex(fg.faces[i], 2); triangle := InitVertex(fg.faces[i], 2);
tris.PushBack(triangle); tris.PushBack(triangle);
robjpart.triangles.PushBack(triangle);
end; end;
end; end;
mesh_tris.PushBack(tris); mesh_tris.PushBack(tris);
fg_idx += 1; fg_idx += 1;
group_vertices.Clear;
last_idx:=fg.fg_group_id; robject.parts.PushBack(robjpart);
end; end;
group_vertices.Free; current_block_vertices.Free;
_triangles.PushBack(mesh_tris); _triangles.PushBack(mesh_tris);
_objects.PushBack(robject);
end; end;
@ -168,11 +195,13 @@ var
hob: THobFile; hob: THobFile;
begin begin
hob := ParseHobFile(stream); hob := ParseHobFile(stream);
_objects.Clear;
if hob.obj_count = 0 then exit; if hob.obj_count = 0 then exit;
for i := 0 to hob.obj_count-1 do for i := 0 to hob.obj_count-1 do
HobReadMesh(hob.objects[i]); HobTransform(hob.objects[i]);
WriteLn('vertices: ', _vertices.Size);
//WriteLn('vertices: ', _vertices.Size);
//WriteLn('faces (triangulated): ', _triangles.Count); //WriteLn('faces (triangulated): ', _triangles.Count);
end; end;
@ -218,6 +247,11 @@ begin
end; end;
constructor TModel.Create;
begin
_objects := TRenderObjectList.Create;
end;
destructor TModel.Destroy; destructor TModel.Destroy;
var var
t: TTriangleListList; t: TTriangleListList;
@ -234,6 +268,7 @@ begin
DeallocHmt(_hmt); DeallocHmt(_hmt);
_vertices.Free; _vertices.Free;
_materials := nil; _materials := nil;
_objects.Free;
end; end;
procedure TModel.Load(hob, hmt: TMemoryStream); procedure TModel.Load(hob, hmt: TMemoryStream);
@ -314,10 +349,6 @@ end;
procedure TModel.DrawGL(var opts: TRenderOpts); procedure TModel.DrawGL(var opts: TRenderOpts);
var
vert: TVertex;
i, j, k: integer;
triangle_count: integer = 0;
procedure DrawTri(tri: TTriangle); procedure DrawTri(tri: TTriangle);
var var
@ -341,44 +372,53 @@ var
glVertex3fv(@tri.vertices[k]); glVertex3fv(@tri.vertices[k]);
end; end;
glEnd; glEnd;
triangle_count += 1;
end; end;
var
vert: TVertex;
triangle_count: integer = 0;
robject: TRenderObject;
part: TObjectPart;
part_idx, i: integer;
begin begin
if _triangles.Size = 0 then if _triangles.Size = 0 then
exit; exit;
if opts.wireframe then
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //clip selected object/part
opts.obj_to_draw := min(integer(opts.obj_to_draw), integer(_objects.Size - 1));
robject := _objects[opts.obj_to_draw];
opts.part_to_draw := min(integer(opts.part_to_draw), integer(robject.parts.Size - 1));
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
if opts.points then begin if opts.points then begin
glBegin( GL_POINTS ); glBegin( GL_POINTS );
glColor3f(0, 1, 0); glColor3f(0, 1, 0);
for i := 0 to _vertices.Size - 1 do begin for part in robject.parts do begin
vert := _vertices[i]; if part.vertices.Size = 0 then
glVertex3fv(@vert); continue;
for i := 0 to part.vertices.Size - 1 do begin
vert := part.vertices[i];
glVertex3fv(@vert);
end;
end; end;
glEnd; glEnd;
end; end;
if opts.wireframe then
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3f(1, 1, 1); glColor3f(1, 1, 1);
j := min(integer(opts.obj_to_draw), integer(_triangles.Size - 1)); for part_idx := 0 to robject.parts.Size - 1 do begin
opts.obj_to_draw := j; // clip if (not opts.show_all_parts) and (part_idx <> opts.part_to_draw) then
if _triangles[j].Size = 0 then continue;
exit; part := robject.parts[part_idx];
if opts.fg_all then begin if part.triangles.Size = 0 then
for k := 0 to _triangles[j].Size - 1 do continue;
if _triangles[j][k].Size > 0 then for i := 0 to part.triangles.Size - 1 do begin
for i := 0 to _triangles[j][k].Size - 1 do DrawTri(part.triangles[i]);
DrawTri(_triangles[j][k][i]); triangle_count += 1;
end end;
else begin
k := min(integer(opts.fg_to_draw), integer(_triangles[j].Size - 1));
opts.fg_to_draw := k; //clip
if _triangles[j][k].Size > 0 then
for i := 0 to _triangles[j][k].Size - 1 do
DrawTri(_triangles[j][k][i]);
end; end;
if opts.wireframe then if opts.wireframe then
@ -387,10 +427,10 @@ begin
ImGui.Begin_('Mesh'); ImGui.Begin_('Mesh');
ImGui.Text('triangles: %d (vertices: %d)', [triangle_count, _vertices.Size]); ImGui.Text('triangles: %d (vertices: %d)', [triangle_count, _vertices.Size]);
ImGui.Text('object: %d / %d', [opts.obj_to_draw + 1, _triangles.Size]); ImGui.Text('object: %d / %d', [opts.obj_to_draw + 1, _triangles.Size]);
if opts.fg_all then if opts.show_all_parts then
ImGui.Text('facegroups: %d', [_triangles[opts.obj_to_draw].Size]) ImGui.Text('parts: %d', [_triangles[opts.obj_to_draw].Size])
else else
ImGui.Text('facegroup: %d / %d', [opts.fg_to_draw + 1, _triangles[opts.obj_to_draw].Size]); ImGui.Text('facegroup: %d / %d', [opts.part_to_draw + 1, _triangles[opts.obj_to_draw].Size]);
ImGui.End_; ImGui.End_;
end; end;

View File

@ -234,8 +234,8 @@ begin
view.y := 0; view.y := 0;
view.autorotate := true; view.autorotate := true;
view.render.fg_all := true; view.render.show_all_parts := true;
view.render.fg_to_draw := 0; view.render.part_to_draw := 0;
view.render.obj_to_draw := 0; view.render.obj_to_draw := 0;
view.render.wireframe := false; view.render.wireframe := false;
view.render.points := false; view.render.points := false;
@ -270,7 +270,7 @@ begin
except except
g_model_loading_failed := true; g_model_loading_failed := true;
end; end;
view.render.fg_to_draw := 0; view.render.part_to_draw := 0;
end; end;
@ -338,11 +338,11 @@ begin
//model selection //model selection
SDLK_f: SDLK_f:
view.render.fg_all := not view.render.fg_all; view.render.show_all_parts := not view.render.show_all_parts;
SDLK_LEFT: SDLK_LEFT:
view.render.fg_to_draw := max(0, view.render.fg_to_draw - 1); view.render.part_to_draw := max(0, view.render.part_to_draw - 1);
SDLK_RIGHT: SDLK_RIGHT:
view.render.fg_to_draw += 1; view.render.part_to_draw += 1;
SDLK_END: SDLK_END:
view.render.obj_to_draw += 1; view.render.obj_to_draw += 1;
SDLK_HOME: SDLK_HOME:
@ -351,14 +351,14 @@ begin
SDLK_UP: SDLK_UP:
if (g_selected_file_idx > 0) then begin if (g_selected_file_idx > 0) then begin
g_selected_file_idx -= 1; g_selected_file_idx -= 1;
view.render.fg_to_draw := 0; view.render.part_to_draw := 0;
view.render.obj_to_draw := 0; view.render.obj_to_draw := 0;
LoadMesh(g_filelist[g_selected_file_idx]); LoadMesh(g_filelist[g_selected_file_idx]);
end; end;
SDLK_DOWN: SDLK_DOWN:
if (g_selected_file_idx < g_filelist.Size - 1) then begin if (g_selected_file_idx < g_filelist.Size - 1) then begin
g_selected_file_idx += 1; g_selected_file_idx += 1;
view.render.fg_to_draw := 0; view.render.part_to_draw := 0;
view.render.obj_to_draw := 0; view.render.obj_to_draw := 0;
LoadMesh(g_filelist[g_selected_file_idx]); LoadMesh(g_filelist[g_selected_file_idx]);
end; end;