Converting Point Clouds to Meshes for Visualization
First, save your point cloud data in the .off file format. For example:
OFF 21496 0 0 1 13 20 1 13 21 1 13 22 1 13 23 1 14 19 1 14 20
Next, utilize Meshlab to visualize the .off file and reconstruct it into a mesh. Follow these steps:
- In the toolbar, select Filter → Normals, Curvatures and Orientation → Smooth normals on a point set.
- Continue with Filter → Remeshing, Simplification and Reconstruction → Surface Reconstruction: Ball Pivoting.
- Select the yellow section in the toolbar.
- Go to Render → Enable Screen Space Ambient Occlusion, then select depthmap.gdp or another shader under Shaders.
Finally, use MATLAB to visualize the generated mesh. Create a function called mesh_loader.m:
function [vertex_coords, face_indices] = mesh_loader(obj_file_path)
% MESH_LOADER reads mesh data from an OBJ file
%
% Usage:
% [vertices, faces] = mesh_loader('model.obj')
%
% Parameters:
% obj_file_path - Path to the OBJ file
%
% Returns:
% vertex_coords - 3D coordinates of vertices
% face_indices - Indices defining faces
% Get file dimensions
[point_count, face_count, normal_count, max_vertices] = mesh_dimensions(obj_file_path);
% Extract mesh data
[vertex_coords, face_order, face_indices] = ...
mesh_data_extract(obj_file_path, point_count, face_count, normal_count, max_vertices);
% Handle polygons of different orders
for face = 1:face_count
face_indices(face_order(face)+1:max_vertices, face) = face_indices(1, face);
end
% Ensure valid indices
for face = 1:face_count
for i = 1:max_vertices
face_indices(i, face) = max(face_indices(i, face), 1);
end
end
end
function c = char_capitalize(c)
% CHAR_CAPITALIZE converts a character to uppercase
if ('a' <= c && c <= 'z')
c = c + 'A' - 'a';
end
end
function equal = char_case_compare(c1, c2)
% CHAR_CASE_COMPARE compares two characters case-insensitively
if (char_capitalize(c1) == char_capitalize(c2))
equal = 1;
else
equal = 0;
end
end
function value = char_find(s, c)
% CHAR_FIND locates first occurrence of character in string
value = 0;
for i = 1:length(s)
if (s(i:i) == c)
value = i;
return
end
end
end
function [vertex_coords, face_order, face_indices, normal_vectors, vertex_normals] = ...
mesh_data_extract(obj_file_path, point_count, face_count, normal_count, max_vertices)
% MESH_DATA_EXTRACT reads mesh information from an OBJ file
face_indices = zeros(max_vertices, face_count);
face_order = zeros(face_count, 1);
vertex_coords = zeros(3, point_count);
normal_vectors = zeros(3, normal_count);
vertex_normals = zeros(max_vertices, face_count);
file_id = fopen(obj_file_path, 'r');
if (file_id < 0)
error('Could not open file: %s', obj_file_path);
end
face = 0;
node = 0;
normal = 0;
while (1)
line_text = fgetl(file_id);
if (line_text == -1)
break
end
% Replace control characters with spaces
line_text = strrep(line_text, char(9), ' '); % Replace tabs
done = 1;
word_index = 0;
% Read first word
[word, done] = word_extract(line_text, done);
if (done)
continue
end
% Skip comments
if (word(1) == '#' || word(1) == '$')
continue
end
word_index = word_index + 1;
first_word = word;
% Process vertex data
if (strcmpi(first_word, 'V'))
node = node + 1;
for i = 1:3
[word, done] = word_extract(line_text, done);
vertex_coords(i, node) = str2double(word);
end
% Process face data
elseif (strcmpi(first_word, 'F'))
face = face + 1;
vertex = 0;
while (1)
[word, done] = word_extract(line_text, done);
if (done)
break
end
vertex = vertex + 1;
max_vertices = max(max_vertices, vertex);
% Find slash characters
slash_pos = char_find(word, '/');
if (0 < slash_pos)
second_slash_pos = char_find(word(slash_pos+1:end), '/') + slash_pos;
else
second_slash_pos = 0;
end
% Read vertex index
face_indices(vertex, face) = str2double(word);
face_order(face) = face_order(face) + 1;
% Read normal index if present
if (0 < second_slash_pos)
vertex_normals(vertex, face) = str2double(word(second_slash_pos+1:end));
end
end
% Process normal data
elseif (strcmpi(first_word, 'VN'))
normal = normal + 1;
for i = 1:3
[word, done] = word_extract(line_text, done);
normal_vectors(i, normal) = str2double(word);
end
end
end
fclose(file_id);
end
function [point_count, face_count, normal_count, max_vertices] = mesh_dimensions(obj_file_path)
% MESH_DIMENSIONS determines sizes of mesh objects in an OBJ file
face_count = 0;
point_count = 0;
normal_count = 0;
max_vertices = 0;
file_id = fopen(obj_file_path, 'r');
if (file_id < 0)
error('Could not open file: %s', obj_file_path);
end
while (1)
line_text = fgetl(file_id);
if (line_text == -1)
break
end
% Replace control characters with spaces
line_text = strrep(line_text, char(9), ' '); % Replace tabs
done = 1;
word_index = 0;
% Read first word
[word, done] = word_extract(line_text, done);
if (done)
continue
end
% Skip comments
if (word(1) == '#' || word(1) == '$')
continue
end
word_index = word_index + 1;
first_word = word;
% Process face data
if (strcmpi(first_word, 'F'))
face_count = face_count + 1;
vertex = 0;
while (1)
[word, done] = word_extract(line_text, done);
if (done)
break
end
vertex = vertex + 1;
max_vertices = max(max_vertices, vertex);
end
% Process vertex data
elseif (strcmpi(first_word, 'V'))
point_count = point_count + 1;
% Process normal data
elseif (strcmpi(first_word, 'VN'))
normal_count = normal_count + 1;
end
end
fclose(file_id);
end
function [word, done] = word_extract(s, done)
% WORD_EXTRACT reads words from a string, one at a time
persistent pos;
persistent length;
tab = char(9);
% Reset for new string
if (done)
pos = 1;
done = 0;
length = strtrim(s);
length = length(length ~= ' ');
if (isempty(length))
done = 1;
word = ' ';
return
end
end
% Find next non-space character
start_pos = pos;
while (start_pos <= length(s) && (s(start_pos) == ' ' || s(start_pos) == tab))
start_pos = start_pos + 1;
end
% Check if we've reached the end
if (start_pos > length(s))
word = ' ';
done = 1;
return
end
% Handle special characters
if (strcmp(s(start_pos), '"') || strcmp(s(start_pos), '(') || ...
strcmp(s(start_pos), ')') || strcmp(s(start_pos), '{') || ...
strcmp(s(start_pos), '}') || strcmp(s(start_pos), '[') || ...
strcmp(s(start_pos), ']'))
word = s(start_pos);
pos = start_pos + 1;
return
end
% Find end of word
end_pos = start_pos + 1;
while (end_pos <= length(s) && s(end_pos) ~= ' ' && s(end_pos) ~= tab && ...
~strcmp(s(end_pos), '"') && ~strcmp(s(end_pos), '(') && ...
~strcmp(s(end_pos), ')') && ~strcmp(s(end_pos), '{') && ...
~strcmp(s(end_pos), '}') && ~strcmp(s(end_pos), '[') && ...
~strcmp(s(end_pos), ']'))
end_pos = end_pos + 1;
end
% Extract word
word = s(start_pos:end_pos-1);
pos = end_pos;
end
Then visualize the mesh using the following MATLAB code:
[vertices, faces] = mesh_loader('chair_model.obj');
% Create mesh visualization
mesh_surface = trisurf(faces', vertices(1,:), vertices(2,:), vertices(3,:));
axis image;
shading interp;
colorbar;
colormap(jet);
axis off;
grid off;
title('3D Mesh Representation');
% Set viewing direction
view_direction = [1 1 1];
rotate(mesh_surface, view_direction, 10);
Note: You can adjust the color gradient range by editing the colormap settings.