Let's vibe code Christmas trees

Mike Croucher on 15 Dec 2025 at 16:59
Latest activity Reply by Seth DeLand on 16 Dec 2025 at 14:26

I thought it would be fun to vibe code Christmas trees.
Model: Claude Sonnet4.5
Prompt: Write a MATLAB script that draws a Christmas tree. There should be decorations and presents too.
Result:
christmasTree()
function christmasTree()
% Christmas Tree with Decorations and Presents
% Creates a festive scene with a decorated tree and gift boxes
figure('Color', 'w', 'Position', [100, 100, 800, 900]);
hold on;
axis equal;
axis off;
xlim([-3, 3]);
ylim([0, 10]);
% Draw the tree (three layered triangular sections)
drawTreeSection(0, 2, 2.5, 2.5, [0.1, 0.5, 0.1]);
drawTreeSection(0, 3.5, 2, 2, [0.15, 0.55, 0.15]);
drawTreeSection(0, 4.8, 1.5, 1.8, [0.2, 0.6, 0.2]);
% Tree trunk
rectangle('Position', [-0.3, 0, 0.6, 2], 'FaceColor', [0.4, 0.2, 0.1], ...
'EdgeColor', 'none');
% Add decorations
addOrnaments();
addTinsel();
% Star on top
drawStar(0, 7.2, 0.4, [1, 0.84, 0]);
% Add presents under the tree
drawPresent(-1.8, 0, 0.6, 0.5, [0.8, 0.1, 0.1], [1, 0.84, 0]);
drawPresent(-0.8, 0, 0.5, 0.6, [0.1, 0.3, 0.8], [0.9, 0.9, 0.9]);
drawPresent(1.2, 0, 0.7, 0.4, [0.7, 0.5, 0.9], [0.2, 0.8, 0.2]);
drawPresent(0.2, 0, 0.4, 0.5, [1, 0.7, 0.1], [0.8, 0.1, 0.1]);
% Add some snow on the ground
scatter(randn(1, 100)*2.5, rand(1, 100)*0.3, 20, 'w', 'filled', ...
'MarkerEdgeColor', [0.8, 0.8, 0.8]);
title('Merry Christmas!', 'FontSize', 24, 'Color', [0.8, 0.1, 0.1], ...
'FontWeight', 'bold');
hold off;
end
function drawTreeSection(x, y, width, height, color)
% Draw a triangular section of the tree
xPoints = [x - width, x + width, x];
yPoints = [y, y, y + height];
fill(xPoints, yPoints, color, 'EdgeColor', [0.05, 0.3, 0.05], ...
'LineWidth', 1.5);
end
function addOrnaments()
% Add colorful baubles to the tree
ornamentColors = [
1, 0, 0; % Red
0, 0, 1; % Blue
1, 0.84, 0; % Gold
0.9, 0.1, 0.5;% Pink
0.5, 0, 0.5 % Purple
];
% Ornament positions (x, y coordinates)
positions = [
-1.5, 2.5; 1.5, 2.5; 0, 3.2;
-1.2, 3.8; 1.2, 3.8; -0.6, 4.2; 0.6, 4.2;
-0.8, 5.2; 0.8, 5.2; 0, 5.8; -0.4, 6.3; 0.4, 6.3
];
for i = 1:size(positions, 1)
colorIdx = mod(i-1, size(ornamentColors, 1)) + 1;
x = positions(i, 1);
y = positions(i, 2);
% Draw bauble
theta = linspace(0, 2*pi, 50);
radius = 0.15;
xCirc = x + radius * cos(theta);
yCirc = y + radius * sin(theta);
fill(xCirc, yCirc, ornamentColors(colorIdx, :), ...
'EdgeColor', ornamentColors(colorIdx, :)*0.7, 'LineWidth', 1.5);
% Add highlight for shine
highlightX = x - radius*0.4 + radius*0.3*cos(theta(1:15));
highlightY = y + radius*0.4 + radius*0.3*sin(theta(1:15));
fill(highlightX, highlightY, [1, 1, 1], 'EdgeColor', 'none', ...
'FaceAlpha', 0.6);
end
end
function addTinsel()
% Add sparkly tinsel effect
tinselX = [-1.8, -1.2, -0.5, 0.2, 0.9, 1.6];
tinselY = [2.8, 3.5, 4.0, 4.5, 5.0, 5.5];
for i = 1:length(tinselX)
plot(tinselX(i) + randn(1, 5)*0.1, tinselY(i) + rand(1, 5)*0.2, ...
'*', 'Color', [1, 0.84, 0], 'MarkerSize', 8, 'LineWidth', 1.5);
end
end
function drawStar(x, y, size, color)
% Draw a 5-pointed star on top of the tree
angles = linspace(0, 2*pi, 11);
radii = repmat([size, size*0.4], 1, 5);
radii = [radii, radii(1)];
xStar = x + radii .* cos(angles - pi/2);
yStar = y + radii .* sin(angles - pi/2);
fill(xStar, yStar, color, 'EdgeColor', [0.8, 0.6, 0], 'LineWidth', 2);
% Add sparkle
plot(x, y, '*', 'Color', [1, 1, 1], 'MarkerSize', 15, 'LineWidth', 2);
end
function drawPresent(x, y, width, height, boxColor, ribbonColor)
% Draw a gift box with ribbon and bow
% Box
rectangle('Position', [x, y, width, height], 'FaceColor', boxColor, ...
'EdgeColor', boxColor*0.7, 'LineWidth', 2);
% Vertical ribbon
ribbonWidth = width * 0.15;
rectangle('Position', [x + width/2 - ribbonWidth/2, y, ribbonWidth, height], ...
'FaceColor', ribbonColor, 'EdgeColor', 'none');
% Horizontal ribbon
ribbonHeight = height * 0.15;
rectangle('Position', [x, y + height/2 - ribbonHeight/2, width, ribbonHeight], ...
'FaceColor', ribbonColor, 'EdgeColor', 'none');
% Bow on top
bowX = x + width/2;
bowY = y + height;
bowSize = width * 0.2;
% Left loop
theta = linspace(0, pi, 30);
fill(bowX - bowSize*0.3 + bowSize*0.5*cos(theta), ...
bowY + bowSize*0.5*sin(theta), ribbonColor, 'EdgeColor', 'none');
% Right loop
fill(bowX + bowSize*0.3 + bowSize*0.5*cos(theta), ...
bowY + bowSize*0.5*sin(theta), ribbonColor, 'EdgeColor', 'none');
% Center knot
theta = linspace(0, 2*pi, 30);
fill(bowX + bowSize*0.25*cos(theta), bowY + bowSize*0.25*sin(theta), ...
ribbonColor*0.8, 'EdgeColor', 'none');
end
Manavendra
Manavendra on 16 Dec 2025 at 5:04 (Edited on 16 Dec 2025 at 5:22)
Prompts and follow-up prompts in MATLAB Copilot:
"please write code to create an animated plot of a christmas tre"
"modify the code to create a three dimentional christmas tree"
"modify the code to create a 10 second animation and save it as a GIF"
[ Error encountered :( ]
Explain error
"please incorporate the recommendations to modify the above code"
Code:
% christmas_tree_3d_gif_validated.m
clf
rng(1)
fig = figure('Color',[0.02 0.02 0.07],'MenuBar','none','ToolBar','none');
axis equal off
hold on
view(40,18)
set(fig,'Renderer','opengl') % reliable for capturing
% Parameters
layers = 5;
baseRadius = 6;
layerHeight = 1.6;
layerShrink = 0.75;
trunkW = 1.2;
trunkH = 1.6;
% Create stacked cones for tree
for k = 1:layers
r = baseRadius * layerShrink^(k-1);
h = layerHeight;
z0 = (k-1)* (layerHeight*0.9);
[X,Y,Z] = cylinder([0 r], 50);
Z = Z * h + z0;
X = flipud(X); Y = flipud(Y); Z = flipud(Z);
surf(X, Y, Z, 'FaceColor', [0 0.55-0.07*k 0], 'EdgeColor','none','FaceLighting','gouraud');
end
% Trunk
[tx,ty,tz] = cylinder(trunkW/2,40);
tz = tz * (-trunkH) - 0.2;
surf(tx,ty,tz,'FaceColor',[0.45 0.25 0.06],'EdgeColor','none','FaceLighting','gouraud');
% Star
starZ = layers*(layerHeight*0.9) + 0.6;
[xs,ys,zs] = sphere(8);
hStar = surf(xs*0.35, ys*0.35, zs*0.35 + starZ, 'FaceColor','y', 'EdgeColor','none','FaceLighting','gouraud');
% Ornaments
nOrn = 40;
ornPos = zeros(nOrn,3);
ornColors = [1 0 0; 0 0.9 1; 1 0.6 0; 1 0 1; 0.9 0.9 0]; % must be Nx3
% Validate ornColors shape
assert(size(ornColors,2)==3, 'ornColors must have 3 columns (RGB).');
for i=1:nOrn
L = randi(layers);
r = baseRadius * layerShrink^(L-1);
h = layerHeight;
z0 = (L-1)* (layerHeight*0.9);
theta = 2*pi*rand;
t = rand;
rr = r * t; zz = z0 + t*h;
ornPos(i,:) = [rr*cos(theta), rr*sin(theta), zz];
end
ornRadius = 0.18;
hOrn = gobjects(nOrn,1);
[bx,by,bz] = sphere(10);
for i=1:nOrn
xc = ornPos(i,1); yc = ornPos(i,2); zc = ornPos(i,3);
hOrn(i) = surf(bx*ornRadius+xc, by*ornRadius+yc, bz*ornRadius+zc, ...
'FaceColor',ornColors(mod(i-1,size(ornColors,1))+1,:), 'EdgeColor','none','FaceLighting','gouraud');
end
blinkState = randi([0 1],nOrn,1);
% Snow
nSnow = 120;
xlimVal = baseRadius*1.2;
sx = (rand(nSnow,1)-0.5)*xlimVal*2;
sy = (rand(nSnow,1)-0.5)*xlimVal*2;
sz = rand(nSnow,1)*(starZ+2);
hSnow = scatter3(sx,sy,sz,12,'w','filled','MarkerFaceAlpha',0.8);
% Lighting and material
camlight headlight
light('Position',[ -1 1 2],'Style','infinite')
material shiny
xlim([-xlimVal xlimVal]); ylim([-xlimVal xlimVal]); zlim([-trunkH-1, starZ+2]);
% GIF settings
gifFilename = 'christmas_tree_3d_validated.gif';
fps = 25; % frames per second
duration = 10; % seconds
T = fps * duration; % total frames
delayTime = 1 / fps;
% Debug flag: set true to print offending colors/indices
debug = false;
% Helper: clamp and validate RGB (1x3)
clampRGB = @(c) max(0,min(1,reshape(c,1,3)));
% Pre-draw to stabilize lighting/limits
drawnow
% Animation loop with GIF capture
for t = 1:T
% Blink ornaments
toggle = rand(nOrn,1) < 0.12;
blinkState(toggle) = ~blinkState(toggle);
for i=1:nOrn
% ensure hOrn(i) is a valid surface handle
if ~isgraphics(hOrn(i),'surface')
if debug
fprintf('hOrn(%d) is not a surface (class: %s)\n', i, class(hOrn(i)));
end
continue
end
if blinkState(i)
baseCol = ornColors(mod(i-1,size(ornColors,1))+1,:);
mult = (0.9 + 0.1*rand); % scalar in ~[0.9,1.0]
col = baseCol * mult;
else
col = [0.12 0.12 0.12];
end
% Validate size and clamp into [0,1]
if ~isnumeric(col) || numel(col) ~= 3
if debug, fprintf('Bad color at ornament %d: non-numeric or wrong length\n', i); end
col = [0.12 0.12 0.12];
end
col = clampRGB(col);
if debug && (any(col<0) || any(col>1))
fprintf('Clamped color at i=%d -> [%g %g %g]\n', i, col(1), col(2), col(3));
end
set(hOrn(i),'FaceColor',col,'FaceAlpha',1);
end
% Star twinkle
starCol = [1 0.92 0.2] * (0.8 + 0.4*abs(sin(0.15*t)));
% Ensure 1x3 and clamp
if ~isnumeric(starCol) || numel(starCol)~=3
starCol = [1 0.92 0.2];
end
starCol = clampRGB(starCol);
set(hStar,'FaceColor',starCol);
% Snow fall
sz = sz - (0.02 + 0.03*rand(nSnow,1));
fallen = sz < -trunkH-1;
if any(fallen)
sz(fallen) = starZ + 1 + rand(sum(fallen),1)*1.2;
sx(fallen) = (rand(sum(fallen),1)-0.5)*xlimVal*2;
sy(fallen) = (rand(sum(fallen),1)-0.5)*xlimVal*2;
end
set(hSnow,'XData',sx,'YData',sy,'ZData',sz);
% gentle camera orbit
camorbit(0.4,0,'data')
drawnow limitrate
% Capture frame and write to GIF
frame = getframe(fig);
[imind,cm] = rgb2ind(frame2im(frame),256);
if t == 1
imwrite(imind,cm,gifFilename,'gif','LoopCount',Inf,'DelayTime',delayTime);
else
imwrite(imind,cm,gifFilename,'gif','WriteMode','append','DelayTime',delayTime);
end
end
disp(['Saved GIF: ' gifFilename])
Saved GIF: christmas_tree_3d_validated.gif
Manavendra
Manavendra on 16 Dec 2025 at 5:19
Had to compress the GIF because of size constraints, and hence the static in the GIF.
Mike Croucher
Mike Croucher on 16 Dec 2025 at 9:08
Very nice!
Vasilis Bellos
Vasilis Bellos on 16 Dec 2025 at 0:37 (Edited on 16 Dec 2025 at 0:40)
Here's a hybrid approach where I asked Claude Opus 4.5 to enhance my code from last year (based on the original Rotating Christmas Tree code of the amazing @Zhaoxu Liu / slandarer). The final product after a few iterations:
%% Enhanced MATLAB Christmas Tree
% Based on: https://uk.mathworks.com/matlabcentral/discussions/tips/878025-christmas-tree-for-matlaber-rotating-with-falling-snowflakes
% Enhancements: trunk, tinsel, presents, star twinkle, wind drift, ground plane, LED chase animation, dust motes
fig = figure('Units','normalized', 'Position',[.25,0,.5,1],...
'Color',[0,9,33]/255);
ax = axes('Parent',fig, 'Position',[0,-1/6,1,1+1/3],...
'XLim',[-6,6], 'YLim',[-6,6], 'ZLim',[-23, 1], 'DataAspectRatio', [1,1,1], 'NextPlot','add',...
'Projection','perspective', 'Color',[0,9,33]/255, 'XColor','none', 'YColor','none', 'ZColor','none');
%% Draw Tree Skirt / Carpet (soft white disc, slightly larger than tree)
groundZ = -18;
carpetTheta = linspace(0, 2*pi, 100);
carpetR = 5.8;
carpetX = carpetR * cos(carpetTheta);
carpetY = carpetR * sin(carpetTheta);
carpetZ = ones(size(carpetX)) * groundZ;
patch('XData', carpetX, 'YData', carpetY, 'ZData', carpetZ, ...
'FaceColor', [0.98, 0.99, 1.0], 'EdgeColor', 'none', ...
'FaceAlpha', 0.92, 'FaceLighting', 'none');
%% Draw Tree Trunk
[Tx, Ty, Tz] = cylinder([0.35 0.45], 20);
Tz = Tz * 4.5 + groundZ; % Taller trunk, pierces into bottom tree layer
trunkHdl = surf(Tx, Ty, Tz, 'FaceColor', [0.35, 0.18, 0.05], 'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', 'AmbientStrength', 0.4);
%% Draw Christmas Tree Layers
[X, T] = meshgrid(.4:.15:1, 0:pi/150:2*pi);
XM = 1 + sin(8.*T) .* .05;
X = X .* XM;
R = X.^(3) .* (.5 + sin(8.*T) .* .02);
dF = @(R, T, X) surf(R.*cos(T), R.*sin(T), -X, 'EdgeColor','interp',...
'FaceColor', [20,107,58]./255, 'FaceAlpha',.8, 'LineWidth',1,'MeshStyle','Column',...
'FaceLighting','gouraud','AmbientStrength',.3,'DiffuseStrength',.5,'SpecularStrength',.5);
cmap = colormap(turbo);
% LED strips - store for animation
cmap = colormap(repmat([cmap; flip(cmap)], 3, 1));
cmapLen = size(cmap, 1);
% Star light
arrayfun(@(x)light('Style','local','Position',[0 0 -1.3],'Color',[255,223,153]./255), 1:4);
CList = [255,100,100; 150,255,100; 0,255,255]./255;
rng(1);
% Store surface handles for LED animation
surfaceHandles = gobjects(6, 1);
% Store RGB light scatter handles for twinkling
rgbLightHandles = {};
rgbLightColors = {};
for i = 1:6
tR = R .* (2 + i);
tT = T + i;
tX = X .* (2 + i) + i;
SFHdl = dF(tR, tT, tX);
surfaceHandles(i) = SFHdl;
% LED strip gradient
for j = 1:size(SFHdl.CData, 2)
SFHdl.CData(:, j) = linspace(1, cmapLen, size(SFHdl.CData, 1));
end
[~, ind] = sort(SFHdl.ZData(:));
ind = ind(1:8);
C = CList(randi([1, size(CList, 1)], [8, 1]), :);
% Tree lights symmetry
if i == 1
C(length(C)/2+1:end, :) = C(1:length(C)/2, :);
end
if mod(i, 2)
for j = 1:length(ind)/2
P = drawPinecone;
set(P, 'Matrix', makehgtform('Translate', [tR(ind(j)).*cos(tT(ind(j))), ...
tR(ind(j)).*sin(tT(ind(j))), -tX(ind(j))], 'Scale', 0.35));
end
% Glow scatter (large, transparent)
glowHdl = scatter3(tR(ind(length(ind)/2+1:end)).*cos(tT(ind(length(ind)/2+1:end)))*1.01, ...
tR(ind(length(ind)/2+1:end)).*sin(tT(ind(length(ind)/2+1:end)))*1.01, ...
-tX(ind(length(ind)/2+1:end)), 500, 'filled',...
'CData', C(length(ind)/2+1:end,:), 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.3);
% Core scatter (small, solid)
coreHdl = scatter3(tR(ind(length(ind)/2+1:end)).*cos(tT(ind(length(ind)/2+1:end)))*1.01, ...
tR(ind(length(ind)/2+1:end)).*sin(tT(ind(length(ind)/2+1:end)))*1.01, ...
-tX(ind(length(ind)/2+1:end)), 80, 'filled', 'CData', C(length(ind)/2+1:end,:));
rgbLightHandles{end+1} = glowHdl;
rgbLightHandles{end+1} = coreHdl;
rgbLightColors{end+1} = C(length(ind)/2+1:end,:);
rgbLightColors{end+1} = C(length(ind)/2+1:end,:);
else
if i == 2 || i == 4
M = drawMembraneOrnament;
set(M, 'Matrix', makehgtform('Translate', [tR(ind(1)).*cos(tT(ind(1)))*.98, ...
tR(ind(1)).*sin(tT(ind(1)))*.98, -tX(ind(1))+0.05*0], 'ZRotate', rand*pi+pi/4*i, 'Scale', .9));
M = drawMembraneOrnament;
set(M, 'Matrix', makehgtform('Translate', [tR(ind(3)).*cos(tT(ind(3)))*.98, ...
tR(ind(3)).*sin(tT(ind(3)))*.98, -tX(ind(3))+0.05*0], 'ZRotate', rand*pi+pi/4*i, 'Scale', .9));
glowHdl = scatter3(tR(ind([2,4:end])).*cos(tT(ind([2,4:end])))*1.01, ...
tR(ind([2,4:end])).*sin(tT(ind([2,4:end])))*1.01, ...
-tX(ind([2,4:end])), 500, 'filled',...
'CData', C([2,4:end],:), 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.3);
coreHdl = scatter3(tR(ind([2,4:end])).*cos(tT(ind([2,4:end])))*1.01, ...
tR(ind([2,4:end])).*sin(tT(ind([2,4:end])))*1.01, ...
-tX(ind([2,4:end])), 80, 'filled', 'CData', C([2,4:end],:));
rgbLightHandles{end+1} = glowHdl;
rgbLightHandles{end+1} = coreHdl;
rgbLightColors{end+1} = C([2,4:end],:);
rgbLightColors{end+1} = C([2,4:end],:);
else
glowHdl = scatter3(tR(ind).*cos(tT(ind))*1.01, tR(ind).*sin(tT(ind))*1.01, -tX(ind), 500, 'filled',...
'CData', C, 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.3);
coreHdl = scatter3(tR(ind).*cos(tT(ind))*1.01, tR(ind).*sin(tT(ind))*1.01, -tX(ind), 80, 'filled', 'CData', C);
rgbLightHandles{end+1} = glowHdl;
rgbLightHandles{end+1} = coreHdl;
rgbLightColors{end+1} = C;
rgbLightColors{end+1} = C;
end
end
% Tree lights
if i == 1
arrayfun(@(h)light('Style','Local','Position',[tR(ind(h)).*cos(tT(ind(h)))*.7, ...
tR(ind(h)).*sin(tT(ind(h)))*.7, -tX(ind(h))+2],'Color',C(h,:)), length(ind)/2+1:length(ind));
end
end
%% Draw Tinsel/Garland (thicker, closer to tree, themed colors)
nTinsel = 800;
tinselT = linspace(0, 8*pi, nTinsel);
% Very close to tree - tight radius following tree cone
tinselR = linspace(1.0, 5.2, nTinsel);
tinselX = tinselR .* cos(tinselT);
tinselY = tinselR .* sin(tinselT);
tinselZ = -linspace(2.5, 14.2, nTinsel); % Shifted downwards
% Add slight waviness
tinselZ = tinselZ + 0.10 * sin(tinselT * 4);
% First strand - use turbo-like gradient (matches LED strips)
% Create color gradient along tinsel
tinselColors1 = turbo(nTinsel);
% Plot as individual segments for color gradient effect
for k = 1:10:nTinsel-10
plot3(tinselX(k:k+10), tinselY(k:k+10), tinselZ(k:k+10), ...
'Color', [tinselColors1(k,:), 0.85], 'LineWidth', 3);
end
% Second strand - offset, gold/warm color (matches star)
tinselT2 = tinselT + pi/2.5;
tinselX2 = tinselR .* cos(tinselT2);
tinselY2 = tinselR .* sin(tinselT2);
tinselZ2 = tinselZ + 0.1 * cos(tinselT * 3);
plot3(tinselX2, tinselY2, tinselZ2, 'Color', [255, 223, 153, 200]./255, 'LineWidth', 2.5);
% Third strand - warm gold/cream color (complementary to other strands)
tinselT3 = tinselT + pi;
tinselX3 = tinselR .* cos(tinselT3);
tinselY3 = tinselR .* sin(tinselT3);
tinselZ3 = tinselZ - 0.08 * sin(tinselT * 5);
plot3(tinselX3, tinselY3, tinselZ3, 'Color', [255, 200, 120, 180]./255, 'LineWidth', 2);
%% Draw Presents (spaced around tree, colorful, uniform height)
% Vibrant colors matching festive theme
presentColors = [255, 80, 80; % bright red
80, 220, 255; % bright cyan
255, 220, 80; % golden yellow
180, 100, 255]./255; % purple
% Red ribbons to match bow color
ribbonColors = [255, 80, 80; % red
255, 80, 80; % red
255, 80, 80; % red
255, 80, 80]./255; % red
% Bow color - festive red
bowColor = [255, 80, 80]./255;
% Spaced out in a ring around the tree
presentPositions = [-3.0, 2.5, groundZ;
3.2, 1.8, groundZ;
-2.5, -3.0, groundZ;
2.8, -2.5, groundZ];
% Uniform height (1.2), varied rectangular footprints
uniformHeight = 1.2;
presentSizes = [2.0, 1.4, uniformHeight;
1.5, 2.2, uniformHeight;
1.8, 1.3, uniformHeight;
1.4, 1.8, uniformHeight];
for p = 1:size(presentPositions, 1)
drawPresent(presentPositions(p,:), presentSizes(p,:), presentColors(p,:), ribbonColors(p,:), bowColor);
end
%% Draw Star of Bethlehem
Rx = @(V, theta) V * [1 0 0; 0 cos(theta) sin(theta); 0 -sin(theta) cos(theta)];
w = .3; RStar = .62; r = .4;
TStar = (1/8:1/8:(2 - 1/8)).' .* pi;
V8 = [0, 0, w; 0, 0, -w;
1, 0, 0; 0, 1, 0; -1, 0, 0; 0, -1, 0;
RStar, RStar, 0; -RStar, RStar, 0; -RStar, -RStar, 0; RStar, -RStar, 0;
cos(TStar).*r, sin(TStar).*r, TStar.*0];
F8 = [1,3,25; 1,3,11; 2,3,25; 2,3,11; 1,7,11; 1,7,13; 2,7,11; 2,7,13;
1,4,13; 1,4,15; 2,4,13; 2,4,15; 1,8,15; 1,8,17; 2,8,15; 2,8,17;
1,5,17; 1,5,19; 2,5,17; 2,5,19; 1,9,19; 1,9,21; 2,9,19; 2,9,21;
1,6,21; 1,6,23; 2,6,21; 2,6,23; 1,10,23; 1,10,25; 2,10,23; 2,10,25];
V8 = Rx(V8 .* .8, pi/2) + [0, 0, -1.3];
starPatch = patch('Faces', F8, 'Vertices', V8, 'FaceColor', [255,223,153]./255,...
'EdgeColor', [255,223,153]./255, 'FaceAlpha', 1, 'FaceLighting', 'gouraud', ...
'AmbientStrength', .7, 'DiffuseStrength', .8, 'SpecularStrength', 0);
%% Draw Snow (two populations) - deterministic for seamless loop
rng(42); % Fixed seed for reproducibility
nSnow1 = 90;
nSnow2 = 110;
nSnowTotal = nSnow1 + nSnow2;
% Initial positions (these will be restored at frame 360)
sXYZ_init = rand(nSnowTotal, 3) .* [12, 12, 19] - [6, 6, 18];
sXYZ = sXYZ_init;
% Fall speeds: snow must fall exactly N complete cycles in 360 frames
% Height range is 19 units (-18 to 1), so fall speed * 360 = N * 19
% For seamless loop: group 1 falls 2 cycles (38 units), group 2 falls 3 cycles (57 units)
fallSpeed1 = 2 * 19 / 360; % 2 complete cycles
fallSpeed2 = 3 * 19 / 360; % 3 complete cycles
sHdl1 = plot3(sXYZ(1:nSnow1, 1), sXYZ(1:nSnow1, 2), sXYZ(1:nSnow1, 3), '*', 'LineWidth', 1, ...
'MarkerSize', 12, 'Color', [1 1 1] * .9);
sHdl2 = plot3(sXYZ(nSnow1+1:end, 1), sXYZ(nSnow1+1:end, 2), sXYZ(nSnow1+1:end, 3), '.', ...
'MarkerSize', 10, 'Color', [1 1 1] * .9);
%% Draw Dust Motes / Ambient Particles - deterministic for seamless loop
nDust = 80;
dustXYZ_init = rand(nDust, 3) .* [10, 10, 16] - [5, 5, 16];
dustHdl = scatter3(dustXYZ_init(:,1), dustXYZ_init(:,2), dustXYZ_init(:,3), 8, 'filled', ...
'MarkerFaceColor', [1, 0.95, 0.8], 'MarkerFaceAlpha', 0.3, 'MarkerEdgeColor', 'none');
%% Animation Loop
frames = {};
step = 10;
for i = 1:step:360
% Snow fall - deterministic cyclic motion
% Calculate position based on frame number (not cumulative)
snowZ1 = sXYZ_init(1:nSnow1, 3) - fallSpeed1 * i;
snowZ2 = sXYZ_init(nSnow1+1:end, 3) - fallSpeed2 * i;
% Wrap using mod to keep in range [-18, 1] (height 19)
snowZ1 = mod(snowZ1 + 18, 19) - 18;
snowZ2 = mod(snowZ2 + 18, 19) - 18;
% Deterministic wind drift based on frame (sinusoidal, completes full cycles)
windX1 = 0.5 * sin(2 * pi * i / 360 + sXYZ_init(1:nSnow1, 3) * 0.2);
windX2 = 0.5 * sin(2 * pi * i / 360 + sXYZ_init(nSnow1+1:end, 3) * 0.2);
sHdl1.XData = sXYZ_init(1:nSnow1, 1) + windX1;
sHdl1.ZData = snowZ1;
sHdl2.XData = sXYZ_init(nSnow1+1:end, 1) + windX2;
sHdl2.ZData = snowZ2;
% Dust motes - sinusoidal motion (completes full cycles in 360 frames)
dustX = dustXYZ_init(:, 1) + 0.3 * sin(2 * pi * i / 360 + (1:nDust)' * 0.5);
dustY = dustXYZ_init(:, 2) + 0.3 * cos(2 * pi * i / 360 + (1:nDust)' * 0.3);
dustZ = dustXYZ_init(:, 3) + 0.2 * sin(2 * pi * i / 180 + (1:nDust)' * 0.2);
dustHdl.XData = dustX;
dustHdl.YData = dustY;
dustHdl.ZData = dustZ;
% RGB lights twinkle - vary brightness by modulating color intensity (subtle fade)
% Uses 2*pi*i/360 for seamless loop (completes integer cycles)
for k = 1:length(rgbLightHandles)
if isvalid(rgbLightHandles{k})
baseColors = rgbLightColors{k};
nLights = size(baseColors, 1);
% Each light twinkles at a different phase, fading between 70% and 100% brightness
% 12 complete cycles in 360 frames
twinkleFactor = 0.85 + 0.15 * sin(2 * pi * i * 12 / 360 + (1:nLights)' * pi / 3);
modulatedColors = baseColors .* twinkleFactor;
rgbLightHandles{k}.CData = modulatedColors;
end
end
% LED chase animation - use frame-based calculation for seamless loop
% Shift by amount that returns to start after 360 frames
for s = 1:length(surfaceHandles)
if isvalid(surfaceHandles(s))
[nRows, nCols] = size(surfaceHandles(s).CData);
baseData = linspace(1, cmapLen, nRows)';
shiftAmount = mod(i * 2, cmapLen); % 2 units per frame, wraps at cmapLen
newCol = mod(baseData + shiftAmount - 1, cmapLen) + 1;
surfaceHandles(s).CData = repmat(newCol, 1, nCols);
end
end
view([i, 30]);
drawnow;
frames{end+1} = getframe(gcf);
end
%% Helper Functions
function H = drawPinecone
% Ref: https://blogs.mathworks.com/graphics-and-apps/2024/12/16/pinecode-creating-pinecones-with-fibonacci-spirals/
nscales = 140;
height = 2.5;
nn = 18;
vps = 17;
vpr = 20;
FIB = (1+sqrt(5)) * (1:nscales);
H_pc = linspace(0, 1, nscales).^2.8 * height;
R_pc = 1 - linspace(-1, 1, nscales).^2;
U = 1 - abs(linspace(-1, 1, nscales).^3);
ST = reshape((linspace(-.5, .5, vps) * .3 + FIB')', 1, []);
SR = reshape(((1 - abs(linspace(-1, 1, vps).^3)) .* R_pc')', 1, []);
SH = reshape((ones(1, vps) .* H_pc' + abs(linspace(-1, 1, vps).^3 .* U') * .2)', 1, []);
MR = linspace(0, 1, vpr)' .* SR;
X = cospi(ST) .* MR;
Y = sinpi(ST) .* MR;
Z = SH .* ones(vpr, 1) + MR .* linspace(0, 1, vps*nscales).^2.1 * 1.2;
P(1) = plot3(X(end,:), Y(end,:), -Z(end,:), '-', 'LineWidth', .5, 'Color', [120 61 3]/255*.5);
P(2) = surface(X, Y, -Z, 'FaceColor', "#783D03", 'EdgeColor', 'none', 'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.5, 'SpecularColorReflectance', 0.1, 'SpecularStrength', 0.1, ...
'SpecularExponent', 5, 'DiffuseStrength', 0.15);
P(3) = line('XData', (0:.5:2)/3*cos(rand*2*pi), 'YData', zeros(1,5), 'ZData', [0 .05 .2 .25 .2]*2, ...
'Color', 'k', 'LineWidth', 1);
NT = linspace(0, 5, nn)';
NR = linspace(.1, .8, nn)';
NV = [0 0 0; -ones(nn,1).*randi([-1,1], nn, 1)*.5, cospi(NT).*NR, sinpi(NT).*NR+.9];
NF = [ones(nn, 1), (1:nn)'+1];
P(4) = patch('Vertices', NV, 'Faces', NF, 'EdgeColor', '#0F9666', 'FaceColor', 'none', 'LineWidth', 1);
H = hgtransform;
set(P, 'Parent', H);
end
function H = drawMembraneOrnament
% Ref: https://uk.mathworks.com/help/matlab/visualize/creating-the-matlab-logo.html
L = membrane(1, 100);
L = L - max(L, [], 'all');
[x, y] = deal(linspace(-.5, .5, length(L)));
[r, c] = find(L == max(L, [], 'all'));
x = x + x(r);
y = y + y(c);
[X, Y] = meshgrid(x, y);
S(1) = surface(X, Y, L, 'EdgeColor', 'none');
view(3);
Z = S(1).ZData;
S(2) = surf([X(Y==Y(1))*[1 1]; NaN(1,2); X(X==X(1))*[1 1]; NaN(1,2); X(Y==Y(end))*[1 1]; NaN(1,2); X(X==X(end))*[1 1]; NaN(1,2); X([1,end],[1,end])],...
[Y(Y==Y(1))*[1 1]; NaN(1,2); Y(X==X(1))*[1 1]; NaN(1,2); Y(Y==Y(end))*[1 1]; NaN(1,2); Y(X==X(end))*[1 1]; NaN(1,2); Y([1,end],[1,end])],...
[[Z(Y==Y(1)), ones(size(Z(Y==Y(1))))*(min(Z,[],'all'))]; NaN(1,2); [Z(X==X(1)), ones(size(Z(X==X(1))))*(min(Z,[],'all'))]; NaN(1,2);...
[Z(Y==Y(end)), ones(size(Z(Y==Y(end))))*(min(Z,[],'all'))]; NaN(1,2); [Z(X==X(end)), ones(size(Z(X==X(end))))*(min(Z,[],'all'))];...
NaN(1,2); ones(2,2)*(min(Z,[],'all'))], 'EdgeColor', 'none');
set(S, 'FaceColor', '#FF4433', 'FaceLighting', 'gouraud', 'AmbientStrength', .3, ...
'DiffuseStrength', .6, 'BackFaceLighting', 'lit', 'SpecularStrength', 1, ...
'SpecularColorReflectance', 1, 'SpecularExponent', 7);
H = hgtransform;
set(S, 'Parent', H);
end
function drawPresent(pos, sz, faceColor, ribbonColor, bowColor)
% Draw a wrapped present box with thick ribbon - sits on ground, doesn't sink
x0 = pos(1) - sz(1)/2; % center the box at pos
y0 = pos(2) - sz(2)/2;
z0 = pos(3); % bottom sits exactly on ground
dx = sz(1); dy = sz(2); dz = sz(3);
% Box vertices
verts = [x0, y0, z0; % 1
x0+dx, y0, z0; % 2
x0+dx, y0+dy, z0; % 3
x0, y0+dy, z0; % 4
x0, y0, z0+dz; % 5
x0+dx, y0, z0+dz; % 6
x0+dx, y0+dy, z0+dz; % 7
x0, y0+dy, z0+dz]; % 8
faces = [1 2 3 4; % bottom
5 6 7 8; % top
1 2 6 5; % front
3 4 8 7; % back
1 4 8 5; % left
2 3 7 6]; % right
patch('Vertices', verts, 'Faces', faces, 'FaceColor', faceColor, ...
'EdgeColor', faceColor * 0.6, 'LineWidth', 1, 'FaceAlpha', 1, ...
'FaceLighting', 'gouraud', 'AmbientStrength', 0.5, 'DiffuseStrength', 0.6);
% Thick ribbon parameters
rw = 0.12 * max([dx, dy]);
ribbonOffset = 0.025;
% All ribbon patche
rx = x0 + dx/2;
ry = y0 + dy/2;
% Front face ribbon
patch('Vertices', [rx-rw, y0-ribbonOffset, z0; rx+rw, y0-ribbonOffset, z0; ...
rx+rw, y0-ribbonOffset, z0+dz; rx-rw, y0-ribbonOffset, z0+dz], ...
'Faces', [1 2 3 4], 'FaceColor', ribbonColor, 'EdgeColor', 'none', ...
'FaceLighting', 'none');
% Back face ribbon
patch('Vertices', [rx-rw, y0+dy+ribbonOffset, z0; rx+rw, y0+dy+ribbonOffset, z0; ...
rx+rw, y0+dy+ribbonOffset, z0+dz; rx-rw, y0+dy+ribbonOffset, z0+dz], ...
'Faces', [1 2 3 4], 'FaceColor', ribbonColor, 'EdgeColor', 'none', ...
'FaceLighting', 'none');
% Left face ribbon
patch('Vertices', [x0-ribbonOffset, ry-rw, z0; x0-ribbonOffset, ry+rw, z0; ...
x0-ribbonOffset, ry+rw, z0+dz; x0-ribbonOffset, ry-rw, z0+dz], ...
'Faces', [1 2 3 4], 'FaceColor', ribbonColor, 'EdgeColor', 'none', ...
'FaceLighting', 'none');
% Right face ribbon
patch('Vertices', [x0+dx+ribbonOffset, ry-rw, z0; x0+dx+ribbonOffset, ry+rw, z0; ...
x0+dx+ribbonOffset, ry+rw, z0+dz; x0+dx+ribbonOffset, ry-rw, z0+dz], ...
'Faces', [1 2 3 4], 'FaceColor', ribbonColor, 'EdgeColor', 'none', ...
'FaceLighting', 'none');
% Top ribbon strip (front-back direction)
patch('Vertices', [rx-rw, y0, z0+dz+ribbonOffset; rx+rw, y0, z0+dz+ribbonOffset; ...
rx+rw, y0+dy, z0+dz+ribbonOffset; rx-rw, y0+dy, z0+dz+ribbonOffset], ...
'Faces', [1 2 3 4], 'FaceColor', ribbonColor, 'EdgeColor', 'none', ...
'FaceLighting', 'none');
% Top ribbon strip (left-right direction)
patch('Vertices', [x0, ry-rw, z0+dz+ribbonOffset; x0+dx, ry-rw, z0+dz+ribbonOffset; ...
x0+dx, ry+rw, z0+dz+ribbonOffset; x0, ry+rw, z0+dz+ribbonOffset], ...
'Faces', [1 2 3 4], 'FaceColor', ribbonColor, 'EdgeColor', 'none', ...
'FaceLighting', 'none');
% Bow on top, festive color
bowX = x0 + dx/2;
bowY = y0 + dy/2;
bowZ = z0 + dz + ribbonOffset;
bowSize = rw * 3.2;
% Bow loops
scatter3(bowX - bowSize*0.4, bowY, bowZ + bowSize*0.25, 180, 'filled', ...
'MarkerFaceColor', bowColor, 'MarkerFaceAlpha', 1, 'MarkerEdgeColor', 'none');
scatter3(bowX + bowSize*0.4, bowY, bowZ + bowSize*0.25, 180, 'filled', ...
'MarkerFaceColor', bowColor, 'MarkerFaceAlpha', 1, 'MarkerEdgeColor', 'none');
% Center knot
scatter3(bowX, bowY, bowZ + bowSize*0.15, 100, 'filled', ...
'MarkerFaceColor', bowColor * 0.8, 'MarkerEdgeColor', 'none');
end
Mike Croucher
Mike Croucher on 16 Dec 2025 at 9:09
That looks fantastic!
Ned Gulley
Ned Gulley on 15 Dec 2025 at 20:43
My first result was chaos!
But it got better.
% Create figure with dark background for night time
figure('Color', [0.05 0.05 0.15], 'Position', [100 100 800 800]);
ax = axes('Position', [0.05 0.05 0.9 0.9]);
set(ax, 'Color', [0.05 0.05 0.15]);
hold on;
% Get the L-shaped membrane data
Z = membrane(1);
[m, n] = size(Z);
[X, Y] = meshgrid(1:n, 1:m);
% Center the coordinates around origin
X = X - mean(X(:));
Y = Y - mean(Y(:));
Z = Z - mean(Z(:));
% Stretch Z extent by factor of 5
Z = Z * 5;
% Create the base membrane surface
baseSurf = surf(X, Y, Z);
set(baseSurf, 'FaceColor', [0.1 0.6 0.2], 'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', 'AmbientStrength', 0.5);
% Create transform for base layer
baseTransform = hgtransform('Parent', ax);
set(baseSurf, 'Parent', baseTransform);
% Number of tree layers
numLayers = 15;
% Store handles for all tree layers
treeHandles = baseTransform;
% Set initial transform for base layer (layer 1)
i = 1;
scaleXY = 1.0 - 0.06 * (i - 1); % X-Y scale shrinks with height (adjusted for 15 layers)
scaleZ = 1.0; % Keep Z scale constant
rotAngle1 = 40 * i;
Rz1 = makehgtform('zrotate', deg2rad(rotAngle1));
S1 = makehgtform('scale', [scaleXY scaleXY scaleZ]);
set(baseTransform, 'Matrix', Rz1 * S1);
% Create the tree by cloning and transforming membrane copies
for i = 2:numLayers
% Clone the base surface
clonedSurf = copyobj(baseSurf, ax);
% Create transform object for this layer
t = hgtransform('Parent', ax);
set(clonedSurf, 'Parent', t);
% Calculate X-Y scale factor (shrinks as we go up for conical shape)
scaleXY = 1.0 - 0.06 * (i - 1);
% Keep Z scale constant (don't shrink vertical extent)
scaleZ = 1.0;
% Calculate rotation angle (spins each layer)
rotAngle = 40 * i;
% Calculate vertical position (stacks upward with overlap)
zOffset = 3.0 * (i - 1);
% Create transformation matrix
% Rotation around Z axis
Rz = makehgtform('zrotate', deg2rad(rotAngle));
% Scale (different for X-Y vs Z)
S = makehgtform('scale', [scaleXY scaleXY scaleZ]);
% Translation
T = makehgtform('translate', [0, 0, zOffset]);
% Apply combined transformation
set(t, 'Matrix', T * Rz * S);
treeHandles = [treeHandles; t];
end
% Add snowy ground
[Xground, Yground] = meshgrid(-20:2:20, -20:2:20);
Zground = -5 + 0.3*randn(size(Xground)); % Slight variation for snow texture
groundSurf = surf(Xground, Yground, Zground);
set(groundSurf, 'FaceColor', [0.95 0.95 1.0], 'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', 'AmbientStrength', 0.7, 'DiffuseStrength', 0.6);
% Add sphere ornaments scattered on the tree
numOrnaments = 30;
ornamentColors = [
1.0, 0.0, 0.0; % Red
1.0, 0.8, 0.0; % Gold
0.0, 0.5, 1.0; % Blue
1.0, 0.0, 1.0; % Magenta
0.0, 1.0, 1.0; % Cyan
1.0, 0.5, 0.0; % Orange
0.8, 0.0, 0.8; % Purple
1.0, 1.0, 0.0; % Yellow
1.0, 0.2, 0.6; % Pink
0.5, 1.0, 0.0; % Lime
];
% Find edge points of the original membrane
% The edges are the boundary of the L-shaped membrane
[m, n] = size(X);
edgeRows = [];
edgeCols = [];
% Top edge
edgeRows = [edgeRows, ones(1, n)];
edgeCols = [edgeCols, 1:n];
% Bottom edge
edgeRows = [edgeRows, m*ones(1, n)];
edgeCols = [edgeCols, 1:n];
% Left edge (excluding corners already added)
edgeRows = [edgeRows, 2:m-1];
edgeCols = [edgeCols, ones(1, m-2)];
% Right edge (excluding corners already added)
edgeRows = [edgeRows, 2:m-1];
edgeCols = [edgeCols, n*ones(1, m-2)];
% Sample random edge points for ornaments
numEdgePoints = length(edgeRows);
ornamentCount = 0;
for i = 1:numOrnaments
% Random layer
layer = randi([1, numLayers]);
% Random edge point
edgeIdx = randi(numEdgePoints);
row = edgeRows(edgeIdx);
col = edgeCols(edgeIdx);
% Get the base coordinates at this edge point
xBase = X(row, col);
yBase = Y(row, col);
zBase = Z(row, col);
% Apply the same transformation as the layer
scaleXY = 1.0 - 0.06 * (layer - 1);
rotAngle = 40 * layer;
zOffset = 3.0 * (layer - 1);
% Transform the point
cosTheta = cosd(rotAngle);
sinTheta = sind(rotAngle);
xPos = scaleXY * (xBase * cosTheta - yBase * sinTheta);
yPos = scaleXY * (xBase * sinTheta + yBase * cosTheta);
zPos = zBase + zOffset;
% Create sphere
[Xs, Ys, Zs] = sphere(20);
sphereSize = 0.5 + rand() * 0.3;
Xs = Xs * sphereSize + xPos;
Ys = Ys * sphereSize + yPos;
Zs = Zs * sphereSize + zPos;
% Random color
colorIdx = randi(size(ornamentColors, 1));
% Draw sphere
ornament = surf(Xs, Ys, Zs);
set(ornament, 'FaceColor', ornamentColors(colorIdx, :), ...
'EdgeColor', 'none', 'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.5, 'DiffuseStrength', 0.8, 'SpecularStrength', 0.9);
end
% Set up the view
axis vis3d;
axis off;
view(3);
camlight('headlight');
lighting gouraud;
material([0.4 0.6 0.1])
% Set axis limits to frame the tree and ground nicely
axis([-27 27 -22 31 -30 68]);
title('Christmas Tree from L-Shaped Membrane', 'FontSize', 16, 'FontWeight', 'bold', 'Color', 'w');
% Rotate for better initial view
view(45, 20);
Seth DeLand
Seth DeLand on 15 Dec 2025 at 19:50
Prompt: "Write the MATLAB code for drawing a Christmas tree. The tree should have a star, ornaments, and a presents beneath it."
Code:
% Christmas Tree with Star, Ornaments, and Presents
% Clear workspace and create figure
clear; clc; close all;
figure('Color', [0.1 0.1 0.3], 'Position', [100 100 600 700]);
hold on;
axis equal;
axis off;
xlim([-10 10]);
ylim([-3 18]);
% === TREE TRUNK ===
trunkX = [-1 1 1 -1];
trunkY = [0 0 2 2];
fill(trunkX, trunkY, [0.4 0.2 0.1], 'EdgeColor', 'none');
% === TREE LAYERS (3 triangular sections) ===
treeGreen = [0.1 0.5 0.1];
% Bottom layer
layer1X = [-6 6 0];
layer1Y = [2 2 7];
fill(layer1X, layer1Y, treeGreen, 'EdgeColor', [0 0.3 0], 'LineWidth', 2);
% Middle layer
layer2X = [-4.5 4.5 0];
layer2Y = [5 5 11];
fill(layer2X, layer2Y, treeGreen, 'EdgeColor', [0 0.3 0], 'LineWidth', 2);
% Top layer
layer3X = [-3 3 0];
layer3Y = [9 9 14];
fill(layer3X, layer3Y, treeGreen, 'EdgeColor', [0 0.3 0], 'LineWidth', 2);
% === STAR ON TOP ===
starPoints = 5;
outerR = 1.5;
innerR = 0.6;
starCenterY = 14.8;
theta = linspace(pi/2, pi/2 + 2*pi, 2*starPoints + 1);
radii = repmat([outerR innerR], 1, starPoints);
radii = [radii outerR];
starX = radii .* cos(theta);
starY = radii .* sin(theta) + starCenterY;
fill(starX, starY, [1 0.85 0], 'EdgeColor', [0.9 0.7 0], 'LineWidth', 2);
% === ORNAMENTS ===
ornamentColors = [1 0 0; 0 0 1; 1 0.8 0; 1 0 1; 0 1 1; 1 0.5 0];
ornamentX = [-3.5 -1 2 3.5 -2.5 1.5 0 -2 2.5 -1 1 0];
ornamentY = [3 3.5 3.5 3 5.5 5.5 4 6.5 7 10 10.5 12];
for i = 1:length(ornamentX)
colorIdx = mod(i-1, size(ornamentColors,1)) + 1;
theta = linspace(0, 2*pi, 50);
ornRadius = 0.4;
ox = ornRadius * cos(theta) + ornamentX(i);
oy = ornRadius * sin(theta) + ornamentY(i);
fill(ox, oy, ornamentColors(colorIdx,:), 'EdgeColor', 'w', 'LineWidth', 1);
% Add shine to ornaments
plot(ornamentX(i)-0.15, ornamentY(i)+0.15, '.', 'Color', 'w', 'MarkerSize', 8);
end
% === TINSEL/GARLAND (wavy lines) ===
tinselY1 = linspace(3, 6, 50);
tinselX1 = 0.3*sin(8*tinselY1) .* linspace(5, 2, 50);
plot(tinselX1, tinselY1, 'Color', [1 0.85 0.4], 'LineWidth', 2);
tinselY2 = linspace(6, 10, 40);
tinselX2 = 0.25*sin(8*tinselY2) .* linspace(3.5, 1.5, 40);
plot(tinselX2, tinselY2, 'Color', [1 0.85 0.4], 'LineWidth', 2);
% === PRESENTS ===
% Present 1 (red with gold ribbon)
fill([-5.5 -3 -3 -5.5], [-2.5 -2.5 -0.5 -0.5], [0.8 0.1 0.1], 'EdgeColor', 'k', 'LineWidth', 1);
fill([-4.5 -4 -4 -4.5], [-2.5 -2.5 -0.5 -0.5], [1 0.8 0], 'EdgeColor', 'none'); % vertical ribbon
fill([-5.5 -3 -3 -5.5], [-1.7 -1.7 -1.3 -1.3], [1 0.8 0], 'EdgeColor', 'none'); % horizontal ribbon
% Bow
fill([-4.8 -4.25 -4.25], [-0.5 -0.5 0.1], [1 0.8 0], 'EdgeColor', [0.8 0.6 0]);
fill([-4.25 -3.7 -4.25], [-0.5 -0.5 0.1], [1 0.8 0], 'EdgeColor', [0.8 0.6 0]);
% Present 2 (blue with white ribbon)
fill([3 5.5 5.5 3], [-2.5 -2.5 -1 -1], [0.1 0.3 0.8], 'EdgeColor', 'k', 'LineWidth', 1);
fill([4 4.5 4.5 4], [-2.5 -2.5 -1 -1], [1 1 1], 'EdgeColor', 'none');
fill([3 5.5 5.5 3], [-1.9 -1.9 -1.6 -1.6], [1 1 1], 'EdgeColor', 'none');
% Bow
fill([3.7 4.25 4.25], [-1 -1 -0.5], [1 1 1], 'EdgeColor', [0.8 0.8 0.8]);
fill([4.25 4.8 4.25], [-1 -1 -0.5], [1 1 1], 'EdgeColor', [0.8 0.8 0.8]);
% Present 3 (green with red ribbon)
fill([-1.5 1.5 1.5 -1.5], [-2.5 -2.5 0 0], [0.2 0.6 0.2], 'EdgeColor', 'k', 'LineWidth', 1);
fill([-0.25 0.25 0.25 -0.25], [-2.5 -2.5 0 0], [0.9 0.1 0.1], 'EdgeColor', 'none');
fill([-1.5 1.5 1.5 -1.5], [-1.5 -1.5 -1 -1], [0.9 0.1 0.1], 'EdgeColor', 'none');
% Bow
fill([-0.6 0 0], [0 0 0.6], [0.9 0.1 0.1], 'EdgeColor', [0.7 0 0]);
fill([0 0.6 0], [0 0 0.6], [0.9 0.1 0.1], 'EdgeColor', [0.7 0 0]);
% === SNOW ON GROUND ===
for i = 1:100
sx = rand*20 - 10;
sy = rand*0.8 - 2.8;
plot(sx, sy, '.', 'Color', 'w', 'MarkerSize', randi([3,8]));
end
% === FALLING SNOW ===
for i = 1:60
sx = rand*20 - 10;
sy = rand*18;
plot(sx, sy, '.', 'Color', [1 1 1 0.7], 'MarkerSize', randi([2,6]));
end
% === TITLE ===
text(0, 17, 'Merry Christmas!', 'Color', [1 0.9 0.9], ...
'FontSize', 18, 'FontWeight', 'bold', 'HorizontalAlignment', 'center');
hold off;
Mike Croucher
Mike Croucher on 16 Dec 2025 at 9:11
Which AI did you use?
Seth DeLand
Seth DeLand on 16 Dec 2025 at 14:16
I used Claude for this.
Seth DeLand
Seth DeLand on 16 Dec 2025 at 14:26
Here is my version from MATLAB Copilot, with kind regards to my friends in Denmark and Sweden.
Hans Scharler
Hans Scharler on 16 Dec 2025 at 14:10
MATLAB Copilot
Toshiaki Takeuchi
Toshiaki Takeuchi on 15 Dec 2025 at 19:20
Here is my attempt with Claude.
christmas_tree()
ans =
Figure (1) with properties: Number: 1 Name: '' Color: [0 0 0] Position: [100 100 800 800] Units: 'pixels' Use GET to show all properties
function fig = christmas_tree(varargin)
% CHRISTMAS_TREE Creates an interactive 3D Christmas tree visualization
%
% Syntax:
% fig = christmas_tree()
% fig = christmas_tree('Name', Value, ...)
%
% Parameters (Name-Value pairs):
% 'Height' - Tree height (default: 5)
% 'BaseRadius' - Base radius (default: 1.5)
% 'NumTiers' - Tree layers (default: 4)
% 'NumOrnaments' - Ornament count (default: 20)
% 'NumLights' - String lights (default: 50)
% 'TreeColor' - Base green [R G B] (default: [0.1, 0.5, 0.2])
% 'ShowStar' - Display star (default: true)
% 'ShowGarland' - Display garland (default: true)
%
% Example:
% fig = christmas_tree();
% fig = christmas_tree('Height', 6, 'NumOrnaments', 30);
% Parse input arguments
p = inputParser;
addParameter(p, 'Height', 5, @(x) isnumeric(x) && x > 0);
addParameter(p, 'BaseRadius', 1.5, @(x) isnumeric(x) && x > 0);
addParameter(p, 'NumTiers', 4, @(x) isnumeric(x) && x > 0);
addParameter(p, 'NumOrnaments', 20, @(x) isnumeric(x) && x >= 0);
addParameter(p, 'NumLights', 50, @(x) isnumeric(x) && x >= 0);
addParameter(p, 'TreeColor', [0.1, 0.5, 0.2], @(x) isnumeric(x) && length(x) == 3);
addParameter(p, 'ShowStar', true, @islogical);
addParameter(p, 'ShowGarland', true, @islogical);
parse(p, varargin{:});
% Extract parameters
tree_height = p.Results.Height;
base_radius = p.Results.BaseRadius;
num_tiers = p.Results.NumTiers;
num_ornaments = p.Results.NumOrnaments;
num_lights = p.Results.NumLights;
tree_color = p.Results.TreeColor;
show_star = p.Results.ShowStar;
show_garland = p.Results.ShowGarland;
% Setup figure and axes with dark background
fig = figure('Color', 'k', 'Position', [100, 100, 800, 800]);
ax = axes('Color', 'k', 'XColor', 'none', 'YColor', 'none', 'ZColor', 'none');
hold on;
% Tier parameters: [radius_multiplier, height_position]
tier_params = [
0.95, 0.15; % Bottom tier (widest)
0.70, 0.40; % Mid-lower
0.45, 0.60; % Mid-upper
0.20, 0.80; % Top tier (narrowest)
];
% Create trunk
trunk_height = tree_height * 0.15;
trunk_radius = base_radius * 0.10;
create_trunk(trunk_height, trunk_radius);
% Create tree tiers
for i = 1:size(tier_params, 1)
radius_mult = tier_params(i, 1);
height_pos = tier_params(i, 2);
tier_radius = base_radius * radius_mult;
tier_z = trunk_height + tree_height * height_pos;
tier_height = tree_height * 0.25; % Each tier height
create_tree_tier(tier_radius, tier_height, tier_z, tree_color);
end
% Add ornaments
if num_ornaments > 0
positions = generate_ornament_positions(num_ornaments, tree_height, ...
base_radius, trunk_height, tier_params);
ornament_colors = [
1.0, 0.0, 0.0; % Red
1.0, 0.84, 0.0; % Gold
0.0, 0.5, 1.0; % Blue
0.9, 0.9, 0.9; % Silver
0.7, 0.0, 0.7; % Purple
];
for i = 1:size(positions, 1)
color_idx = mod(i-1, size(ornament_colors, 1)) + 1;
place_ornament(positions(i,:), 0.08, ornament_colors(color_idx,:));
end
end
% Add string lights with glow
if num_lights > 0
[light_x, light_y, light_z, light_colors] = create_light_spiral(...
num_lights, tree_height, base_radius, trunk_height, 3.5);
% Main lights
scatter3(light_x, light_y, light_z, 100, light_colors, ...
'filled', 'MarkerFaceAlpha', 0.9);
% Glow halos (3 layers)
for j = 1:3
glow_scale = 1 + j*0.5;
alpha_glow = 0.3 / j;
scatter3(light_x, light_y, light_z, ...
100*glow_scale^2, light_colors, ...
'filled', 'MarkerFaceAlpha', alpha_glow);
end
end
% Add garland
if show_garland
[garland_x, garland_y, garland_z] = create_garland_spiral(...
200, tree_height, base_radius, trunk_height, 5);
plot3(garland_x, garland_y, garland_z, ...
'Color', [1, 0.84, 0.2], 'LineWidth', 3);
end
% Add star topper
if show_star
star_z = trunk_height + tree_height;
create_star(star_z, 0.3, [1, 0.84, 0]);
end
% Lighting setup (3 lights for dimensional appearance)
light('Position', [-4, -3, 8], ...
'Style', 'infinite', ...
'Color', [1.0, 0.95, 0.9]); % Warm white
light('Position', [5, 4, 3], ...
'Style', 'infinite', ...
'Color', [0.4, 0.4, 0.6]); % Cool fill
light('Position', [0, 0, -2], ...
'Style', 'infinite', ...
'Color', [0.2, 0.2, 0.3]); % Bottom light
% Material properties
material dull;
% Camera and view settings
axis equal off;
view([30, 20]);
camva(35);
% Interactive controls
title('Christmas Tree - Left click: Rotate | Right click: Pan | Scroll: Zoom', ...
'Color', 'w', 'FontSize', 12);
cameratoolbar('Show');
cameratoolbar('SetMode', 'orbit');
set(gcf, 'WindowButtonDownFcn', @mouseDown);
end
%% Helper Functions
function create_trunk(height, radius)
% Creates brown cylindrical trunk
[x, y, z] = cylinder(radius, 30);
z = z * height; % Scale to trunk height
trunk_color = [0.4, 0.25, 0.15]; % Brown
surf(x, y, z, ...
'EdgeColor', 'none', ...
'FaceColor', trunk_color, ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.4, ...
'DiffuseStrength', 0.7, ...
'SpecularStrength', 0.1);
end
function create_tree_tier(tier_radius, tier_height, z_offset, tree_color)
% Creates one tier of the tree with texture and color variation
n_points = 100; % High resolution for smooth appearance
% Create cone profile (wide at bottom, narrow at top)
theta = linspace(0, 2*pi, n_points);
height_profile = linspace(0, 1, 30); % Vertical resolution
% Build cone geometry with noise for branch-like texture
[THETA, H] = meshgrid(theta, height_profile);
% Radius decreases linearly from base to tip
R = tier_radius * (1 - H);
% Add random noise for branch texture
noise = 1 + 0.1 * randn(size(R));
R = R .* noise;
% Convert to Cartesian coordinates
X = R .* cos(THETA);
Y = R .* sin(THETA);
Z = z_offset - H * tier_height; % Tier hangs down from z_offset
% Create color gradient (darker at center, lighter at tips)
green_base = tree_color;
green_light = tree_color + [0.1, 0.2, 0.1]; % Lighter green
% Color based on height (darker at top/center, lighter at edges)
color_data = rescale(H, 0, 1);
% Render the tier
surf(X, Y, Z, color_data, ...
'EdgeColor', 'none', ...
'FaceColor', 'interp', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.4, ...
'DiffuseStrength', 0.7, ...
'SpecularStrength', 0.1);
% Apply green colormap for this surface
% Note: This will affect all surfaces, but we set it last
green_map = [linspace(green_base(1), green_light(1), 256)', ...
linspace(green_base(2), green_light(2), 256)', ...
linspace(green_base(3), green_light(3), 256)'];
colormap(green_map);
end
function positions = generate_ornament_positions(n_ornaments, tree_height, ...
base_radius, trunk_height, tier_params)
% Generates random positions for ornaments on the tree surface
% Avoids top 20% (star) and bottom 10% (trunk)
positions = zeros(n_ornaments, 3);
% Valid height range (middle 70%)
min_height_ratio = 0.15;
max_height_ratio = 0.75;
for i = 1:n_ornaments
% Random height within valid range
h_ratio = min_height_ratio + (max_height_ratio - min_height_ratio) * rand();
h = trunk_height + tree_height * h_ratio;
% Calculate radius at this height based on cone taper
% Find which tier this height corresponds to
r_at_h = base_radius * (1 - h_ratio) * 0.85; % Slightly inside tree surface
% Random angle around tree
theta = rand() * 2 * pi;
% Position on tree surface
positions(i,:) = [
r_at_h * cos(theta), ...
r_at_h * sin(theta), ...
h
];
end
end
function place_ornament(position, radius, color)
% Renders a single ornament sphere at the given position
[xs, ys, zs] = sphere(30);
surf(xs*radius + position(1), ...
ys*radius + position(2), ...
zs*radius + position(3), ...
'FaceColor', color, ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.3, ...
'DiffuseStrength', 0.6, ...
'SpecularStrength', 0.9); % High specular for shiny ornaments
end
function [x, y, z, colors] = create_light_spiral(n_lights, tree_height, ...
base_radius, trunk_height, n_wraps)
% Generates spiral path and colors for string lights
t = linspace(0, 1, n_lights);
% Calculate spiral coordinates (bottom to near-top)
height_pos = trunk_height + tree_height * (0.1 + 0.8*t);
angle = t * n_wraps * 2*pi;
% Radius follows cone taper
height_ratio = (height_pos - trunk_height) / tree_height;
radius_pos = base_radius * (1 - height_ratio) * 0.95;
% Light positions
x = radius_pos .* cos(angle);
y = radius_pos .* sin(angle);
z = height_pos;
% Light colors (warm white with variation)
colors = rand(n_lights, 3);
colors(:,1) = 0.8 + 0.2*rand(n_lights, 1); % More red
colors(:,2) = 0.6 + 0.4*rand(n_lights, 1); % Medium green
colors(:,3) = 0.3 + 0.7*rand(n_lights, 1); % Variable blue
end
function [x, y, z] = create_garland_spiral(n_points, tree_height, base_radius, ...
trunk_height, n_wraps)
% Generates spiral path for garland
t = linspace(0, 1, n_points);
% Calculate spiral coordinates
height_pos = trunk_height + tree_height * (0.15 + 0.8*t);
angle = t * n_wraps * 2*pi;
% Radius follows cone taper (slightly outside tree)
height_ratio = (height_pos - trunk_height) / tree_height;
radius_pos = base_radius * (1 - height_ratio) * 1.0;
% Garland positions
x = radius_pos .* cos(angle);
y = radius_pos .* sin(angle);
z = height_pos;
end
function create_star(star_z, star_size, star_color)
% Creates a 3D star with glow at tree top
% Create 5-pointed star profile
n_points = 5;
angles = linspace(0, 2*pi, n_points*2+1);
radii = repmat([star_size, star_size*0.5], 1, n_points);
radii = [radii, radii(1)]; % Close the shape
star_x = radii .* cos(angles);
star_y = radii .* sin(angles);
% Create front and back faces
z_front = star_z + 0.2;
z_back = star_z + 0.05;
% Front face
fill3(star_x, star_y, ones(size(star_x))*z_front, star_color, ...
'EdgeColor', 'none', ...
'FaceAlpha', 1.0, ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.8);
% Back face
fill3(star_x, star_y, ones(size(star_x))*z_back, star_color, ...
'EdgeColor', 'none', ...
'FaceAlpha', 1.0, ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.8);
% Add glow effect (multiple transparent layers)
[xs, ys, zs] = sphere(30);
for i = 1:8
glow_scale = star_size * (1 + i*0.15);
alpha_val = 0.3 / sqrt(i);
surf(xs*glow_scale, ys*glow_scale, zs*glow_scale + star_z + 0.125, ...
'EdgeColor', 'none', ...
'FaceColor', star_color, ...
'FaceAlpha', alpha_val, ...
'FaceLighting', 'none');
end
end
function mouseDown(src, ~)
% Mouse interaction callback
selType = get(src, 'SelectionType');
switch selType
case 'normal' % Left click - rotate
cameratoolbar('SetMode', 'orbit');
rotate3d on;
case 'alt' % Right click - pan
cameratoolbar('SetMode', 'pan');
pan on;
end
end
Hans Scharler
Hans Scharler on 15 Dec 2025 at 18:44 (Edited on 15 Dec 2025 at 18:45)
Yann Debray
Yann Debray on 15 Dec 2025 at 17:13
How about this (opus 4.5):
function christmasTree()
%CHRISTMASTREE Animated 3D Christmas tree with lights, ornaments, and snow
% Run christmasTree() to display a festive animated Christmas tree
% Create figure
fig = figure('Color', [0.05 0.05 0.15], 'Name', 'Merry Christmas!', ...
'NumberTitle', 'off', 'Position', [100 100 800 700]);
ax = axes('Parent', fig);
hold(ax, 'on');
% Set up 3D view
view(ax, 30, 20);
axis(ax, 'equal');
axis(ax, [-3 3 -3 3 0 6]);
set(ax, 'Color', [0.05 0.05 0.15], 'XColor', 'none', 'YColor', 'none', 'ZColor', 'none');
% Draw tree (stacked cones)
treeColor = [0.1 0.5 0.1];
drawTreeLayer(ax, 0, 0, 0.5, 2.0, 1.8, treeColor);
drawTreeLayer(ax, 0, 0, 1.8, 1.6, 1.5, treeColor * 1.1);
drawTreeLayer(ax, 0, 0, 2.8, 1.2, 1.3, treeColor * 1.2);
drawTreeLayer(ax, 0, 0, 3.6, 0.8, 1.0, treeColor * 1.3);
% Draw trunk
[xc, yc, zc] = cylinder(0.3, 20);
zc = zc * 0.5;
surf(ax, xc, yc, zc, 'FaceColor', [0.4 0.2 0.1], 'EdgeColor', 'none');
% Create ornaments
numOrnaments = 30;
ornamentColors = [1 0 0; 1 0.8 0; 0 0.5 1; 1 0 1; 0.8 0.8 0.8];
ornaments = struct('handle', {}, 'baseColor', {}, 'pos', {});
for i = 1:numOrnaments
theta = rand * 2 * pi;
h = 0.8 + rand * 3.2;
maxR = getTreeRadius(h);
r = (0.6 + 0.35 * rand) * maxR;
x = r * cos(theta);
y = r * sin(theta);
z = h;
colorIdx = randi(size(ornamentColors, 1));
baseColor = ornamentColors(colorIdx, :);
[xs, ys, zs] = sphere(10);
xs = xs * 0.12 + x;
ys = ys * 0.12 + y;
zs = zs * 0.12 + z;
hOrn = surf(ax, xs, ys, zs, 'FaceColor', baseColor, 'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', 'AmbientStrength', 0.5);
ornaments(i).handle = hOrn;
ornaments(i).baseColor = baseColor;
ornaments(i).pos = [x, y, z];
end
% Create string lights wrapping around tree
numLights = 60;
lights = struct('handle', {}, 'color', {}, 'phase', {});
lightColors = [1 1 0.3; 1 0.3 0.3; 0.3 1 0.3; 0.3 0.5 1; 1 0.5 1];
for i = 1:numLights
t = (i - 1) / numLights;
h = 0.6 + t * 3.8;
theta = t * 8 * pi;
r = getTreeRadius(h) * 0.95;
x = r * cos(theta);
y = r * sin(theta);
z = h;
colorIdx = mod(i-1, size(lightColors, 1)) + 1;
hLight = plot3(ax, x, y, z, '.', 'MarkerSize', 15, ...
'Color', lightColors(colorIdx, :));
lights(i).handle = hLight;
lights(i).color = lightColors(colorIdx, :);
lights(i).phase = rand * 2 * pi;
end
% Create star on top
starZ = 4.5;
starPoints = 5;
starOuter = 0.4;
starInner = 0.15;
starTheta = linspace(0, 2*pi, 2*starPoints + 1);
starR = repmat([starOuter starInner], 1, starPoints);
starR = [starR starOuter];
starX = starR .* cos(starTheta + pi/2);
starY = starR .* sin(starTheta + pi/2);
starZcoord = ones(size(starX)) * starZ;
hStar = fill3(ax, starX, starY, starZcoord, [1 0.85 0], ...
'EdgeColor', [1 0.9 0.3], 'LineWidth', 2);
% Star glow
[xs, ys, zs] = sphere(15);
hStarGlow = surf(ax, xs*0.3, ys*0.3, zs*0.3 + starZ, ...
'FaceColor', [1 1 0.5], 'EdgeColor', 'none', 'FaceAlpha', 0.3);
% Create snow particles
numSnow = 150;
snowX = (rand(numSnow, 1) - 0.5) * 8;
snowY = (rand(numSnow, 1) - 0.5) * 8;
snowZ = rand(numSnow, 1) * 6;
snowSpeed = 0.02 + rand(numSnow, 1) * 0.03;
snowDrift = (rand(numSnow, 1) - 0.5) * 0.02;
hSnow = plot3(ax, snowX, snowY, snowZ, '.', 'Color', [1 1 1], ...
'MarkerSize', 4);
% Add lighting
light(ax, 'Position', [5 5 10], 'Style', 'infinite');
light(ax, 'Position', [-5 -5 5], 'Style', 'infinite', 'Color', [0.3 0.3 0.5]);
% Add title
title(ax, '🎄 Merry Christmas! 🎄', 'Color', [0.9 0.9 0.9], ...
'FontSize', 20, 'FontWeight', 'bold');
% Animation loop
frame = 0;
while ishandle(fig)
frame = frame + 1;
t = frame * 0.05;
% Twinkle lights
for i = 1:length(lights)
brightness = 0.5 + 0.5 * sin(t * 3 + lights(i).phase);
newColor = lights(i).color * brightness;
markerSize = 10 + 10 * brightness;
set(lights(i).handle, 'Color', newColor, 'MarkerSize', markerSize);
end
% Subtle ornament shimmer
for i = 1:length(ornaments)
shimmer = 0.85 + 0.15 * sin(t * 2 + i);
newColor = min(1, ornaments(i).baseColor * shimmer);
set(ornaments(i).handle, 'FaceColor', newColor);
end
% Rotate star
starTheta = linspace(0, 2*pi, 2*starPoints + 1);
starR = repmat([starOuter starInner], 1, starPoints);
starR = [starR starOuter];
rotation = t * 0.5;
starX = starR .* cos(starTheta + pi/2 + rotation);
starY = starR .* sin(starTheta + pi/2 + rotation);
set(hStar, 'XData', starX, 'YData', starY);
% Star glow pulse
glowScale = 0.3 + 0.1 * sin(t * 2);
set(hStarGlow, 'XData', xs*glowScale, 'YData', ys*glowScale);
% Animate snow
snowZ = snowZ - snowSpeed;
snowX = snowX + snowDrift .* sin(t + snowX);
% Reset snow that falls below ground
fallen = snowZ < 0;
snowZ(fallen) = 6;
snowX(fallen) = (rand(sum(fallen), 1) - 0.5) * 8;
snowY(fallen) = (rand(sum(fallen), 1) - 0.5) * 8;
set(hSnow, 'XData', snowX, 'YData', snowY, 'ZData', snowZ);
% Slow camera rotation
view(ax, 30 + t * 5, 20);
drawnow;
pause(0.03);
end
end
function drawTreeLayer(ax, cx, cy, baseZ, radius, height, color)
% Draw a cone-shaped tree layer
[theta, h] = meshgrid(linspace(0, 2*pi, 40), linspace(0, 1, 20));
r = radius * (1 - h);
% Add some irregularity for natural look
r = r .* (1 + 0.1 * sin(8 * theta));
x = cx + r .* cos(theta);
y = cy + r .* sin(theta);
z = baseZ + h * height;
surf(ax, x, y, z, 'FaceColor', color, 'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', 'AmbientStrength', 0.4);
end
function r = getTreeRadius(h)
% Get approximate tree radius at height h
if h < 0.5
r = 0;
elseif h < 2.3
r = 2.0 * (1 - (h - 0.5) / 1.8);
elseif h < 3.3
r = 1.6 * (1 - (h - 1.8) / 1.5);
elseif h < 4.1
r = 1.2 * (1 - (h - 2.8) / 1.3);
else
r = 0.8 * (1 - (h - 3.6) / 1.0);
end
r = max(0.2, r);
end
David
David on 15 Dec 2025 at 17:50
I like how the star is positioned horizontally at the top :)
Seth DeLand
Seth DeLand on 15 Dec 2025 at 19:52
Reminds me of a launch star in Super Mario Galaxy.
Vasilis Bellos
Vasilis Bellos on 16 Dec 2025 at 0:24
That was my first thought as well!