In simplified terms; GNU Octave is the major open license version of MATLAB. with a license via the GNU General Public License. As always with non-commercial versions of programs we can see a certain lack of fine-tuning in the software as well as some missing functions from the commercial, licensed, version. I will here show some key points in working with Octave in relation to modelling of 3D data and saving it in a 3D data format. This wasn’t at all straight forward when I set out to export 3D objects.
The basics – axis
First of all: when working with 3D export from Octave you need to know what kind of axis dimensions you are working with in your plot. The question is relevant in whether your 3D output actually will relate to the 3D surface/mesh that you have created. You can test this in Octave/MATLAB with this simple command:
If you, after the execution of the command above, retain a 3D figure that looks good, then you can proceed with exporting your 3D image. Otherwise you need to fix your X, Y, and Z axis so that they are represented inside a quadratic cube. I solved this issue in my 3D to 3D surface plots by automatically resizing the Z axis, depending on the values in the X and Y arrays. I was before this correction to my 3D plots only able to export a very small segment of the X-Y plane.
- Not all formats are all inclusive with structures and colours. If you want a colourised 3D object you will need a format that actually supports it in some way.
- Colour support is often supplied via JPEG or PNG images. This is defined as texture mapping in 3D modelling. The process of advanced texture mapping can be cumbersome in 3D modelling, but it is often very easy to apply a colour or colormap.
- Note that even though colour is supported in the format, it doesn’t mean that it is all saved in one file. For example; Wavefront object format supports colours and textures, but the colour/texture is saved in separate files.
Octave export scripts for 3D objects
If you don’t need colour for your 3D object, then you can export your plot more or less to any format. The easiest format is the Wavefront object file format. To do this you will only need to run the following code from your Octave terminal:
% Converting 2D matrix parameters to 1D x = (X')(:)'; y = (Y')(:)'; z = (C')(:)'/k; % Creating an output file fullfilename = 'image.obj' fid = fopen(fullfilename,'w'); % Printing the data points in the 3D mesh for i=1:size(x,2) fprintf(fid,'v %.2f %.2f %.4f\n',y(1,i),x(1,i),z(1,i)/255); end fprintf(fid,'f 1 2 3\n'); fclose(fid);
This however does not support colours, which you can see if you open up the exported object in (for example) MeshLab and try to attach a texture to it. Similar results are also attained by scripts like surf2stl.m. Why is it not possible to attach a texture? For me this is usually due to the surface basis on the exported 3D object, since I create my 3D plots via the surf()command. So essentially it is based on a surface, and not a mesh, and we need a mesh to be able to apply a texture.
You can however apply the method above generally in 3D object exports. The basics are the same, and the main challenge really is to identifying the structure of the desired file format. Our solution with the missing mesh format? Well, we need to apply a mesh based exportation. Here the credits goes to Anders Sandberg and his excellent page with multiple scripts for MATLAB output to the object file format. From there you can download the script you need for your specific purpose, but the one I use is saveobjmesh.m. The code is also available here below.
function saveobjmesh(name,x,y,z,nx,ny,nz) % SAVEOBJMESH Save a x,y,z mesh as a Wavefront/Alias Obj file % SAVEOBJMESH(fname,x,y,z,nx,ny,nz) % Saves the mesh to the file named in the string fname % x,y,z are equally sized matrices with coordinates. % nx,ny,nz are normal directions (optional) normals=1; if (nargin&amp;lt;5) normals=0; end l=size(x,1); h=size(x,2); n=zeros(l,h); fid=fopen(name,'w'); nn=1; for i=1:l for j=1:h n(i,j)=nn; fprintf(fid, 'v %f %f %f\n',x(i,j),y(i,j),z(i,j)); fprintf(fid, 'vt %f %f\n',(i-1)/(l-1),(j-1)/(h-1)); if (normals) fprintf(fid, 'vn %f %f %f\n', nx(i,j),ny(i,j),nz(i,j)); end nn=nn+1; end end fprintf(fid,'g mesh\n'); for i=1:(l-1) for j=1:(h-1) if (normals) fprintf(fid,'f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n',n(i,j),n(i,j),n(i,j),n(i+1,j),n(i+1,j),n(i+1,j),n(i+1,j+1),n(i+1,j+1),n(i+1,j+1),n(i,j+1),n(i,j+1),n(i,j+1)); else fprintf(fid,'f %d/%d %d/%d %d/%d %d/%d\n',n(i,j),n(i,j),n(i+1,j),n(i+1,j),n(i+1,j+1),n(i+1,j+1),n(i,j+1),n(i,j+1)); end end end fprintf(fid,'g\n\n'); fclose(fid);
With the function above you can export a functioning 3D object in Octave, and one that will accept colours since we now have a mesh based 3D object. The produced image is so far in grey-scale, so we still need to apply a texture in order to bring back the colours.
↑ Before and after mesh colourisation (texture mapping)
Texture mapping in MeshLab
The process of texture mapping is somewhat similar to what we do in Octave/MATLAB when we apply a colormap. In 3D modelling the process is defined by applying an JPEG or PNG image (which essentially is a colormap) as a texture to the 3D object. If you use MeshLab, you can apply a texture by:
- Loading/importing your 3D object into MeshLab.
- Go to: Filters (in top menu) → Texture → Set texture
- Supplying the correct file name to the texture map. Note: if you get an error when doing this your 3D model probably still lacks the needed mesh structure.
- Go to the top toolbar and activate ‘Texture’, via the texture button to the left of the ‘Light on/off’ button. Notice that the true colours will show when you turn off the light.
You can now export your mesh/3D model as a new mesh format, and thereby preserving your texture mapping. Note that even though colour may be included when you export your object, it doesn’t imply that all textures are included in your object file. You can include texture mapping in Wavefront object files, but the information of the texture is retained in your texture file(s).