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:
parent
0dfa3b5e08
commit
aa723776ba
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user