- /
-
Mathworks Cube!
on 29 Oct 2024
- 53
- 341
- 1
- 10
- 1810
This version has more function, better code, and less characters.
Get your Matworks cube at mathworksmerch.com for the low-low price of $10.00!
function drawframe(f)
clf
%% Movement sequence, MS
% (1,:) Which axis x, y, z, or (pause p) to rotate around
% (2,:) Which row to rotate 1, 2, 3, or 4 for all. Any character if pause.
% (3,:) Which direction to rotate, n if negative direction, p for positive
% Change to alter moves made. The function tries to fit all moves within 4s
% If timing issues arise all moves are executed and then a pause untill the
% time runs out
MS=['zxzpyxzpzxyy';'444021303124';'npn0ppp0nnnp'];
%% Set figure window properties
figure(1)
lim = [-1,1]*2.4;
hold on
xlim(lim);
ylim(lim);
zlim(lim);
axis off
pbaspect([1,1,1])
view(45+180*f/96,30);
%% Timing and frame variables
% Frames per move, FPM
FPM=floor(96/size(MS,2));
AngSpd=90/FPM;
%Pause for remaining time if timing issues arise
if f>FPM*size(MS,2)
f=FPM*size(MS,2);
end
%% Get Textures encoded in audio
y=audioread("audio.wav");
y=reshape(y,[],1);
% Texture size, s
s=28;
n=s*s*3;% Number of elements in image
% Create the textures of each face
for i=1:55
I{i}=reshape(y(n*(i-1)+1:n*i),[s,s,3]);
end
%% Initiate surfaces
S=initCoords(I);
% Verticies
V=cell2mat(cellfun(@(x)reshape([x.XData,x.YData,x.ZData],4,1,3),S,...
UniformOutput=0));
V=permute(V,[3,2,1]);
%Counter to keep track of which move we are performing
c=1;
for frame = 1:f
%% Set the rotation matrix
if MS(3,c)=='n'
dir=-1;
elseif MS(3,c)=='p'
dir=1;
end
% Condition to swap to next move, nm
nm=~mod(AngSpd*frame,90);
switch MS(1,c)
% Rotation matrix, R
% Vertice data in the axis of rotation, D
case 'x'
R=[1,0,0;
0,cosd(dir*AngSpd),-sind(dir*AngSpd);
0,sind(dir*AngSpd),cosd(dir*AngSpd)];
D=V(1,:,:);
case 'y'
R=[cosd(dir*AngSpd),0,sind(dir*AngSpd);
0,1,0;
-sind(dir*AngSpd),0,cosd(dir*AngSpd)];
D=V(2,:,:);
case 'z'
R=[cosd(dir*AngSpd),-sind(dir*AngSpd),0;
sind(dir*AngSpd),cosd(dir*AngSpd),0;
0,0,1];
D=V(3,:,:);
case 'p' %pause
if nm
c=c+1;
end
continue
end
%% Find the indices for the faces to rotate
D=squeeze(D)';
% Index of faces to include in rotation, F
if MS(2,c)=='1'
F=find(sum(D>=.5-10^-5,1)==4);
elseif MS(2,c)=='2'
F=find(sum(D<=.5+10^-5&D>=-.5-10^-5,1)==4);
elseif MS(2,c)=='3'
F=find(sum(D<=-.5+10^-5,1)==4);
elseif MS(2,c)=='4'
F=1:size(S,2);
end
%% Perform the rotation for each of the four vertices in a face
V(:,F,:)=pagemtimes(R,V(:,F,:));
if nm
c=c+1;
end
end
%% Update the surface coordinate data
V=permute(V,[3,2,1]);
% We need to update the data in all nodes or the camera rotation effect
% will not persist, Otherwise i would just have updated the data of
% relevant faces
for i=1:162
S{i}.XData=reshape(V(1:4,i,1),2,2);
S{i}.YData=reshape(V(1:4,i,2),2,2);
S{i}.ZData=reshape(V(1:4,i,3),2,2);
end
%% Draw
drawnow
%% Prevent ears from bleeding
if f==96
%P C1 C2 C3 F2 G2
freq=[0 65.41 130.81 261.63 174.61 196];
y=[];
for i=[2 3 4 1 2 3 4 3 2 3 4 1 2 3 4 6]
y=[y,.5*sin(2*pi*freq(i)*(0:1/(44100):1))];
end
audiowrite('audio.wav',y,44100)
end
end
function [S] = initCoords(I)
% shorthand some matrixes to save some characters
a=[0,0;0,0];
b=[2,3;2,3];
c=[0,0;1,1];
% Unfortunately we need to create every surface by itself if we want to
% texture them individually and not have any morphing geometry during plot
% We loop across:
% The 3 coordinate axes, C
% The 6 planes of the cube, p (inside planes count to not make it hollow)
% The 3 columns on each side of the cube, i
% The 3 rows on each side of the cube, j
t=1;%Counter for selection of textures
v=1;%Counter for keeping track of loop iteration
for C=1:3
for p=0:5
for i=0:2
for j=0:2
d=0;
if p==0||p==5 % First or last plane -> Textures!
T=I{t};
t=t+1;
else
% Plane inside the cube, we texture these black.
% To be able to "select" plane faces easily, we
% separate them slightly from eachother with a delta, d
if mod(p,2)
d=-10^-4;
else
d=+10^-4;
end
T=I{end};
end
pl=round(p/2);
%Determine coordinates based on axis and plane
switch C
case 1 %x
x=a+pl+d;
y=[3,3;2,2]-i;
z=b-j;
case 2 %y
x=c+i;
y=a+pl+d;
z=b-j;
case 3 %z
x=c+i;
y=[1,0;1,0]+j;
z=a+pl+d;
end
% Create, texture, and store the individual surface objects
% Unfortunately we need seperate surfaces as we do not want
% them to stay connected to stationary faces when rotating.
S{v}=surf(x-1.5,y-1.5,z-1.5,T,FaceColor='texturemap');
v=v+1;
end
end
end
end
end