在Matlab中利用OpenGL得到深度缓冲 [英] Using OpenGL in Matlab to get depth buffer

查看:693
本文介绍了在Matlab中利用OpenGL得到深度缓冲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

香港专业教育学院之前问过类似的问题,并没有设法找到一个直接的<一个href="http://stackoverflow.com/questions/5963193/matlab-z-buffer-for-simulating-kinect">answer.

Ive asked a similar question before and didnt manage to find a direct answer.

可能有人用于提取对象的渲染深度缓冲到Matlab中的人物提供样品code?

Could someone provide sample code for extracting the depth buffer of the rendering of an object into a figure in Matlab?

因此​​,可以说我加载OBJ文件,甚至只是一个简单的冲浪电话,渲染它,现在想获得它的深度缓冲凭什么code将同时使用Matlab和OpenGL的为我做的。即我该如何设置此,然后访问实际的数据?

So lets say I load an obj file or even just a simple surf call, render it and now want to get to its depth buffer then what code will do that for me using both Matlab and OpenGL. I.e. how do I set this up and then access the actual data?

我基本上希望能够使用Matlabs强大的绘图功能,然后才能够访问底层图形上下文获取深度缓冲了。

I essentially want to be able to use Matlabs powerful plotting functions and then be able to access the underlying graphics context for getting the depth buffer out.

注:赏金指定JOGL,但不是必须的。任何code充当上面,并且可以在Matlab中运行它之后我提供深度缓冲就足够了)

NOTE: The bounty specifies JOGL but that is not a must. Any code which acts as above and can provide me with the depth buffer after running it in Matlab is sufficient)

推荐答案

今天,我和我的同事们喝酒,经过五年的啤酒和一些tequillas我发现这个问题,并认为,有爱你!所以我挣扎了一段时间,但后来我发现使用MEX一个简单的解决方案。我的理论是OpenGL的情况下,由最后一个窗口创建,可以留待活跃,因此可以从C访问,如果脚本运行在同一个线程。

Today, I went drinking with my colleagues, and after five beers and some tequillas I found this question and thought, "have at ya!" So I was struggling for a while but then I found a simple solution using MEX. I theorized that the OpenGL context, created by the last window, could be left active and therefore could be accessible from "C", if the script ran in the same thread.

我创建了一个简单的C程序,调用一次MATLAB的功能,被称为testofmyfilter,它绘制的过滤器(这是唯一的剧本我已在手)的频率响应。这是使用的OpenGL呈现。然后,该程序使用glGetViewport()和glReadPixels()来获取到OpenGL的缓冲区。然后它创建一个矩阵,具有深度值填充它,并将其传递给第二功能,被称为trytodisplaydepthmap。它只是显示使用imshow函数depthmap。请注意,MEX功能被允许返回值一样,所以也许后期处理也不会是另一个函数,但我在任何状态下能够理解它是如何做。应该是微不足道的,但。我正与墨西哥在今天第一次。

I created a simple "C" program which calls one matlab function, called "testofmyfilter" which plots frequency response of a filter (that was the only script I had at hand). This is rendered using OpenGL. Then the program uses glGetViewport() and glReadPixels() to get to the OpenGL buffers. Then it creates a matrix, fills it with the depth values, and passes it to the second function, called "trytodisplaydepthmap". It just displays the depthmap using the imshow function. Note that the MEX function is allowed to return values as well, so maybe the postprocessing would not have to be another function, but I'm in no state to be able to understand how it's done. Should be trivial, though. I'm working with MEX for the first time today.

如果没有进一步的延迟,有源$ C ​​$ CS我用:

Without further delay, there are source codes I used:

testofmyfilter.m

testofmyfilter.m

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

test.c的

test.c

//You can include any C libraries that you normally use
#include "windows.h"
#include "stdio.h"
#include "math.h"
#include "mex.h"   //--This one is required

extern WINAPI void glGetIntegerv(int n_enum, int *p_value);

extern WINAPI void glReadPixels(int     x, 
    int     y, 
    int     width, 
    int     height, 
    int     format, 
    int     type, 
    void *      data);

#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;
    mxArray *arg[1];

    mexCallMATLAB(0, NULL, 0, NULL, "testofmyfilter");
    // call an .m file which creates OpenGL window and draws a plot inside

    glGetIntegerv(GL_VIEWPORT, viewport);
    printf("GL_VIEWPORT = [%d, %d, %d, %d]\n", viewport[0], viewport[1], viewport[2], viewport[3]);
    // print viewport dimensions, should be [0, 0, m, n]
    // where m and n are size of the GL window

    data = (float*)malloc(viewport[2] * viewport[3] * sizeof(float));
    glReadPixels(0, 0, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_FLOAT, data);
    // alloc data and read the depth buffer

    /*for(i = 0; i < 10; ++ i)
        printf("%f\n", data[i]);*/
    // debug

    arg[0] = mxCreateNumericMatrix(viewport[3], viewport[2], mxDOUBLE_CLASS, mxREAL);
    matrix = mxGetPr(arg[0]);
    colLen = mxGetM(arg[0]);
    printf("0x%08x 0x%08x 0x%08x %d\n", data, arg[0], matrix, colLen); // debug
    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]];
    }
    // create matrix, copy data (this is stupid, but matlab switches
    // rows/cols, also convert float to double - but OpenGL could have done that)

    free(data);
    // don't need this anymore

    mexCallMATLAB(0, NULL, 1, arg, "trytodisplaydepthmap");
    // pass the array to a function (returnig something from here
    // is beyond my understanding of mex, but should be doable)

    mxDestroyArray(arg[0]);
    // cleanup

    return;
}

trytodisplaydepthmap.m:

trytodisplaydepthmap.m:

function [] = trytodisplaydepthmap(depthMap)

figure(2);
imshow(depthMap, []);
% see what's inside

保存所有这些到同一个目录,编译test.c的有(键入Matlab的控制台):

Save all of these to the same directory, compile test.c with (type that to Matlab console):

mex test.c Q:\MATLAB\R2008a\sys\lcc\lib\opengl32.lib

在哪里。问:\ MATLAB \ R2008a \ SYS \ LCC \ lib目录\ opengl32.lib是路径opengl32.lib文件

Where "Q:\MATLAB\R2008a\sys\lcc\lib\opengl32.lib" is path to "opengl32.lib" file.

和仅仅通过键入测试在MATLAB控制台终于执行了这一切。它应调出带有滤波器频率响应的一个窗口,并与深度缓冲区中的另一窗口。注意前后缓冲区被交换的时刻Ccode读取深度缓冲,所以它可能需要运行该脚本两次得到任何结果(如此前缓冲区现在包含的结果互换背部再次缓冲,并且深度可被读出)。这可以通过自动C来完成,或者你可以尝试包括的getFrame(GCF);在脚本的末尾(即回读从OpenGL的,以及因此交换缓冲区为你,什么的)。

And finally execute it all by merely typing "test" in matlab console. It should bring up a window with filter frequency response, and another window with the depth buffer. Note the front and back buffers are swapped at the moment "C" code reads the depth buffer, so it might be required to run the script twice to get any results (so the front buffer which now contains the results swaps with back buffer again, and the depth can be read out). This could be done automatically by "C", or you can try including getframe(gcf); at the end of your script (that reads back from OpenGL as well so it swaps the buffers for you, or something).

这在Matlab 7.6.0.324(R2008a)为我工作。该脚本运行,并吐出了以下工作:

This works for me in Matlab 7.6.0.324 (R2008a). The script runs and spits out the following:

>>test
GL_VIEWPORT = [0, 0, 560, 419]
0x11150020 0x0bd39620 0x12b20030 419

当然它显示的图像。注意深度缓冲范围取决于Matlab的,并且可以是相当高,所以使得所产生的图像中的任何感可能并不简单。

And of course it displays the images. Note the depth buffer range depends on Matlab, and can be quite high, so making any sense of the generated images may not be straightforward.

这篇关于在Matlab中利用OpenGL得到深度缓冲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆