Posts Tagged ‘3d’

Paper-worthy rendering in MATLAB

Thursday, July 20th, 2017

MATLAB is not a great tool for creating 3D renderings. However, the learning curves for most commercial rendering tools are quite steep. Other tools like Mitsuba can create beautiful pictures, but can feel quite cumbersome for rendering pure geometry rather than the physical scenes their designed for.

Over the years, I’ve developed a way of creating plots of 3D shapes in MATLAB using a few extra functions in gptoolbox. This started as a way to just make images from research prototypes more palatable, but eventually became the usual way that I render images for papers. If the code for my research is already written in MATLAB then one huge advantage is that every image in my paper can have a *.m script that deterministically generates the result and the corresponding image with user intervention. This helps with reproducibility, editing and sharing between collaborators.

Here’s a “VFX Breakdown” of rendering a 3D shape in MATLAB.

t = tsurf(F,V);
set(gcf,'COlor',0.94*[1 1 1]);
teal = [144 216 196]/255;
pink = [254 194 194]/255;
bg_color = pink;
fg_color = teal;
for pass = 1:10
  switch pass
  case 1
    % blank run
    axis([-209.4       119.38      -181.24       262.67      -247.28 247.38]);
  case 2
    axis equal;
    axis([-209.4       119.38      -181.24       262.67      -247.28 247.38]);
    axis vis3d;
  case 3
    t.EdgeColor = 'none';
  case 4
    set(t,fphong,'FaceVertexCData',repmat(fg_color,size(V,1),1));
  case 5
    set(t,fsoft);
  case 6
    l = light('Position',[0.2 -0.2 1]);
  case 7
    set(gca,'Visible','off');
  case 8
    set(gcf,'Color',bg_color);
  case 9
    s = add_shadow(t,l,'Color',bg_color*0.8,'BackgroundColor',bg_color,'Fade','infinite');
  case 10
    apply_ambient_occlusion(t,'AddLights',false,'SoftLighting',false);
  end

  vidObj = VideoWriter(sprintf('nefertiti-%02d.mp4',pass),'MPEG-4');
  vidObj.Quality = 100;
  vidObj.open;
  thetas = linspace(30,-30,450);
  for theta = thetas(1:end-1)
    view(theta,30);
    drawnow;
    vidObj.writeVideo(getframe(gcf));
  end
  vidObj.close;

end

Skinning Subdivision Surfaces

Monday, March 16th, 2015

bounding bunny

Songrun and Yotam have wrapped up the little 3D demo of our Siggraph Asia 2014 paper Skinning Cubic B├ęzier Splines and Catmull-Clark Subdivision Surfaces. Build the demo from source on github.

Stable triangle normals

Wednesday, February 11th, 2015

Here’s one way to compute a triangle’s normal using floating point arithmetic that is stable with respect to the order the triangle’s vertices are given in. To demonstrate the issue, consider:

% Vertex positions
A = [1/8 1 1/6];
B = [1/3 1/5 1/7];
C = [1/4 1/9 1/2];
% normals via cross product of different edge vectors
NB = cross(A-B,C-B);
NC = cross(B-C,A-C);
NA = cross(C-A,B-A);
NA-NB
NB-NC

producing

ans =
            0            0  -2.7756e-17
ans =
   5.5511e-17   1.3878e-17            0

Computing the normals three different ways, I get three different floating point errors. The right thing to do I guess is analyze the vertex positions and design a normal computation that minimizes floating point error (the solution hopefully being stable via uniqueness). I took a lazier route and take a careful average of the three solutions. The might also have the effect of cutting down floating point error a bit. But at least it’s stable.

Unfortunately it’s not enough to naively sum N1, N2, and N3 entry-wise and divide by 3. The summation could incur roundoff error depending on the order of the three arguments. So first we must sort the arguments. If going to the trouble of sorting we might as well sort in a way that reduces roundoff error: descending order of absolute value. The matlab syntax for this is a little clunky:

NABC = [NA(:) NB(:) NC(:)];
[~,I] = sort([NABC],2,'descend');
sNABC = reshape( ...
  NABC(sub2ind(size(NABC),repmat(1:size(NABC,1),size(NABC,2),1)',I)),size(NABC));
N = 1/3*reshape(sum(sNABC,2),shape);

Extruding a Bezier curve into a triangle mesh in maya

Friday, October 17th, 2014

Today I struggled to convince Maya to let me extrude a Bezier Curve into a solid shape (sweep a closed curve and finish with planar end caps). I could used the Surface > Extrude tool to extrude the curve and then select the boundary edges and use the Surface > Planar tool to close the endcaps, but this just creates a group of 3 surfaces which are not topologically connected.

My end goal today was to create something to send to the 3D printer. So in this case I eventually wanted a triangle mesh. Here’re the steps I took to convert a bezier curve to a polygonal mesh:

  1. draw bezier curves
    maya bezier curve to polygon mesh
  2. find the Polygons > Plane tool
    maya bezier curve to polygon mesh
  3. draw a plane behind the curves
    maya bezier curve to polygon mesh
  4. Select one of the curves and the plane
    maya bezier curve to polygon mesh
  5. Choose Edit Mesh > Project curve onto mesh
    maya bezier curve to polygon mesh
  6. Select the new projected curve and the plane
    maya bezier curve to polygon mesh
  7. Choose Edit Mesh > Split Mesh with projected curve
    maya bezier curve to polygon mesh
  8. Right click and hold and drag to select “Face” selection mode
    maya bezier curve to polygon mesh
  9. Mouse over the plane until just the filled curve appears (there seem to be many overlapping faces.
    maya bezier curve to polygon mesh
  10. Choose Edit > Invert Selection
    maya bezier curve to polygon mesh
  11. Then choose Edit > Delete
    maya bezier curve to polygon mesh
  12. Select just the original Bezier curve and delete it.
    maya bezier curve to polygon mesh
  13. Repeat steps 2-12 for the other curves (why can’t we do all curves at once?)
    maya bezier curve to polygon mesh
  14. Select both filled curves and choose the Polygons > Extrude tool
    maya bezier curve to polygon mesh
  15. Pull down on the widget’s arrow to extrude.
    maya bezier curve to polygon mesh
  16. Select both extruded surfaces and choose Mesh > Cleanup...
    maya bezier curve to polygon mesh
  17. Make sure 4-sided faces is unchecked
    maya bezier curve to polygon mesh
  18. Make sure Faces with zero geometry area is checked with very small Area tolerance (e.g. 0.00001)
    maya bezier curve to polygon mesh
  19. Hit Cleanup
    maya bezier curve to polygon mesh
  20. The choose Mesh > Triangulate
    maya bezier curve to polygon mesh
  21. The surface is now triangulated. Select everything.
    maya bezier curve to polygon mesh
  22. File > Export Selection and save as an obj
    maya bezier curve to polygon mesh

Wow. So 21 steps. Not particularly easy for a task I thought would be dead simple. I must be missing some faster way to do this.

Bounded biharmonic weights c++ demo for surfaces/volumes in 3d

Monday, December 24th, 2012

By popular demand I’ve created a quick-and-dirty 3d C++ demo of our paper “Bounded Biharmonic Weights for Real-time Deformation” [Jacobson et al. 2011].

The demo takes a mesh (.obj or .off) and a description of a skeleton (in my own ridiculous .bf and .tgf file formats) and computes a tetrahedral volume mesh using tetgen (saved to a .mesh file) and then computed bounded biharmonic weights for each handle over this mesh (save to my not-so-ridiculous .dmat file format).

This is a small program that illustrates how to compute Bounded Biharmonic Weights (BBW) for a given surface mesh and skeleton description. This only supports point handles and skeleton trees (bones). Cages are not supported. This program only computes and outputs the weight function values. You should be able to load them into matlab or maya or whatever.

COMPILE

First install the dependencies (e.g. mosek). If your on a mac, and why wouldn’t you be, then you *should* with any luck and by the grace of God be able to compile with:


make

RUN

Then run an example with (e.g.):


./bbw_demo examples/brick.obj examples/brick.tgf

This will produce at least 2 files:


  examples/brick-volume.mesh  Tetrahedral mesh over which weights were computed
  examples/brick-volume.dmat  Coefficients of weights defined over .mesh

File Formats

See file-formats/index.html

The dependencies are:

  igl_lib
    eigen3
    tetgen
    mosek

Igl lib

IGL_lib is our groups internal library. It will someday be publicly available, but not yet. Thus I only include here a bare minimum to get this demo to work. The library functions as an inlined header library. All the source is located in ./igl_lib/include/igl

Eigen3: The igl dependencies rely on a depracted version of the Sparse Matrix suite in eigen 3. Thus you need the correct version of eigen. To make this easier I have included the necessary version of eigen here: ./eigen3

Mosek: Mosek is free for academics and has its own installation instructions. Adjust your makefile accordingly.

Tetgen Tetgen is also free and easy to install. Be sure to compile the library version, i.e.:


make tetlib

To make life a little easier I include a working version of tetgen in ./igl_lib/external/tetgen/. You can go there and compile libtet.a or download the tetgen source and do that on your own. Whatever.

You can try to contact me with questions. Especially regarding the algorithm described in “Bounded biharmonic weights for real-time deformation” by [Jacobson et al. 2011]. However, please
please
please
please
please
please
please
please
please
please
please
please
please
please
please
please
please
please
try to solve compilation troubles on your own. I didn’t intend for this code to be machine independent or even necessarily easy to compile. This is a quick and dirty demo because so many people requested it.

Sometime in the not too distant future I still plan to release a *nice* 3d, C++ demo.

Update: I have updated this demo to use the libigl library. Please find the new version on the bbw project page.

calistatics

Wednesday, October 5th, 2011

calistatics

http://alecjacobson.com/art/digital/
http://alecjacobson.com/art/

Hide bounding box and axes in MATLAB 3D plots

Monday, December 13th, 2010

Took me a while to track this down.
matlab remove 3d bounding box

To get rid of the bounding box and axes that matlab puts under your 3D plot use:


set(gca, 'visible', 'off'); 

MATLAB display certain vertex indices

Friday, July 9th, 2010

When I’m prototyping with meshes in MATLAB it is often useful to plot the meshes in 3D.
Then I might want to examine individual vertices. So say I have defined vertices V and faces F:


[x,y]=meshgrid(1:10,1:10);
z = peaks(size(x,1));
V = [x(:),y(:),z(:)];
F = delaunay(x,y);

I can plot these normally with:


trisurf(F, V(:,1),V(:,2),V(:,3))


matlab plot 3d mesh without vertex labels

I can create an array to hold the vertex indices, then plot the labels at corresponding points in 3d:


indices = 1:size(V,1);
text(V(:,1),V(:,2),V(:,3),num2str(indices'))


matlab plot 3d mesh with vertex labels

And sometimes it helps to plot the labels in bold:


text(V(:,1),V(:,2),V(:,3),num2str(indices'),'FontWeight','Bold')


matlab plot 3d mesh with vertex labels in bold

Other times it is nice to push the labels off the vertex positions. Here I move them to the right a little:


text(V(:,1),V(:,2),V(:,3),[repmat(' ',size(indices',1),1) num2str(indices')],'FontWeight','Bold')


matlab plot 3d mesh with vertex labels in bold and indented