1

私は現在、プログラムIgorPro用のプラグインをC++で構築しています。このプラグインは、ポイントの3つの配列(X、Y、Z)を取り、データのピクセル値を含む行列を返します(float array [windowsize] [windowsize])。

私はすでにVBOを使用してOpenGL(glew)でソリューションを開発しましたが、それは最適なソリューションではないと感じています。

1)FBOまたはPBOでオフスクリーンレンダリングを使用する必要があると思いますか?できるだけ速く走らせたいです。

2)また、glutMainLoopを1回だけ実行したいと思います。FreeGLUTに変更する必要がありますか?

/*  
        RenderTriangle.c
*/
#include "VC10\triangulation.h"
#include "XOPStandardHeaders.h"         // Include ANSI headers, Mac headers, IgorXOP.h, XOP.h and XOPSupport.h
#include "glui.h"

// Prototypes
HOST_IMPORT int main(IORecHandle ioRecHandle);

// Global Variables
const int windowSize = 512;
GLuint ID;
int size,el_size;
float* waveX=NULL;
float* waveY=NULL;
float* waveZ=NULL;
waveHndl waveH;

// Custom error codes
#define OLD_IGOR 1 + FIRST_XOP_ERR
#define NON_EXISTENT_WAVE 2 + FIRST_XOP_ERR
#define REQUIRES_SP_OR_DP_WAVE 3 + FIRST_XOP_ERR

#pragma pack(2)     // All structures passed to Igor are two-byte aligned.
typedef struct FitParams {
    waveHndl waveX; 
    waveHndl waveY;
    waveHndl waveZ;
    double result;
} FitParams, *FitParamsPtr;
#pragma pack()      // Restore default structure alignment

// Prototypes of the OpenGL callbacks
void init(void);
void display(void);
void idle(void);

void init(void){

    float z_val=0;
    int point=0;

    //Loading data from the text files and applying the Delaunay algorithm
    triangulateio tri_data=triangulationWave(waveX,waveY,waveZ);
    vector<float>data_vector(tri_data.numberoftriangles*3*6); //3 points with 6 coordinates (position and color)

    size=data_vector.size();

    double zMin=tri_data.pointattributelist[N_ELEMENTS],zMax=tri_data.pointattributelist[N_ELEMENTS+1];
    for (int i_tri = 0; i_tri < tri_data.numberoftriangles; i_tri++) {

        for (int i_point = 0; i_point < 3; i_point++) {

            z_val=tri_data.pointattributelist[tri_data.trianglelist[i_tri * 3 + i_point]];
            z_val=1-((z_val-zMin)/(zMax-zMin)); //normalize and invertion

            point=6*(i_tri *3 + i_point);

            data_vector[point+0]=tri_data.pointlist[2*tri_data.trianglelist[i_tri * 3 + i_point]];
            data_vector[point+1]=tri_data.pointlist[2*tri_data.trianglelist[i_tri * 3 + i_point]+1];
            data_vector[point+2]=z_val;
            data_vector[point+3]=z_val;
            data_vector[point+4]=z_val;
            data_vector[point+5]=z_val;
        }
    }

    glewInit();

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    glDepthRange(-2.0f, 2.0f);
    glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
    glShadeModel(GL_SMOOTH);
    glEnableClientState(GL_VERTEX_ARRAY);
    glGenBuffers(1,&ID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,size*sizeof(float), &data_vector[0], GL_STATIC_DRAW);

    el_size=6*sizeof(float);
}
void display(void){

    int zoom = 1;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2*zoom, 2*zoom,2*zoom,-2*zoom, -5.0f, 5.0f);
    glPushMatrix ();
    glBindBuffer(GL_ARRAY_BUFFER, ID);

    // Pointer for the position of the points
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, el_size, 0);

    // Pointer for the color of the points
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(3,GL_FLOAT, el_size,(void*)(el_size/2));

    //Draw callback
    glDrawArrays(GL_TRIANGLES,0,size/6);

    glPopMatrix ();
    glFlush();
}

// Idle callback function for OpenGL API
void idle(void){

    float* pixels = (float*)malloc(windowSize*windowSize*sizeof(float));
    glReadPixels(0, 0, windowSize, windowSize, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);

    //
    //char waveName[MAX_OBJ_NAME+1]; 
    //CountInt dimensionSizes[MAX_DIMENSIONS+1]; 
    //float* wp;
    //strcpy(waveName, "wave0");
    //MemClear(dimensionSizes, sizeof(dimensionSizes));
    //dimensionSizes[ROWS] = windowSize*windowSize; // Make 1D wave 
    //wp = (float*)WaveData(waveH); // Get a pointer to the wave data 

    //for(int i = 0;i < windowSize*windowSize; i++){    
    //  *wp++ =pixels[i];                 
    //}

    //glDeleteBuffers(1,&ID);
}

// Main function for the XOP
extern "C" int
RenderTriangle(FitParamsPtr p)
{
    waveX=(float*)WaveData(p->waveX);
    waveY=(float*)WaveData(p->waveY);
    waveZ=(float*)WaveData(p->waveZ);

    char *myargv [1];
    int myargc=1;
    myargv [0]=strdup ("RenderTriangle");
    glutInit(&myargc,myargv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_DEPTH | GLUT_RGB);
    glutInitWindowSize(windowSize,windowSize);
    glutCreateWindow("OpenGL");
    init();
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutMainLoop();
    p->result = 1;

    return 0;
}

static XOPIORecResult
RegisterFunction()
{
    int funcIndex;

    funcIndex = (int)GetXOPItem(0);         // Which function invoked ?
    switch (funcIndex) {
        case 0:                                 // y = RenderTriangle(w,x) (curve fitting function).
            return (XOPIORecResult)RenderTriangle;  // This function is called using the direct method.
            break;
    }
    return 0;
}

/*  XOPEntry()

    This is the entry point from the host application to the XOP for all
    messages after the INIT message.
*/
extern "C" void
XOPEntry(void)
{   
    XOPIORecResult result = 0;

    switch (GetXOPMessage()) {
        case FUNCADDRS:
            result = RegisterFunction();    // This tells Igor the address of our function.
            break;
    }
    SetXOPResult(result);
}

/*  main(ioRecHandle)

    This is the initial entry point at which the host application calls XOP.
    The message sent by the host must be INIT.
    main() does any necessary initialization and then sets the XOPEntry field of the
    ioRecHandle to the address to be called for future messages.
*/
HOST_IMPORT int
main(IORecHandle ioRecHandle)
{   
    XOPInit(ioRecHandle);                           // Do standard XOP initialization.
    SetXOPEntry(XOPEntry);                          // Set entry point for future calls.

    if (igorVersion < 600) {
        SetXOPResult(OLD_IGOR);
        return EXIT_FAILURE;
    }

    SetXOPResult(0);
    return EXIT_SUCCESS;
}
4

1 に答える 1

0
  • VBO は頂点データを転送するためのものです。

VBO を介して点群データを転送していますが、それ以上のものはありません。

  • PBO は、ピクセル データを転送するためのものです。

PBO を使用して、OpenGL フレームバッファからデータを非同期に読み取ることができます。

  • FBO を引き寄せることができます。

FBO を使用して、ターゲット フレームバッファをウィンドウ操作から分離する必要があります。

2) また、glutMainLoop を 1 回だけ実行したいと思います。FreeGLUT に変更する必要がありますか?

メインループを実行する必要はまったくありません。必要なのは作成されたウィンドウだけです。メインループが開始されるまで表示されません。OpenGL コンテキストを取得するにはウィンドウが必要ですが、メインループは安全に省略できます。

コールバックを登録する (呼び出されない) 代わりに、OpenGL コマンドを順番に実行するだけです。ライブラリが数回呼び出される場合、ウィンドウを再作成する必要はありませんが、コンテキストを最新にするために glutSetWindow を呼び出す必要がある場合があります。

  1. 描画する FBO をセットアップする
  2. FBOに引き寄せる
  3. glReadPixels
    • PBO と glMapBuffer と memcpy のいずれかに。
    • または適切なサイズのバッファーに直接入れます。
于 2013-01-16T19:18:56.243 に答える