Использование OpenGL в Matlab для получения буфера глубины

Ive задал аналогичный вопрос раньше и не смог найти прямой ответ.

может ли кто-нибудь предоставить пример кода для извлечения буфера глубины рендеринга объекта в фигуру в Matlab?

Итак, скажем, я загружаю файл obj или даже просто простой вызов surf, рендеринг и теперь хочу добраться до его буфера глубины, а затем какой код сделает это для меня, используя как Matlab, так и OpenGL. Т. е. как настроить это, а затем получить доступ к фактическим данным?

Я по существу хочу иметь возможность использовать мощные функции построения Matlabs, а затем иметь доступ к базовому графическому контексту для получения буфера глубины.

Примечание: bounty указывает JOGL, но это не обязательно. Любой код, который действует как указано выше и может предоставить мне буфер глубины после его запуска в Matlab, достаточен)

2 ответов


depthmap thing

сегодня я пошел пить с моими коллегами, и после пяти пива и некоторых текиллы я нашел этот вопрос и подумал: "есть у вас!"Поэтому я некоторое время боролся, но потом нашел простое решение, используя MEX. Я предположил, что контекст OpenGL, созданный последним окном, может быть оставлен активным и, следовательно, может быть доступен из "C", если сценарий выполняется в том же потоке.

Я создал простую программу "C", которая вызывает одну функцию matlab, называется "testofmyfilter", который строит частотную характеристику фильтра (это был единственный скрипт, который у меня был под рукой). Это отображается с помощью OpenGL. Затем программа использует glGetViewport() и glReadPixels () для доступа к буферам OpenGL. Затем он создает матрицу, заполняет ее значениями глубины и передает ее второй функции, называемой "trytodisplaydepthmap". Он просто отображает depthmap с помощью функции imshow. Обратите внимание, что функция MEX также может возвращать значения, поэтому, возможно, постобработка не должна быть другой функцией, но я не в состоянии понять, как это делается. Хотя это должно быть тривиально. Сегодня я впервые работаю с мекс.

без дальнейших задержек, есть исходные коды, которые я использую:

testofmyfilter.м

imp = zeros(10000,1);
imp(5000) = 1;
% impulse

[bwb,bwa] = butter(3, 0.1, 'high');
b = filter(bwb, bwa, imp);
% filter impulse by the filter

fs = 44100; % sampling frequency (all frequencies are relative to fs)
frequency_response=fft(b); % calculate response (complex numbers)
amplitude_response=20*log10(abs(frequency_response)); % calculate module of the response, convert to dB
frequency_axis=(0:length(b)-1)*fs/length(b); % generate frequency values for each response value
min_f=2;
max_f=fix(length(b)/2)+1; % min, max frequency

figure(1);
lighting gouraud
set(gcf,'Renderer','OpenGL')

semilogx(frequency_axis(min_f:max_f),amplitude_response(min_f:max_f),'r-') % plot with logarithmic axis using red line
axis([frequency_axis(min_f) frequency_axis(max_f) -90 10])  % set axis limits

xlabel('frequency [Hz]');
ylabel('amplitude [dB]'); % legend

grid on % draw grid

свиньяответ правильный. Вот немного отформатированная и более простая версия, которая является кросс-платформенной.

создайте файл с именем mexGetDepth.c

#include "mex.h"   

#define GL_VIEWPORT                       0x0BA2
#define GL_DEPTH_COMPONENT                0x1902
#define GL_FLOAT                          0x1406

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    int viewport[4], i, x, y;
    int colLen;
    float *data;
    double *matrix;

    glGetIntegerv(GL_VIEWPORT, viewport);
    data = (float*)malloc(viewport[2] * viewport[3] * sizeof(float));
    glReadPixels(0, 0, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_FLOAT, data);

    plhs[0] = mxCreateNumericMatrix(viewport[3], viewport[2], mxDOUBLE_CLASS, mxREAL);
    matrix = mxGetPr(plhs[0]);
    colLen = mxGetM(plhs[0]);

    for(x = 0; x < viewport[2]; ++ x) {
        for(y = 0; y < viewport[3]; ++ y)
            matrix[x * colLen + y] = data[x + (viewport[3] - 1 - y) * viewport[2]];
    }

    free(data);
    return;
}

тогда, если вы на компиляции windows, используя

mex mexGetDepth.c "path to OpenGL32.lib"

или если вы находитесь в системе nix

mex mexGetDepth.c "path to opengl32.a"

затем запустите следующий небольшой скрипт, чтобы проверить новую функцию

peaks;
figure(1);
depthData=mexGetDepth;
figure
imshow(depthData);