volmetrics
view src/volume.cc @ 8:928954bfefd7
added mesh (draw: immediate mode - todo: displ. list)
author | Eleni Maria Stea <elene.mst@gmail.com> |
---|---|
date | Sat, 25 Jan 2014 19:25:32 +0200 |
parents | e6485ef45e6e |
children | 40febfed6cff |
line source
1 #include <GL/glew.h>
3 #include <assert.h>
5 #include <ctype.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include <string.h>
10 #include <string>
11 #include <vector>
13 #include "volume.h"
15 static char *strip_whitespaces(char *buf);
17 Volume::Volume()
18 {
19 width = height = 0;
20 zaspect = 1;
21 vol_tex_valid = false;
23 glGenTextures(1, &vol_tex);
24 }
26 Volume::~Volume()
27 {
28 glDeleteTextures(1, &vol_tex);
29 }
31 void Volume::create_vol_tex() const
32 {
33 if(slices.empty())
34 return;
36 glBindTexture(GL_TEXTURE_3D, vol_tex);
37 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
38 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
39 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
40 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
41 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
43 assert(glGetError() == GL_NO_ERROR);
44 glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE, width, height,
45 slices.size(), 0, GL_LUMINANCE, GL_FLOAT, 0);
46 assert(glGetError() == GL_NO_ERROR);
48 for(size_t i=0; i<slices.size(); i++) {
49 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, width, height,
50 1, GL_LUMINANCE, GL_FLOAT, slices[i].get_pixels());
51 }
52 }
54 bool Volume::load(const char *fname)
55 {
56 FILE *fp = fopen(fname, "r");
57 if(!fp) {
58 fprintf(stderr, "Failed to open file: %s: %s\n", fname, strerror(errno));
59 return false;
60 }
62 char buf[512];
63 if(!fgets(buf, sizeof buf, fp)) {
64 fprintf(stderr, "Empty file: %s.\n", fname);
65 return false;
66 }
67 if(strstr(buf, "VOLUME") != buf) {
68 fprintf(stderr, "Invalid volume file format: %s\n", fname);
69 return false;
70 }
72 bool reading_slices = false;
73 std::vector<std::string> img_fnames;
75 while(fgets(buf, sizeof buf, fp)) {
76 char *line = strip_whitespaces(buf);
77 if(!line || *line == 0 || *line == '#')
78 continue;
80 if(reading_slices == false) {
81 if(strcmp(line, "SLICES") == 0)
82 reading_slices = true;
84 sscanf(line, "zaspect = %f", &zaspect);
85 }
86 else {
87 img_fnames.push_back(line);
88 }
89 }
91 fclose(fp);
93 for(size_t i=0; i<img_fnames.size(); i++) {
94 Image img;
95 if(img.load(img_fnames[i].c_str())) {
96 push_slice(std::move(img));
97 }
98 else {
99 fprintf(stderr, "Failed to load slice: %s\n", img_fnames[i].c_str());
100 }
101 }
103 return true;
104 }
106 bool Volume::push_slice(Image &&slice)
107 {
108 if(slices.empty()) {
109 width = slice.get_width();
110 height = slice.get_height();
111 }
112 else {
113 if(width != slice.get_width() || height != slice.get_height()) {
114 fprintf(stderr, "failed to load slice no: %d\n", (int)slices.size() + 1);
115 return false;
116 }
117 }
119 slices.push_back(slice);
120 return true;
121 }
123 const Image *Volume::get_slice(int num_slice) const
124 {
125 if(num_slice >= (int)slices.size() || num_slice < 0)
126 return 0;
128 return &slices[num_slice];
129 }
131 const Image *Volume::get_slice_by_z(float z) const
132 {
133 int idx = get_slice_idx_by_z(z);
134 return get_slice(idx);
135 }
137 int Volume::get_slice_count() const
138 {
139 return (int)slices.size();
140 }
142 int Volume::get_slice_idx_by_z(float z) const
143 {
144 int last_slice_idx = (int)slices.size() - 1;
145 int idx = z * last_slice_idx;
146 if(idx < 0) {
147 idx = 0;
148 }
149 else if(idx > last_slice_idx) {
150 idx = last_slice_idx;
151 }
153 return idx;
154 }
156 unsigned int Volume::get_texture() const
157 {
158 if(!vol_tex_valid) {
159 create_vol_tex();
160 vol_tex_valid = true;
161 }
163 return vol_tex;
164 }
166 void Volume::draw() const
167 {
168 }
170 static char *strip_whitespaces(char *buf)
171 {
172 while(*buf && isspace(*buf))
173 buf++;
175 if(!*buf)
176 return 0;
178 char *end = buf + strlen(buf) - 1;
179 while(end > buf && isspace(*end))
180 end--;
181 end[1] = 0;
182 return buf;
183 }