## Posts Tagged ‘trisurf’

### Plot a bunch of edges in matlab with per-edge color data

Monday, December 19th, 2016

Suppose you have a list of vertices V (#V by dim) and a list of edges E (#E by 2) indexing V, then one hacky to draw all of these edges with per-vertex color data DV (#V by 1) is to use trisurf:

trisurf(E(:,[1 1 2]),V(:,1),V(:,2),V(:,3),'CData',DV,'EdgeColor','interp');


However, if you try to use this trick to draw per-edge color data DE (#E by 1), you’ll find that 'EdgeColor','flat' does not work. Instead you can explode you compact “mesh” of edges into individual edges and repeat you edge color data for each edge point:

trisurf(reshape([1:size(E,1),1:size(E,1)*2],[],3),V(E(:),1),V(E(:),2),V(E(:),3),'CData',repmat(DE,2,1),'EdgeColor','interp');


### Two-sided material in matlab

Monday, March 23rd, 2015

Unfortunately there seems to be no builtin support for two-sided surfaces in matlab. There’s some rudimentary control over back-face lighting, but that’s all. At least you can determine the back-facing triangles for a given camera position:

N = normals(V,F);
BC = barycenter(V,F);
back_facing = sum(N.*bsxfun(@minus,BC,campos),2)<=0;


Here’s an example for an armadillo mesh:

t = tsurf(F,V,'EdgeColor','none','FaceLighting','phong');view(2);
axis equal;
camproj('persp')
t.FaceVertexCData = 1*(sum(N.*bsxfun(@minus,BC,campos),2)<=0)
apply_ambient_occlusion();


Of course, if you change the view, the coloring is no longer valid:

So you need to recompute the coloring:

You can also insert nans to achieve back-face culling:

t.FaceVertexCData(sum(N.*bsxfun(@minus,BC,campos),2)>0) = nan;


### Use NaNs to hide faces in matlab trisurf/patch renderings

Wednesday, February 11th, 2015

I recently (re)discovered that if you set the ‘CData’ value of a face to nan the face will be hidden. This can sometimes be useful if you want to use the wireframe of a model to give context but focus on just a few faces. Here’s an example:

% selected faces
I = sparse(125,1,1,size(F,1),1);
while true
% Set all but selected to nan
tsurf(F,V,'CData',sparse(find(~I),1,nan,size(F,1),1));
view(-48,4); set(gca,'Visible','off');apply_ambient_occlusion();
drawnow;
if nnz(I)==size(F,1);
break;
end
I = A*I;
end


### MATLAB2014b features anti-aliasing

Monday, October 13th, 2014

Finally. I’m pretty happy about the results:

[V,F] = load_mesh('/usr/local/igl/libigl/examples/shared/cheburashka.off');
AO = ambient_occlusion(V,F,V,per_vertex_normals(V,F),1000);
t = tsurf(F,V,fphong,'EdgeColor','none');
C = squeeze(ind2rgb(floor(matrixnormalize(t.FaceVertexCData)*size(colormap,1))+1,colormap));
t.FaceVertexCData = bsxfun(@times,C,1-AO);
t.SpecularStrength = 0.1;
t.DiffuseStrength = 0.1;
t.AmbientStrength = 0.8;
l = light('Position',[1 1 100],'Style','infinite');
l2 = light('Position',[1 -100 1],'Style','infinite');
set(gca,'XTickLabel',[],'YTickLabel',[],'ZTickLabel',[],'Color',[0.94 0.94 0.94]);
set(gcf,'Color','w');


And to spin the camera around:

axis equal
axis vis3d;
camproj('persp');
for f = 1:numel(T)
t = T(f);
view(-cos(t*2*pi)*45,sin(t*2*pi)*45+45);
drawnow;
frame = getframe(gcf);
[SIf,cm] = rgb2ind(frame.cdata,256);
if f == 1
imwrite(SIf,cm,filename,'Loop',Inf,'Delay',0);
else
imwrite(SIf,cm, filename,'WriteMode','append','Delay',0);
end
end


With the awesome but now obsolete myaa.m hacked anti-aliasing, creating this gif would have taken many minutes. This runs in real time.

### Animated GIF of vector field coordinates in matlab

Monday, August 26th, 2013

Suppose you have a mesh (V,F) and a vector field (or matrix of scalar field values) W. You can create a looping animated gif in matlab of a visualization of those values using:

t = trisurf(F,V(:,1),V(:,2),0*V(:,1),'EdgeColor','none','FaceColor','interp','FaceLighting','phong');
hold on;
% for me each coordinate corresponds to a point in C
scatter(C(:,1),C(:,2),'ok','MarkerFaceColor','y','LineWidth',3,'SizeData',100);
hold off;
axis equal;
view(2);
title('Vector Field  ','FontSize',20);
for w = 1:size(W,2)
set(t,'CData',W(:,w));
drawnow;
im = myaa('raw');
[imind,cm] = rgb2ind(im,256);
filename = 'vector-field.gif';
if w == 1;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end


This produces something like:

Source

### Using patcht to texture map a triangle mesh in matlab

Friday, August 9th, 2013

Recently I found the patcht script which lets you texture map a triangle mesh in matlab. It unfortunately does it in a brute force way: creating a textured surface for every triangle. But it’s at least something. Here’s how I use it for 2d meshes of images using the xy positions as texture coordinates:

im = imread('woody.png');
patcht(F,V,F,[max(V(:,2))-V(:,2) V(:,1)],im);
axis equal


which produces:

We thank Scott Schaefer for providing the wooden gingerbread man image from “Image Deformation Using Moving Least Squares”.

### Matlab’s trisurf confuses face colors with vertex colors

Sunday, July 28th, 2013

I recently had trouble getting matlab’s trisurf to display interpolated colors inside each face. I was calling:


set(trisurf(F,V(:,1),V(:,2),V(:,3)),'FaceColor','interp');


But the display looked like flat shading.

The problem turned out to be that I had 9 faces and 9 vertices. In this rare instance matlab decides that the vertex colors (which actually are just the Z coordinates in V(:,3)) should be attached (incorrectly) to the faces and are not interpolatable.

I hacked a fix to this by appending an extra ghost vertex:


set(trisurf(F,[V(:,1);0],[V(:,2);0],[V(:,3);0]),'FaceColor','interp');