Creating Animated 3D Objects with MATLAB

Ever since the introduction of electronic devices with touch controls, interactive 3D graphics objects have become increasingly popular in multimedia electronic books (ebooks). The Lidar Toolbox and the Computer Vision Toolbox from MathWorks provide the necessary tools for creating and exporting 3D graphics objects for inclusion in documents such as multimedia ebooks, interactive websites, and presentations (MathWorks 2025a, b).

I have been working on this for a while, after important features for macOS were no longer available, which were previously provided in Simulink 3D Animation and which I presented in earlier editions of my books. The problem was that the 3D model had to be equipped not only with vertices and edges, but also with faces that were colored in the DEMCMAP color map. Thanks to the excellent MathWorks support from Oliver Jährig and Sebastian Gross, we finally managed to do it.

The Polygon File Format (PLY) files are text or binary files with the file extension .ply. Suche a file contains vertices, edges, and faces for 3D polygons. The PLY files can be viewed using a browser plugin (many different types of which are available online) or using 3D software, such as the open-source MeshLab software

https://www.meshlab.net

or the free Blender software available at

https:///www.blender.org

These tools (as well as others) can be used to convert the PLY format into other 3D graphics object file formats, such as the Universal 3D (U3D), the Virtual Reality Modeling Language (VRML), the Collada digital asset exchange (DAE) or Filmbox (FBX) formats. As an example, the U3D format is the format required to place a 3D graphics object onto a PDF page with Adobe Acrobat.

The digital terrain models such as the one in file s01_e036_1arc_v3.tif are great examples of such interactive 3D objects. We use the script readgeoraster to read the GeoTIFF file using

[SRTM,R] = readgeoraster('s01_e036_1arc_v3.tif',...
    'OutputType','double');

which is a generic tool for reading geospatial raster data files. The output arguments are the digital elevation data SRTM and the spatial reference object R. The SRTM dataset actually has a resolution of 1/3600 degrees, but we first reduce it to 1/360 degrees so that our computers can handle a smooth 3D display. We define a coordinate grid LON and LAT to match SRTM using

SRTM = SRTM(1:10:end,1:10:end)/5000;
[LON,LAT] = meshgrid(36:1/360:37,-1:1/360:0);

3D graphics can be generated from the elevation data using the function

vertices = [LON(:),LAT(:),SRTM(:)];
faces = delaunay(LON,LAT);
mesh = surfaceMesh(vertices,faces);

We now set the demcmap as the colormap for our digital terrain model, that is, we replace the standard color map parula with a colormap that is commonly used for displaying digital terrain models. To ensure that our colormap matches the data, we scale it to the range between the extreme values of SRTM using

zLimits = [min(SRTM(:)),max(SRTM(:))];
demcmap(zLimits)

Then we determine the number of faces and colors using

numFaces = size(faces,1);
cmap = colormap;
numColors = size(cmap,1);

We then assign colors to the faces of the 3D model using

faceColors = zeros(numFaces,3);
for i = 1:numFaces
   vertexIndices = faces(i,:);
   avgZ = mean(SRTM(vertexIndices));
   colorIndex = round((avgZ-zLimits(1))/ ...
      (zLimits(2)-zLimits(1))*(numColors-1))+1;
   colorIndex = min(max(colorIndex,1),numColors);
   faceColors(i,:) = cmap(colorIndex,:);
end

We then convert the faceColors to vertexColors using

numVertices = size(vertices,1);
vertexColors = zeros(numVertices,3);
vertexCounts = zeros(numVertices,1);

We then assign colors to the vertices of the 3D model using

for i = 1:numFaces
   face = faces(i,:);
   color = faceColors(i,:);
   for j = 1:3
     vIdx = face(j);
     vertexColors(vIdx,:) = vertexColors(vIdx,:)+...
        color;
     vertexCounts(vIdx) = vertexCounts(vIdx)+1;
   end
end

We replace zeros by ones in order to avoid division by zero before we devide vertexColors by vertexCounts using

vertexCounts(vertexCounts==0) = 1;
vertexColors = vertexColors./vertexCounts;

Then we assign vertexColors and facesColors to the attributes of the mesh object using

mesh.VertexColors = vertexColors;
mesh.FaceColors = faceColors;

and display the result using surfaceMeshShow:

surfaceMeshShow(mesh)

We can the use writeSurfaceMesh to save the 3D model to a file in a range of formats, for example as a PLY or FBX file using

writeSurfaceMesh(mesh,'srtm_1.ply')
writeSurfaceMesh(mesh,'srtm_2.fbx')

Instead of a mesh of vertices, edges, and faces with colors, we can also display the vertices as a point cloud. Before we do that, we remove the vertices with no data using

xyzPoints = xyzPoints(~isnan(xyzPoints(:,3)),:);

Again, we defined the colors of the vertices using

colorIndices = round(rescale(SRTM(:),1,...
    size(cmap,1)));
colors = cmap(colorIndices,:);

With the function pointCloud, we can create a point cloud ptCloud from xyzPoints with the colors colors:

ptCloud = pointCloud(xyzPoints,...
   'color',colors);

We can display the resulting point cloud with colors using

pcshow(ptCloud)

We can the use pcwrite to save the 3D model to a PLY file using

pcwrite(ptCloud,'srtm_3.ply',...
   'Encoding','binary')

Importing the resulting PLY file into a PLY client such as MeshLab or Blender reveals that the terrain model does indeed has colors, as defined by demcmap. We can use the file in the PLY format to create an interactive document.

Downloads

Download all files to perform the experiment.

References

MathWorks (2025a) Computer Vision Toolbox – User’s Guide. The MathWorks, Natick, MA

MathWorks (2025b) Lidar Toolbox – User’s Guide. The MathWorks, Natick, MA

Trauth, M.H. (2025) MATLAB Recipes for Earth Sciences – Sixth Edition. Springer International Publishing, 567 p, https://doi.org/10.1007/978-3-031-57949-3