使用 MATLAB 制作文本动画 [英] Text Animation with MATLAB
问题描述
我的简化问题是在 3D 绘图上为一些文本设置动画.
我有一个立方体,
vert = [1 1 0;0 1 0;0 1 1;1 1 1;0 0 1;1 0 1;1 0 0;0 0 0];fac = [1 2 3 4;4 3 5 6;6 7 8 5;1 2 8 7;6 7 1 4;2 3 5 8];patch('Faces',fac,'Vertices',vert,'FaceColor',[.8 .5 .2]);轴([0, 1, 0, 1, 0, 1]);轴相等轴关闭
有没有可能得到这样的东西?
使用 text
没有帮助(看起来是假的!),
谢谢,
这个想法是使用纹理映射作为 管理转换的函数,这比)
My simplified problem is to animate some text on a 3D plot.
I have a cube,
vert = [1 1 0;0 1 0;0 1 1;1 1 1;0 0 1;1 0 1;1 0 0;0 0 0];
fac = [1 2 3 4; 4 3 5 6; 6 7 8 5; 1 2 8 7; 6 7 1 4; 2 3 5 8];
patch('Faces',fac,'Vertices',vert,'FaceColor',[.8 .5 .2]);
axis([0, 1, 0, 1, 0, 1]);
axis equal
axis off
Is it possible to get something like this?
Using text
doesn't help (it looks fake!),
Thanks,
The idea is to use texture mapping as @Hoki showed. I tried to implement this on my end, here is what I came up with.
First we'll need 6 images to apply on the cube faces. These can be any random images of any size. For example:
% just a bunch of demo images from IPT toolbox
function imgs = get_images()
imgs = {
imread('autumn.tif');
imread('coloredChips.png');
imread('toysflash.png');
imread('football.jpg');
imread('pears.png');
imread('peppers.png');
};
end
Better yet, let's use an online service that returns placeholder images containing digits 1 to 6:
% online API for placeholder images
function imgs = get_images()
imgs = cell(6,1);
clr = round(255*brighten(lines(6),0.75));
for i=1:6
%bg = randsample(['0':'9' 'a':'f'], 6, true);
%fg = randsample(['0':'9' 'a':'f'], 6, true);
bg = strjoin(cellstr(dec2hex(clr(i,:))).', '');
fg = strjoin(cellstr(dec2hex(clr(7-i,:))).', '');
[img,map] = imread(sprintf(...
'http://placehold.it/100x100/%s/%s&text=%d', bg, fg, i));
imgs{i} = im2uint8(ind2rgb(img,map));
end
end
Here are the resulting images:
>> imgs = get_images();
>> montage(cat(4,imgs{:}))
Next let's create a function that renders a unit cube with images texture-mapped as faces:
function h = get_unit_cube(imgs)
% we need a cell array of 6 images, one for each face (they can be any size)
assert(iscell(imgs) && numel(imgs)==6);
% coordinates for unit cube
[D1,D2,D3] = meshgrid([-0.5 0.5], [-0.5 0.5], 0.5);
% texture mapped surfaces
opts = {'FaceColor','texturemap', 'EdgeColor','none'};
h = zeros(6,1);
h(6) = surface(D1, flipud(D2), D3, imgs{6}, opts{:}); % Z = +0.5 (top)
h(5) = surface(D1, D2, -D3, imgs{5}, opts{:}); % Z = -0.5 (bottom)
h(4) = surface(fliplr(D1), D3, flipud(D2), imgs{4}, opts{:}); % Y = +0.5 (right)
h(3) = surface(D1, -D3, flipud(D2), imgs{3}, opts{:}); % Y = -0.5 (left)
h(2) = surface(D3, D1, flipud(D2), imgs{2}, opts{:}); % X = +0.5 (front)
h(1) = surface(-D3, fliplr(D1), flipud(D2), imgs{1}, opts{:}); % X = -0.5 (back)
end
Here is what it looks like:
imgs = get_images();
h = get_unit_cube(imgs);
view(3), axis vis3d, rotate3d on
Now we can have some fun with this creating interesting animations. Consider the following:
% create two separate unit cubes
figure('Renderer','OpenGL')
h1 = get_unit_cube(get_images());
h2 = get_unit_cube(get_images());
set([h1;h2], 'FaceAlpha',0.8) % semi-transparent
view(3), axis vis3d off, rotate3d on
% create transformation objects, used as parents of cubes
t1 = hgtransform('Parent',gca);
t2 = hgtransform('Parent',gca);
set(h1, 'Parent',t1)
set(h2, 'Parent',t2)
% transform the second cube (scaled, rotated, then shifted)
M = makehgtform('translate', [-0.7 1.2 0.5]) * ...
makehgtform('yrotate', 15*(pi/180)) * ...
makehgtform('scale', 0.5);
set(t2, 'Matrix',M)
drawnow
axis on, axis([-2 2 -2 2 -0.7 1]), box on
xlabel x, ylabel y, zlabel z
% create animation by rotating cubes 5 times
% (1st rotated around z-axis, 2nd around its own z-axis in opposite
% direction as well as orbiting the 1st)
for r = linspace(0,10*pi,90)
R = makehgtform('zrotate', r);
set(t1, 'Matrix',R)
set(t2, 'Matrix',R(M/R))
pause(0.1)
end
I'm using the hgtransform
function to manage transformations, this is much more efficient than continuously changing the x/y/z data points of the graphics objects.
BTW I've used slightly different images in the animation above.
EDIT:
Let's replace the rotating cubes with images of planet earth mapped onto spheres. First here are two functions to render the spheres (I'm borrowing code from these examples in the MATLAB documentation):
get_earth_sphere1.m
function h = get_earth_sphere1()
% read images of planet earth
earth = imread('landOcean.jpg');
clouds = imread('cloudCombined.jpg');
% unit sphere with 35x35 faces
[X,Y,Z] = sphere(35);
Z = flipud(Z);
a = 1.02;
% render first sphere with earth mapped onto the surface,
% then a second transparent surface with clouds layer
if verLessThan('matlab','8.4.0')
h = zeros(2,1);
else
h = gobjects(2,1);
end
h(1) = surface(X, Y, Z, earth, ...
'FaceColor','texturemap', 'EdgeColor','none');
h(2) = surface(X*a, Y*a, Z*a, clouds, ...
'FaceColor','texturemap', 'EdgeColor','none', ...
'FaceAlpha','texturemap', 'AlphaData',max(clouds,[],3));
end
get_earth_sphere2.m
function h = get_earth_sphere2()
% load topographic data
S = load('topo.mat');
C = S.topo;
cmap = S.topomap1;
n = size(cmap,1);
% convert altitude data and colormap to RGB image
C = (C - min(C(:))) ./ range(C(:)); % scale to [0,1]
C = ind2rgb(round(C*(n-1)+1), cmap); % convert indexed to RGB
% unit sphere with 50x50 faces
[X,Y,Z] = sphere(50);
% render sphere with earth mapped onto the surface
h = surface(X, Y, Z, C, ...
'FaceColor','texturemap', 'EdgeColor','none');
end
The animation script is similar to before (with minor changes), so I'm not gonna repeat it. Here is the result:
(This time I'm using the new graphics system in R2014b)
这篇关于使用 MATLAB 制作文本动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!