Este é um código MATLAB para criar uma árvore de natal 3D e animada (luzes piscando e neve caindo). A inspiração veio de diversas outras árvores de natal em MATLAB existentes na internet (pode procurar, elas existem). O diferencial dessa são as partes animadas e os presentes tridimensionais.
% A mensagem msg = char([70 101 108 105 122 32 78 97 116 97 108 33]); % Simplificando o cellfun para nao ter que digitar os dois últimos % parametros sempre cf = @(f,p)(cellfun(f, p, 'UniformOutput', 0)); % Ajusta o tamanho da figura, centraliza na tela e acerta outros parâmetros s_sz = get(0, 'ScreenSize'); f_sz = s_sz(3:4) * 0.5; figure('Units', 'Pixels', 'Position', [(s_sz(3:4)-f_sz)./2 f_sz], ... 'ToolBar', 'none', 'Name', msg, 'Renderer', 'OpenGL', ... 'NumberTitle', 'off', 'Color', [.6 .6 1], 'MenuBar','none');
% Isso gera a árvore, a função 'cylinder' cria um solido de revolução de % altura unitária, a partir de um vetor de raios [x y z] = cylinder([ones(1,7)*.5 (1.96:-.04:0)], 255); % Aqui amassamos a árvore para dar a ilusão de folhas individuais e do % tronco enrrugado. Note o z multiplicado por 5, para definir a altura % final da árvore amassa = @(m)(m .* (rand(size(m)) * .05 + .975)); C = cf(amassa, {x y z*5}); % Plota a árvore surfl(C{1}, C{2}, C{3}, 'light'); % Cria um colormap com o tronco marrom e um verde com gradiente colormap([repmat([.3 .24 .02],7,1); zeros(50,1) (.2:.01:0.69)' zeros(50,1)]); shading interp; % O titulo em letras grandes title(['{\bf \fontsize{16} ' msg '}']);
% Escolhe pontos na árvore que receberão as luzes piscantes, pegamos de 8 % ao final para garantir que não haverá luzes no tronco D = cf(@(m)(m(8:end,:)), C); dec = randperm(numel(D{1})); I = cf(@(in)(dec(in:in+49)), num2cell(1:50:151)); % xp, yp e zp formam um cubo de lado unitário xp = [0 1 0 0 0 0; 0 1 0 1 1 1; 1 1 0 1 1 1; 1 1 0 0 0 0]; yp = [0 0 0 1 0 0; 0 1 1 1 0 0; 0 1 1 1 1 1; 0 0 0 1 1 1]; zp = [0 0 0 0 1 0; 1 0 0 0 1 0; 1 1 1 1 1 0; 0 1 1 1 1 0]; % Com essa função podemos criar os presentes achatando, esticando e movendo % um cubo cubo = @(x,y,z,l,c,a,s)(patch(xp*l+x, yp*c+y, zp*a+z, s)); % As cores dos enfeites enfeites = {'r','g','y','c'}; % As cores em uma função que retorna uma ordem diferente para cada chamada, % assim as cores podem ser alternadas, fazendo as luzes piscarem cores = @()(cell2mat(enfeites(randperm(4)))); % Posição inicial da neve, note que usa-se a função 'amassa' para deixar a % posição da neve aleatoria [nx, ny, nz] = meshgrid(linspace(-3,3,5), linspace(-3,3,5), 0:0.25:7); N = cf(amassa, {nx(:) ny(:) nz(:)}); hold on % Plota as luzes e guarda o handle para poder fazer elas piscarem mais % adiante h = cellfun(@(in,s)(plot3(D{1}(in),D{2}(in),D{3}(in), ['d' s], 'MarkerFaceColor', s, 'MarkerEdgeColor', 'none')), I, enfeites); % Plota a neve e guarda o handle para faze-la cair mais adiante n = plot3(N{1}, N{2}, N{3}, 'xw'); % Cria os presentes e faixas decorativas para as caixas arrayfun(cubo, [-2 -1.6 -1.7 -0.5 -0.51 -3], [-1.5 -1.52 -1.2 -2.1 -2.11 -3], ... [0 -0.01 0.25 0 0.2 0], [1 0.2 0.5 0.7 0.72 6], [1 1.02 0.5 1 1.02 6], ... [0.25 0.27 0.3 0.6 0.2 -1e-5], 'rkgbrw'); hold off % Ajusta a posição da camera view(-34, 6); % Seria estranho uma árvore de natal com eixo cartesiano… axis equal off; % Limita o eixo z zlim([0 5]);
% Reseta o passo de tempo t_pos = 0; % 'while 1' equivale a 'para sempre' while 1 % Se o passo de tempo for par, pisca as luzes if rem(t_pos,2), arrayfun(@(x,s)(set(x, 'MarkerFaceColor', s)), h, cores()); end % A variavel N recebe a posição atual da neve Nz = get(n, 'ZData'); % Faz a neve cair 0.25 unidades Nz = Nz-0.25; % Devido a corte de custos, a neve que ja caiu no chão será mandada % para cima para cair de novo Nz(Nz <= 0) = 7; % Depois de ajustar os novos valores atualizamos a neve set(n, 'ZData', Nz); % Atualiza o passo de tempo t_pos = t_pos+1; % Manda o matlab desenhar, agora. drawnow; % Espera um 1/4 de segundo… pause(0.25); end