function obj_display ( input_file_name )
%*****************************************************************************80
%
%% OBJ_DISPLAY displays the faces of a shape defined by an OBJ file.
%
% Usage:
%
% obj_display ( 'file.obj' )
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 27 September 2008
%
% Author:
%
% John Burkardt
%
timestamp ( );
fprintf ( 1, '\n' );
fprintf ( 1, 'OBJ_DISPLAY\n' );
fprintf ( 1, ' MATLAB version\n' );
fprintf ( 1, '\n' );
fprintf ( 1, ' Reads an object in an ASCII OBJ file.\n' );
fprintf ( 1, ' Display it as a MATLAB shape.\n' );
%
% If at least one command line argument, it's the input file name.
%
if ( nargin < 1 )
fprintf ( 1, '\n' );
fprintf ( 1, 'OBJ_DISPLAY:\n' );
input_file_name = input ( 'Enter the name of the input file:' );
end
%
% Get sizes.
%
[ node_num, face_num, normal_num, order_max ] = obj_size ( input_file_name );
%
% Print the sizes.
%
obj_size_print ( input_file_name, node_num, face_num, normal_num, order_max );
%
% Get the data.
%
[ node_xyz, face_order, face_node ] = ...
obj_read ( input_file_name, node_num, face_num, normal_num, order_max );
%
% FACE_NODE may contain polygons of different orders.
% To make the call to PATCH, we will assume all the polygons are the same order.
% To do so, we'll simply "stutter" the first node in each face list.
%
for face = 1 : face_num
face_node(face_order(face)+1:order_max,face) = face_node(1,face);
end
%
% If any node index is still less than 1, set the whole face to 1's.
% We're giving up on this presumably meaningless face, but we need to
% do it in a way that keeps MATLAB happy!
%
for face = 1 : face_num
for i = 1 : order_max
face_node(i,face) = max ( face_node(i,face), 1 );
end
end
%
% Display the shape.
%
handle = patch ( 'Vertices', node_xyz', 'Faces', face_node' );
set ( handle, 'FaceColor', [0.5, 0.6, 0.8], 'EdgeColor', 'Black' );
axis equal;
grid on;
xlabel ( '--X axis--' )
ylabel ( '--Y axis--' )
zlabel ( '--Z axis--' )
%
% The TITLE function will interpret underscores in the title.
% We need to unescape such escape sequences!
%
title_string = s_escape_tex ( input_file_name );
title ( title_string )
%
% Terminate.
%
fprintf ( 1, '\n' );
fprintf ( 1, 'OBJ_DISPLAY:\n' );
fprintf ( 1, ' Normal end of execution.\n' );
fprintf ( 1, '\n' );
timestamp ( );
return
end
function c = ch_cap ( c )
%*****************************************************************************80
%
%% CH_CAP capitalizes a single character.
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 22 November 2003
%
% Author:
%
% John Burkardt
%
% Parameters:
%
% Input, character C, the character to capitalize.
%
% Output, character C, the capitalized character.
%
if ( 'a' <= c && c <= 'z' )
c = c + 'A' - 'a';
end
return
end
function truefalse = ch_eqi ( c1, c2 )
%*****************************************************************************80
%
%% CH_EQI is a case insensitive comparison of two characters for equality.
%
% Example:
%
% CH_EQI ( 'A', 'a' ) is TRUE.
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 28 July 2000
%
% Author:
%
% John Burkardt
%
% Parameters:
%
% Input, character C1, C2, the characters to compare.
%
% Output, logical TRUEFALSE, is TRUE (1) if the characters are equal.
%
FALSE = 0;
TRUE = 1;
if ( ch_cap ( c1 ) == ch_cap ( c2 ) )
truefalse = TRUE;
else
truefalse = FALSE;
end
return
end
function value = ch_index ( s, c )
%*****************************************************************************80
%
%% CH_INDEX is the first occurrence of a character in a string.
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 01 May 2004
%
% Author:
%
% John Burkardt
%
% Parameters:
%
% Input, string S, the string to be searched.
%
% Input, character C, the character to be searched for.
%
% Output, integer VALUE, the location of the first occurrence of C
% in the string, or 0 if C does not occur.
%
value = 0;
for i = 1 : length ( s )
if ( s(i:i) == c )
value = i;
return
end
end
return
end
function value = ch_is_control ( ch )
%*****************************************************************************80
%
%% CH_IS_CONTROL is TRUE if a character is a control character.
%
% Discussion:
%
% A "control character" has ASCII code <= 31 or 127 <= ASCII code.
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 27 September 2008
%
% Author:
%
% John Burkardt
%
% Parameters:
%
% Input, character CH, the character to be tested.
%
% Output, integer CH_IS_CONTROL, TRUE if the character is a control
% character, and FALSE otherwise.
%
if ( ch <= 31 || 127 <= ch )
value = 1;
else
value = 0;
end
return
end
function truefalse = ch_is_digit ( c )
%*****************************************************************************80
%
% CH_IS_DIGIT returns TRUE if the character C is a digit.
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 11 December 2003
%
% Author:
%
% John Burkardt
%
% Parameters:
%
% Input, character C, a character.
%
% Output, integer TRUEFALSE, is TRUE (1) if C is a digit, FALSE (0) otherwise.
%
TRUE = 1;
FALSE = 0;
if ( '0' <= c && c <= '9' )
truefalse = TRUE;
else
truefalse = FALSE;
end
return
end
function digit = ch_to_digit ( c )
%*****************************************************************************80
%
%% CH_TO_DIGIT returns the integer value of a base 10 digit.
%
% Example:
%
% C DIGIT
% --- -----
% '0' 0
% '1' 1
% ... ...
% '9' 9
% ' ' 0
% 'X' -1
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 22 November 2003
%
% Author:
%
% John Burkardt
%
% Parameters:
%
% Input, character C, the decimal digit, '0' through '9' or blank
% are legal.
%
% Output, integer DIGIT, the corresponding integer value. If C was
% 'illegal', then DIGIT is -1.
%
if ( '0' <= c && c <= '9' )
digit = c - '0';
elseif ( c == ' ' )
digit = 0;
else
digit = -1;
end
return
end
function [ node_xyz, face_order, face_node, normal_vector, vertex_normal ] = ...
obj_read ( input_file_name, node_num, face_num, normal_num, order_max )
%*****************************************************************************80
%
%% OBJ_READ reads graphics information from a Wavefront OBJ file.
%
% Discussion:
%
% It is intended that the information read from the file can
% either start a whole new graphics object, or simply be added
% to a current graphics object via the '<<' command.
%
% This is controlled by whether the input values have been zeroed
% out or not. This routine simply tacks on the information it
% finds to the current graphics object.
%
% Example:
%
% # magnolia.obj
%
% v -3.269770 -39.572201 0.876128
% v -3.263720 -39.507999 2.160890
% ...
% v 0.000000 -9.988540 0.000000
% vn 1.0 0.0 0.0
% ...
% vn 0.0 1.0 0.0
%
% f 8 9 11 10
% f 12 13 15 14
% ...
% f 788 806 774
%
% Licensing:
%
% This code is distributed under the GNU LGPL license.
%
% Modified:
%
% 27 September 2008
%
% Author:
%
% John Burkardt
%
% Parameters:
%
%