Rendering a large 3D dataset with a scatter plot

I am running a simulation in MATLAB in which I have a large 3D dataset that changes every time step. I am trying to render data using a 3D scatter plot with points that traverse different locations, sizes, colors, and transparency levels as the simulation continues. Size and color information is redundant.

Rendering and rotating a shape in MATLAB is slow and choppy. My computer has a 4 GHz i7-4790 processor and an NVIDIA GeForce GTX 750 Ti graphics card. I am using Matlab R2016a on Windows 7. I checked the MATLAB OpenGL settings and the hardware support level is full. (OpenGL hardware is needed for transparency.) Also, I track my GPU usage with GPU-Z , and when building and rotating, GPU load peaks are only 25-30%.

Here's my sample code:

load sample_data2
channels_matrix = cat(1, channels{:});
num_channels = length(channels);
channel_lengths = cellfun(@(x) size(x, 1), channels);

figure(1);
for i = 1:num_channels
    g = plot3(channels{i}(:, 1), channels{i}(:, 2), channels{i}(:, 3), 'k');
    set(g, 'LineWidth', 1.5)
    hold on;
    text(channels{i}(1, 1), channels{i}(1, 2), channels{i}(1, 3), num2str(i))
end
caxis([0 1])
colorbar
drawnow

numDivisions = 8;
ptsPerDivision = numel(grid_x)/numDivisions;
T = 1000;
numplotpts = 2E4;
for t = 1:T
    plot_signal = nan(size(grid_x));
    plot_signal(sort(randsample(numel(grid_x), numplotpts))) =...
        sort(rand(numplotpts, 1));
    tic
    for i = 1:numDivisions
        temp = plot_signal(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        yplot = grid_y(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        xplot = grid_x(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        zplot = grid_z(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        if t == 1
            h(i) = scatter3(yplot(~isnan(temp)), xplot(~isnan(temp)),...
                zplot(~isnan(temp)), 50*temp(~isnan(temp)), temp(~isnan(temp)), ...
                'filled', 'MarkerFaceAlpha', exp(-i)^0.25);
        else
            h(i).XData = yplot(~isnan(temp));
            h(i).YData = xplot(~isnan(temp));
            h(i).ZData = zplot(~isnan(temp));
            h(i).SizeData = 50*temp(~isnan(temp));
            h(i).CData = temp(~isnan(temp));
        end
    end
    drawnow
    toc
end

      

and here is the link to data . Is there a way to speed up rendering and make rotation smoother? I noticed that fixing the size of all data points to a single scalar makes rendering and rotation much faster. Is it possible to keep the size as it is in the code and still have the shape render and rotate quickly?

Edit : A related question I posted.

+3


source to share


2 answers


It looks like the function timer

is a good place to try further to understand the meaning of your simulation, and then create an AVI once you are satisfied with how things look.



MATLAB has got excellent documentation for it with various sequential call options and the spacing between them. Check properties ExecutionMode

and Period

.

+1


source


I'm not sure if this will solve the whole problem, but as a first step, I suggest taking all calculations out of the loop that is used for drawing. Here's a suggestion on how to do it:



load sample_data2
clf
channels_matrix = cat(1, channels{:});
num_channels = length(channels);
channel_lengths = cellfun(@(x) size(x, 1), channels);

figure(1);
for k = 1:num_channels
    g = plot3(channels{k}(:, 1), channels{k}(:, 2), channels{k}(:, 3), 'k');
    set(g, 'LineWidth', 1.5)
    hold on;
    text(channels{k}(1, 1), channels{k}(1, 2), channels{k}(1, 3), num2str(k))
end
caxis([0 1])
colorbar
drawnow

numDivisions = 8;
ptsPerDivision = numel(grid_x)/numDivisions;
T = 1000;
numplotpts = 2E4;

% -> chnages starts here:

% first loop for creating random indices
plot_signal = nan(size(grid_x));
rand_numplotpts =sort(rand(numplotpts,T),1);
rand_inds = zeros(numplotpts,T);
for t = 1:T % one loop for creating random indices
    rand_inds(:,t) = sort(randperm(numel(grid_x),numplotpts));
end
plot_signal(rand_inds(:,t)) = rand_numplotpts(:,t);

% second loop for drawing the first instance:
for k = 1:numDivisions
    temp = plot_signal(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
    yplot = grid_y(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
    xplot = grid_x(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
    zplot = grid_z(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
    h(k) = scatter3(yplot(~isnan(temp)), xplot(~isnan(temp)),...
        zplot(~isnan(temp)), 50*temp(~isnan(temp)), temp(~isnan(temp)), ...
        'filled', 'MarkerFaceAlpha', exp(-k)^0.25);
end

% third loop to calculate all timesteps:
[X,Y,Z,S,C] = deal(nan(size(temp,1),numDivisions,T));
for t = 2:T 
    plot_signal(rand_inds(:,t)) = rand_numplotpts(:,t);
    for k = 1:numDivisions
        temp = plot_signal(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        yplot = grid_y(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        xplot = grid_x(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        zplot = grid_z(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        non_nan_inds = ~isnan(temp);
        inds = 1:sum(non_nan_inds);
        X(inds,k,t) = yplot(non_nan_inds);
        Y(inds,k,t) = xplot(non_nan_inds);
        Z(inds,k,t) = zplot(non_nan_inds);
        S(inds,k,t) = 50*temp(non_nan_inds);
        C(inds,k,t) = temp(non_nan_inds);
    end
end

% forth loop to draw all data:
for t = 2:T
    for k = 1:numDivisions
        h(k).XData = Y(:,k,t);
        h(k).YData = X(:,k,t);
        h(k).ZData = Z(:,k,t);
        h(k).SizeData = S(:,k,t);
        h(k).CData = C(:,k,t);
        drawnow
    end
end

      

0


source







All Articles