Как я могу сгенерировать 3d текстуры из обычной ячейки сетки для объемного рендеринга? - PullRequest
0 голосов
/ 24 марта 2019

Мне нужно создать визуализацию объекта, для этого я планирую использовать технику приведения лучей на GPU.Информация об этом объекте описана в двух текстовых файлах.Один файл описывает структуру этого объекта через обычную ячейку сетки, а другой файл содержит информацию об интенсивности для каждой ячейки в сетке.

Сетка описывается списком x, y, z floatточка в декартовых осях, которые образуют ячейки, а второй файл - это просто список с плавающей точкой, который описывает интенсивность для каждой ячейки.

Как я могу сгенерировать трехмерную текстуру с этими файлами для последующего создания визуализации объема"литье по объему луча"?

[Edit1 by Spektre]

Здесь образец входного файла :

1
0
0
0
1 1 1
32 32 32
-1.495980e+14
-1.402481e+14
-1.308982e+14
-1.215484e+14
-1.121985e+14
-1.028486e+14
-9.349875e+13
-8.414888e+13
-7.479900e+13
-6.544912e+13
-5.609925e+13
-4.674938e+13
-3.739950e+13
-2.804962e+13
-1.869975e+13
-9.349875e+12
 0.000000e+00
 9.349875e+12
 1.869975e+13
 2.804962e+13
 3.739950e+13
 4.674938e+13
 5.609925e+13
 6.544912e+13
 7.479900e+13
 8.414888e+13
 9.349875e+13
 1.028486e+14
 1.121985e+14
 1.215484e+14
 1.308982e+14
 1.402481e+14
 1.495980e+14
-1.495980e+14
-1.402481e+14
-1.308982e+14
-1.215484e+14
-1.121985e+14
-1.028486e+14
-9.349875e+13
-8.414888e+13
-7.479900e+13
-6.544912e+13
-5.609925e+13
-4.674938e+13
-3.739950e+13
-2.804962e+13
-1.869975e+13
-9.349875e+12
 0.000000e+00
 9.349875e+12
 1.869975e+13
 2.804962e+13
 3.739950e+13
 4.674938e+13
 5.609925e+13
 6.544912e+13
 7.479900e+13
 8.414888e+13
 9.349875e+13
 1.028486e+14
 1.121985e+14
 1.215484e+14
 1.308982e+14
 1.402481e+14
 1.495980e+14
-1.495980e+14
-1.402481e+14
-1.308982e+14
-1.215484e+14
-1.121985e+14
-1.028486e+14
-9.349875e+13
-8.414888e+13
-7.479900e+13
-6.544912e+13
-5.609925e+13
-4.674938e+13
-3.739950e+13
-2.804962e+13
-1.869975e+13
-9.349875e+12
 0.000000e+00
 9.349875e+12
 1.869975e+13
 2.804962e+13
 3.739950e+13
 4.674938e+13
 5.609925e+13
 6.544912e+13
 7.479900e+13
 8.414888e+13
 9.349875e+13
 1.028486e+14
 1.121985e+14
 1.215484e+14
 1.308982e+14
 1.402481e+14
 1.495980e+14

И информация о формате файла :

Для обычной сетки без уточнения сетки amr grid.inp выглядит следующим образом:

iformat <=== Обычно 1в настоящее время 0 <=== Grid style (обычный = 0) координатная система gridinfo incl_x incl_y incl_z nx ny nz </p>

xi [1] xi [2] xi [3] .....… xi [nx +1]

yi [1] yi [2] yi [3] .....… yi [ny + 1]

zi [1] zi [2] zi [3].....… zi [nz + 1]

Значения записей следующие:

iformat: номер формата, в настоящее время 1. Для неотформатированных файлов это должно быть 4-байтовое целое число.

Система координат: Если система координат <100, тосистема координат декартова.Если 100 <= Система координат <200, система координат является сферической (полярной).Если 200 <= координатная система <300, система координат является цилиндрической. Для неформатированных файлов это должно быть 4-байтовое целое число. </p>

gridinfo: если gridinfo == 1, в этот файл будет записано много информации о сетке, возможно, полезнодля процедур постобработки.Обычно это избыточная информация, поэтому рекомендуется установить gridinfo = 0 для экономии места на диске.В дальнейшем мы будем предполагать, что gridinfo = 0.Для неотформатированных файлов это должно быть 4-байтовое целое число.

incl x, incl y, incl z: это либо 0, либо 1. Если 0, то это измерение не активно (поэтому при уточнении сетки в этом уточнение не уточняется)измерение сделано).Если 1 это измерение полностью активно, даже если число базовых ячеек сетки в этом направлении равно 1. При уточнении ячейка также будет разделена в этом измерении.Для неформатированных файлов эти числа должны быть 4-байтовыми целыми числами.

nx, ny, nz: это количество ячеек сетки в базовой сетке в каждом из этих измерений.Для неформатированных файлов эти числа должны быть 4-байтовыми целыми числами.

xi [1] ... xi [nx + 1]: края ячеек базовой сетки в направлении x.Для nx ячеек сетки мы имеем nx + 1 клеточных стенок, следовательно, nx + 1 клеточных стенок.Для неформатированных файлов эти числа должны быть 8-байтовыми вещественными числами (= doubleprecision).

yi [1] ... yi [ny + 1]: то же, что и выше, но теперь для направления y.

zi [1] ... zi [nz + 1]: То же, что и выше, но теперь для направления z.

Пример простой регулярной сетки 2x2x2 в декартовых координатах: 1 0 1 0 11 1 2 2 2 -1.0. 1. -1.0. 1. -1.0. 1.

1 Ответ

0 голосов
/ 26 марта 2019

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

//---------------------------------------------------------------------------
//--- AMR class ver: 1.000 --------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _amr_grid_h
#define _amr_grid_h
//---------------------------------------------------------------------------
#include "gl\OpenGL3D_double.cpp"
//---------------------------------------------------------------------------
// https://stackoverflow.com/q/55319835/2521214
//---------------------------------------------------------------------------
class amr_grid
    {
public:
    // BVH file
    int iformat;        // 0,1
    int gridstyle;      // 0 regular
    int coordsystem;    // <0,100) cartesian, <100<200) spherical/polar, <200,300) cylindrical
    int gridinfo;       // 0:  1: additional info added to file
    int en[3];          // enable x,y,z?
    int sz[3];          // size of grid [cells]
    List<double> p[3];  // walls per dimension
    // misc
    double min[3],max[3];   // BBOX
    double dl;              // avg cell size

    amr_grid(){ reset(); }
    amr_grid(amr_grid& a)   { *this=a; }
    ~amr_grid(){}
    amr_grid* operator = (const amr_grid *a) { *this=*a; return this; }
    //bvh* operator = (const bvh &a) { ...copy... return this; }
    // render/set/load
    void reset();               // clear whole skeleton data
    void draw();                // render actual set frame
    void load(AnsiString name); // load from AMR grid file
    };
//---------------------------------------------------------------------------
void amr_grid::reset()
    {
    iformat=1;
    gridstyle=0;
    coordsystem=0;
    gridinfo=0;
    en[0]=1; sz[0]=0;   p[0].num=0; min[0]=0.0; max[0]=0.0;
    en[1]=1; sz[1]=0;   p[1].num=0; min[1]=0.0; max[1]=0.0;
    en[2]=1; sz[2]=0;   p[2].num=0; min[2]=0.0; max[2]=0.0;
    dl=0.0;
    }
//---------------------------------------------------------------------------
void amr_grid::draw()
    {
    int i,x,y,z;

    glColor3f(0.0,1.0,0.5);
    glBegin(GL_LINES);

    if ((gridstyle>=0)&&(gridstyle<100))    // cartesian
        {
        if ((en[0])&&(en[1])&&(en[2]))      // 3D
            {
            for (x=0;x<=sz[0];x++)
             for (y=0;y<=sz[1];y++)
                {
                glVertex3d(p[0][x],p[1][y],min[2]);
                glVertex3d(p[0][x],p[1][y],max[2]);
                }
            for (x=0;x<=sz[0];x++)
             for (z=0;z<=sz[2];z++)
                {
                glVertex3d(p[0][x],min[1],p[2][z]);
                glVertex3d(p[0][x],max[1],p[2][z]);
                }
            for (y=0;y<=sz[1];y++)
             for (z=0;z<=sz[2];z++)
                {
                glVertex3d(min[0],p[1][y],p[2][z]);
                glVertex3d(max[0],p[1][y],p[2][z]);
                }
            }
        }

    glEnd();
    }
//---------------------------------------------------------------------------
void amr_grid::load(AnsiString name)
    {
    int hnd,siz,adr,i,j,k;
    AnsiString lin,s;
    BYTE *txt=NULL;
    reset();
    // file -> memory
    hnd=FileOpen(name,fmOpenRead);
    if (hnd<0) return;
    siz=FileSeek(hnd,0,2);
        FileSeek(hnd,0,0);
    txt=new BYTE[siz];
    if (txt==NULL) { FileClose(hnd); return; }
    siz=FileRead(hnd,txt,siz);
    FileClose(hnd);
    // memory -> amr_grid data
    adr=0;
    iformat=str2int(txt_load_lin(txt,siz,adr,true));
    gridstyle=str2int(txt_load_lin(txt,siz,adr,true));
    coordsystem=str2int(txt_load_lin(txt,siz,adr,true));
    gridinfo=str2int(txt_load_lin(txt,siz,adr,true));
    lin=txt_load_lin(txt,siz,adr,true); i=1; for (j=0;j<3;j++) en[j]=str2num(str_load_str(lin,i,true));
    lin=txt_load_lin(txt,siz,adr,true); i=1; for (j=0;j<3;j++) sz[j]=str2num(str_load_str(lin,i,true));
    for (j=0;j<3;j++) for (p[j].num=0,i=0;i<=sz[j];i++) p[j].add(str2num(txt_load_str(txt,siz,adr,true)));
    // BBOX
    for (j=0;j<3;j++) for (min[j]=max[j]=p[j][0],i=0;i<=sz[j];i++)
        {
        if (min[j]>p[j][i]) min[j]=p[j][i];
        if (max[j]<p[j][i]) max[j]=p[j][i];
        }
    double q[3];
    vector_sub(q,max,min);
    dl=3.0*vector_len(q)/double(sz[0]+sz[1]+sz[2]);
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

Это просто загружает и рисует сетку.Однако я ожидаю, что вы получили файл 3D-текстуры, содержащий интенсивность ячеек, поэтому просто используйте его в качестве цвета для блока и измените процедуру рисования, которая будет отображать ячейки в виде блока с цветом из вашей текстуры.угловые точки ячейки для любой ячейки представляют собой 8 комбинаций этих координат:

x: p[0][i],p[0][i+1]
y: p[1][i],p[1][i+1]
z: p[2][i],p[2][i+1]

вы можете адаптировать мою glBox (остерегайтесь ее float, но код выше использует double ...):

void glBox(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat xs,GLfloat ys,GLfloat zs)
    {
    xs*=0.5;
    ys*=0.5;
    zs*=0.5;
    glBegin(GL_QUADS);

    glNormal3f(+1.0,0.0,0.0);
    glVertex3f(x0+xs,y0-ys,z0-zs);
    glVertex3f(x0+xs,y0+ys,z0-zs);
    glVertex3f(x0+xs,y0+ys,z0+zs);
    glVertex3f(x0+xs,y0-ys,z0+zs);

    glNormal3f(-1.0,0.0,0.0);
    glVertex3f(x0-xs,y0-ys,z0+zs);
    glVertex3f(x0-xs,y0+ys,z0+zs);
    glVertex3f(x0-xs,y0+ys,z0-zs);
    glVertex3f(x0-xs,y0-ys,z0-zs);

    glNormal3f(0.0,+1.0,0.0);
    glVertex3f(x0-xs,y0+ys,z0+zs);
    glVertex3f(x0+xs,y0+ys,z0+zs);
    glVertex3f(x0+xs,y0+ys,z0-zs);
    glVertex3f(x0-xs,y0+ys,z0-zs);

    glNormal3f(0.0,-1.0,0.0);
    glVertex3f(x0-xs,y0-ys,z0-zs);
    glVertex3f(x0+xs,y0-ys,z0-zs);
    glVertex3f(x0+xs,y0-ys,z0+zs);
    glVertex3f(x0-xs,y0-ys,z0+zs);

    glNormal3f(0.0,0.0,+1.0);
    glVertex3f(x0+xs,y0-ys,z0+zs);
    glVertex3f(x0+xs,y0+ys,z0+zs);
    glVertex3f(x0-xs,y0+ys,z0+zs);
    glVertex3f(x0-xs,y0-ys,z0+zs);

    glNormal3f(0.0,0.0,-1.0);
    glVertex3f(x0-xs,y0-ys,z0-zs);
    glVertex3f(x0-xs,y0+ys,z0-zs);
    glVertex3f(x0+xs,y0+ys,z0-zs);
    glVertex3f(x0+xs,y0-ys,z0-zs);

    glEnd();
    }

до x0,y0,z0,x1,y1,z1 сформировать или написать VBO или что-то еще ...

PS.

Я также использую мой шаблон динамического списка так:


List<double> xxx; совпадает с double xxx[];
xxx.add(5); добавляет 5 в конец списка
xxx[7] элемент массива доступа (безопасный)
xxx.dat[7] элемент массива доступа (небезопасный, но быстрый прямой доступ)
xxx.num - фактический используемый размер массива
xxx.reset() очищает массив и устанавливает xxx.num=0
xxx.allocate(100) предварительно выделить место для 100 items

и код C ++ основаны на VCL , поэтому вам нужно переписать AnsiString в тип строки, который вы получили в вашем распоряжении.Также я использовал свои собственные строковые подпрограммы для загрузки строк, строк и преобразования в числа, так что вам тоже нужно их портировать, но я предполагаю, что у вас уже есть загрузчик ...

кстати, это вывод для простого файла примерав описании формата файла:

screenshot

...