我需要生成对象的可视化,为此,我计划使用GPU射线投射技术。在两个txt文件中描述了该对象的信息。一个文件通过规则的单元格网格描述该对象的结构,另一个文件包含有关网格中每个单元格强度的信息。
网格由笛卡尔轴上的x,y,z浮点列表来描述,这些浮点形成了单元格,第二个文件只是一个列表o float,描述了每个单元格的强度。
如何使用这些文件生成3d纹理,以便以后创建体积可视化的“体积射线投射”?
[Spektre编辑1]
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 <===网格样式(常规= 0) coordsystem gridinfo incl_x incl_y incl_z nx ny nz
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字节整数。
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字节实数(=双精度)。
yi [1] ... yi [ny + 1]:与上面相同,但现在用于y方向。
zi [1] ... zi [nz + 1]:与上面相同,但现在用于z方向。
在笛卡尔坐标中的简单2x2x2正则网格示例:1 0 1 0 1 1 1 2 2 2 -1。 0. 1。 -1。 0. 1。 -1。 0. 1。
答案 0 :(得分:0)
很好奇,根据您的示例网格,这是我想出的:
//---------------------------------------------------------------------------
//--- 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
个项目预分配空间
, C ++ 代码基于 VCL ,因此您需要将AnsiString重写为可使用的字符串类型。我也使用了我自己的字符串例程来加载行,字符串并转换为数字,因此您也需要移植它,但是我想您已经有了一个加载器...
btw这是文件格式说明中简单样本文件的输出: