Ответ 1
Идея состоит в том, чтобы использовать отображение текстур как @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
Еще лучше, позвольте использовать онлайн-сервис, который возвращает образы заполнителей, содержащие цифры от 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
Вот результирующие изображения:
>> imgs = get_images();
>> montage(cat(4,imgs{:}))
Затем создайте функцию, которая отображает куб единичного изображения с изображениями, отображаемыми в виде граней:
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
Вот как это выглядит:
imgs = get_images();
h = get_unit_cube(imgs);
view(3), axis vis3d, rotate3d on
Теперь мы можем немного повеселиться, создавая интересные анимации. Рассмотрим следующее:
% 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
Я использую hgtransform
для управления преобразованиями, это гораздо эффективнее, чем постоянное изменение точек данных x/y/z графических объектов.
BTW Я использовал несколько разных изображений в анимации выше.
EDIT:
Позвольте заменить вращающиеся кубы изображениями планеты Земля, нанесенными на сферы. Прежде всего, это две функции для визуализации сфер (я заимствую код из эти examples в документации MATLAB):
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
Анимация script похожа на предыдущую (с незначительными изменениями), поэтому я не собираюсь повторять ее. Вот результат:
(На этот раз я использую новую графическую систему в R2014b)