- /
- 
        You get a cube! And you get a cube! And...
        on 1 Nov 2024
        
        
 
    - 43
- 228
- 0
- 3
- 1947
This is really just a performance update. I was not happy with the execution times and learned about Persistent variables from other entries so I improved it. 
Now that it is fast I could make more of them.... Hans Scharler, you wanted one; Take as many as you want! 
function drawframe(f)
persistent S V f1 f2
%% 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=['pzxzpyxzpzxyy';'0444021303124';'0npn0ppp0nnnp'];
%% First frame initiation
if f == 1
    %% Set figure window properties
    f2=figure(2); % Multi cube window
    f1=figure(1); % Base rubix figure window
    lim=[-1,1]*2.4;
    hold on
    xlim(lim);
    ylim(lim);
    zlim(lim);
    axis off
    pbaspect([1,1,1])
    %% 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
    % By looping backwards we skip the need for explicit preallocation for
    % speed and thus save characters.
    for i=55:-1:1
        I{i}=reshape(y(n*(i-1)+1:n*i),[s,s,3]);
    end
    %% Initiate surfaces
    % Surfaces
    S=initSurf(I);
    % Verticies
    % V = [v1 v2 v3 v4] X [Faces] X [x y z]
    V=cell2mat(cellfun(@(x)reshape([x.XData,x.YData,x.ZData],4,1,3),S,...
        UniformOutput=0));
    % V = [x y z]  X [Faces] X [v1 v2 v3 v4]
    V=permute(V,[3,2,1]);
end
%% Prevent ears from bleeding
if f==96
    %     P C1    C2     C3     F2     G2
    freq=[0 65.41 130.81 261.63 174.61 196];
    note=[2 3 4 1 2 3 4 3 2 3 4 1 2 3 4 6];
    fs=44100;
    y=[];
    for i=note
        y=[y,.5*sin(2*pi*freq(i)*(0:1/fs:1))];
    end
    audiowrite('audio.wav',y,fs)
end
%% Timing and frame variables
figure(f1)
% Frames per move, FPM
FPM=floor(96/size(MS,2));
AngSpd=90/FPM;
view(45+180*f/96,35.2644);
%Pause for remaining time if timing issues arise
if f>FPM*size(MS,2)
    return
end
% Determine which move in the sequence we are performing
c=ceil(AngSpd*f/90);
%% Set the rotation matrix
% Direction of rotation
if MS(3,c)=='n'
    dir=-1;
elseif MS(3,c)=='p'
    dir=1;
end
%Choice of Rotation Matrix
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
        return
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,:));
%% Update the surface coordinate data
% We need to update the data of relevant faces
for i=F
    S{i}.XData=reshape(V(1,i,:),2,2);
    S{i}.YData=reshape(V(2,i,:),2,2);
    S{i}.ZData=reshape(V(3,i,:),2,2);
end
%% DrawRubix
drawnow
%% Multi Cube
% So... I was going to make an enire other cube to rotate to prove how much
% faster the program is executing. But it was a pain so I will be cheating
% here...
if f>1
Images=cell(20,1);
Images(:) = {imresize(frame2im(getframe),[345,310],Method='bicubic')};
figure(f2)
montage(Images)
f2.Position=[0 0 600 600];    
drawnow
end
end
function S = initSurf(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
S=cell(1,162);%Preallocation
for C=0:2
    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 0 %x
                        x=a+pl+d;
                        y=[3,3;2,2]-i;
                        z=b-j;
                    case 1 %y
                        x=c+i;
                        y=a+pl+d;
                        z=b-j;
                    case 2 %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


 
