elene@6: #include elene@6: elene@6: #include elene@6: elene@5: #include elene@5: #include elene@4: #include elene@5: #include elene@5: elene@5: #include elene@5: #include elene@4: elene@9: #include elene@9: elene@9: #include "mesh.h" elene@3: #include "volume.h" elene@4: elene@5: static char *strip_whitespaces(char *buf); elene@5: elene@4: Volume::Volume() elene@4: { elene@4: width = height = 0; elene@5: zaspect = 1; elene@6: vol_tex_valid = false; elene@6: elene@6: glGenTextures(1, &vol_tex); elene@4: } elene@4: elene@6: Volume::~Volume() elene@6: { elene@6: glDeleteTextures(1, &vol_tex); elene@6: } elene@6: elene@6: void Volume::create_vol_tex() const elene@6: { elene@6: if(slices.empty()) elene@6: return; elene@6: elene@6: glBindTexture(GL_TEXTURE_3D, vol_tex); elene@6: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); elene@6: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); elene@6: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); elene@6: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); elene@6: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); elene@6: elene@6: assert(glGetError() == GL_NO_ERROR); elene@6: glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE, width, height, elene@6: slices.size(), 0, GL_LUMINANCE, GL_FLOAT, 0); elene@6: assert(glGetError() == GL_NO_ERROR); elene@6: elene@6: for(size_t i=0; i img_fnames; elene@5: elene@5: while(fgets(buf, sizeof buf, fp)) { elene@5: char *line = strip_whitespaces(buf); elene@5: if(!line || *line == 0 || *line == '#') elene@5: continue; elene@5: elene@5: if(reading_slices == false) { elene@5: if(strcmp(line, "SLICES") == 0) elene@5: reading_slices = true; elene@5: elene@5: sscanf(line, "zaspect = %f", &zaspect); elene@5: } elene@5: else { elene@5: img_fnames.push_back(line); elene@5: } elene@5: } elene@5: elene@5: fclose(fp); elene@5: elene@5: for(size_t i=0; i= (int)slices.size() || num_slice < 0) elene@6: return 0; elene@6: elene@6: return &slices[num_slice]; elene@6: } elene@6: elene@6: const Image *Volume::get_slice_by_z(float z) const elene@6: { elene@6: int idx = get_slice_idx_by_z(z); elene@6: return get_slice(idx); elene@6: } elene@6: elene@6: int Volume::get_slice_count() const elene@6: { elene@6: return (int)slices.size(); elene@6: } elene@6: elene@6: int Volume::get_slice_idx_by_z(float z) const elene@6: { elene@6: int last_slice_idx = (int)slices.size() - 1; elene@6: int idx = z * last_slice_idx; elene@6: if(idx < 0) { elene@6: idx = 0; elene@6: } elene@6: else if(idx > last_slice_idx) { elene@6: idx = last_slice_idx; elene@6: } elene@6: elene@6: return idx; elene@6: } elene@6: elene@6: unsigned int Volume::get_texture() const elene@6: { elene@6: if(!vol_tex_valid) { elene@6: create_vol_tex(); elene@6: vol_tex_valid = true; elene@6: } elene@6: elene@6: return vol_tex; elene@6: } elene@6: elene@9: static Mesh *cur_mesh; elene@9: static Volume *cur_vol; elene@9: elene@9: static float cb_eval(float x, float y, float z) elene@9: { elene@9: const Image *img = cur_vol->get_slice_by_z((z + 1) / 2.0); elene@9: const float *pixels = img->get_pixels(); elene@9: elene@9: int px = (x + 1) / 2.0 * img->get_width(); elene@9: int py = (y + 1) / 2.0 * img->get_height(); elene@9: elene@9: return pixels[px + img->get_width() * py]; elene@9: } elene@9: elene@9: void Volume::create_mesh(Mesh *mesh, float threshold) elene@9: { elene@9: cur_mesh = mesh; elene@9: cur_vol = this; elene@9: elene@9: metasurface *ms = msurf_create(); elene@9: msurf_threshold(ms, threshold); elene@9: msurf_resolution(ms, width, height, slices.size()); elene@9: msurf_vertex_func(ms, elene@9: [](float x, float y, float z){cur_mesh->add_vertex(Vector3(x, y, z));}); elene@9: msurf_normal_func(ms, elene@9: [](float x, float y, float z){cur_mesh->add_normal(Vector3(x, y, z));}); elene@9: elene@9: msurf_eval_func(ms, cb_eval); elene@9: msurf_polygonize(ms); elene@9: msurf_free(ms); elene@9: } elene@9: elene@8: void Volume::draw() const elene@5: { elene@5: } elene@5: elene@5: static char *strip_whitespaces(char *buf) elene@5: { elene@5: while(*buf && isspace(*buf)) elene@5: buf++; elene@5: elene@5: if(!*buf) elene@5: return 0; elene@5: elene@5: char *end = buf + strlen(buf) - 1; elene@5: while(end > buf && isspace(*end)) elene@5: end--; elene@5: end[1] = 0; elene@5: return buf; elene@5: }