Point Cloud to Mesh Conversion and Visualization Techniques

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:

  1. In the toolbar, select Filter → Normals, Curvatures and Orientation → Smooth normals on a point set.
  2. Continue with Filter → Remeshing, Simplification and Reconstruction → Surface Reconstruction: Ball Pivoting.
  3. Select the yellow section in the toolbar.
  4. 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.

Tags: point cloud mesh conversion visualization meshlab MATLAB

Posted on Tue, 06 Oct 2026 16:17:18 +0000 by Maiku