Ras*_*hid 10 3d matlab animation text image
我的简化问题是在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]);
axis([0, 1, 0, 1, 0, 1]);
axis equal
axis off
Run Code Online (Sandbox Code Playgroud)
有可能得到这样的东西吗?
使用text
没有帮助(看起来很假!),
谢谢,
Amr*_*mro 19
想法是使用纹理映射,如@Hoki所示.我试图在我的最终实现这一点,这是我想出来的.
首先,我们需要在立方体面上应用6个图像.这些可以是任何大小的任何随机图像.例如:
% 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
Run Code Online (Sandbox Code Playgroud)
更好的是,让我们使用返回包含数字1到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
Run Code Online (Sandbox Code Playgroud)
以下是生成的图像:
>> imgs = get_images();
>> montage(cat(4,imgs{:}))
Run Code Online (Sandbox Code Playgroud)
接下来让我们创建一个函数,使用纹理映射为面的图像渲染单位立方体:
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
Run Code Online (Sandbox Code Playgroud)
这是它的样子:
imgs = get_images();
h = get_unit_cube(imgs);
view(3), axis vis3d, rotate3d on
Run Code Online (Sandbox Code Playgroud)
现在我们可以通过这个创建有趣的动画来获得乐趣.考虑以下:
% 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
Run Code Online (Sandbox Code Playgroud)
我正在使用该hgtransform
函数来管理转换,这比连续更改图形对象的x/y/z数据点要高效得多.
顺便说一下,我在上面的动画中使用了稍微不同的图像.
让我们用映射到球体上的行星地球图像替换旋转立方体.首先是两个渲染球体的函数(我在MATLAB文档中借用了这些 例子中的代码):
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
动画脚本与之前类似(稍作修改),所以我不会重复它.结果如下:
Hok*_*oki 10
我有一个解决方案,通过使用呈现好texture mapping
.
我们的想法是将图像应用于脸部,让Matlab处理其他所有事情.最大的优点是matlab将处理所有透视方面,渲染非常好.缺点是您只能将纹理应用于surface
对象,并且由于您需要6个不同的图像,因此您必须管理6个不同的表面.
下面的代码显示了如何执行此操作的示例:
%% // read faces images
idxFaces = [1 2 3 4 5 6] ;
for iface = idxFaces
imgface{iface} = imread( ['E:\ICONS\number_blue_' num2str(iface) '-150x150.png'] ) ;
end
%% // Define cube properties
cubeLenght = 1 ;
x = linspace(-cubeLenght/2,cubeLenght/2,21) ;
[X,Y] = meshgrid(x,x) ;
Zp = ones(size(X))*cubeLenght/2 ; Zm = Zp-cubeLenght ;
%// draw face surfaces (organised 2 by 2)
hcubeface(1) = surf(X,Y,Zp ,'CData',imgface{1},'FaceColor','texturemap','LineStyle','none') ; hold on
hcubeface(6) = surf(X,Y,Zm ,'CData',imgface{6},'FaceColor','texturemap','LineStyle','none') ;
hcubeface(2) = surf(X,Zp,Y ,'CData',imgface{2},'FaceColor','texturemap','LineStyle','none') ;
hcubeface(5) = surf(X,Zm,Y ,'CData',imgface{5},'FaceColor','texturemap','LineStyle','none') ;
hcubeface(3) = surf(Zp,X,Y ,'CData',imgface{3},'FaceColor','texturemap','LineStyle','none') ;
hcubeface(4) = surf(Zm,X,Y ,'CData',imgface{4},'FaceColor','texturemap','LineStyle','none') ;
axis square
axis off
Run Code Online (Sandbox Code Playgroud)
这将呈现下图:
对不起我拍的第一张照片.您必须生成立方体面的漂亮图像,然后如上所示应用它们.
如果使用图形交互工具旋转多维数据集,则没有问题.
如果要以编程方式旋转它,则有2个选项:
如果对象是唯一显示的对象,那么最简单的方法是仅移动视点(使用view
或其他相机操作功能).
如果您有多个对象并且只想旋转多维数据集,则必须单独旋转每个曲面.在这种情况下,我建议编写一个辅助函数,在给定角度和方向的情况下,将为您旋转6个面.更简洁的方法是在一个类中管理您的多维数据集,然后添加一个方法来旋转它(在内部它将旋转6个面).
编辑:只是为了好玩,下面的片段会动画你的骰子(不是最温和的方式,但它会显示上面第一个选项的例子).
%% // animate by changing point of view
azi = linspace(-180,180,100) ;
for iv =1:100
view(azi(iv),azi(iv)+randi(5))
pause(0.01)
end
view(45,45)
Run Code Online (Sandbox Code Playgroud)
跑这个街区看你的骰子跳舞;)
编辑(再次)
这是一个关于如何通过旋转对象本身来动画化立方体对象的示例
%% // animate by rotating the object
%// this is necessary because the first rotation reset the axes to shading interp
rotate(hcubeface , [0 1 1] , 0.5)
for iface = 1:6 ; set( hcubeface(iface) , 'CData',imgface{iface}, 'FaceColor','texturemap' ) ; end
%// after that, no need to reset the texture map, enjoy as many rotations as you like
for iv =1:360
axerot = rand(1,3) ; % // pick a random axis to rotate around
rotate(hcubeface , axerot , 0.5) %// rotate the 6 faces by 0.5 degrees
pause(0.01)
end
Run Code Online (Sandbox Code Playgroud)
请注意,我修改了多维数据集的定义,以便在一个数组中包含所有面表面句柄.这允许rotate
仅通过将句柄数组作为参数发送,将命令一次性应用于所有表面.