# HG changeset patch # User John Tsiombikas # Date 1419654748 -7200 # Node ID cc9e0d8590e24205e6d2baf4f22da93f982fc26b # Parent 7bdf40403b9c4308e1fe003b407a84ca43c7cf19 foo diff -r 7bdf40403b9c -r cc9e0d8590e2 src/dicomview.cc --- a/src/dicomview.cc Sat Dec 27 02:35:58 2014 +0200 +++ b/src/dicomview.cc Sat Dec 27 06:32:28 2014 +0200 @@ -1,21 +1,36 @@ #include "opengl.h" #include "dicomview.h" +#include "rend_fast.h" +static int win_width, win_height; static float cam_theta, cam_phi, cam_dist = 6; +static Renderer *rend; + extern "C" { int init() { + rend = new RendererFast; + if(!rend->init()) { + return -1; + } + + return 0; } void cleanup() { + rend->destroy(); + delete rend; } void ev_display() { glClear(GL_COLOR_BUFFER_BIT); + + rend->update(0); + rend->render(); } void ev_reshape(int x, int y) @@ -23,11 +38,25 @@ win_width = x; win_height = y; - glViweport(0, 0, x, y); + glViewport(0, 0, x, y); } -void ev_keyboard(int key, int press, int x, int y); -void ev_mouse_button(int bn, int press, int x, int y); -void ev_mouse_motion(int x, int y); +void ev_keyboard(int key, int press, int x, int y) +{ + if(press) { + switch(key) { + case 27: + quit(); + } + } +} + +void ev_mouse_button(int bn, int press, int x, int y) +{ +} + +void ev_mouse_motion(int x, int y) +{ +} } // extern "C" diff -r 7bdf40403b9c -r cc9e0d8590e2 src/image.cc --- a/src/image.cc Sat Dec 27 02:35:58 2014 +0200 +++ b/src/image.cc Sat Dec 27 06:32:28 2014 +0200 @@ -1,3 +1,4 @@ +#include #include #include "image.h" @@ -39,7 +40,7 @@ // TODO dicom loader ... ? int x, y; - float *pixels = img_load_pixels(fname, &x, &y, IMG_FMT_GREYF); + float *pixels = (float*)img_load_pixels(fname, &x, &y, IMG_FMT_GREYF); if(!pixels) { return false; } diff -r 7bdf40403b9c -r cc9e0d8590e2 src/main.cc --- a/src/main.cc Sat Dec 27 02:35:58 2014 +0200 +++ b/src/main.cc Sat Dec 27 06:32:28 2014 +0200 @@ -19,8 +19,6 @@ static void mouse(int bn, int state, int x, int y); static void motion(int x, int y); -static float cam_theta, cam_phi, cam_dist = 6; - int main(int argc, char **argv) { glutInit(&argc, argv); @@ -30,7 +28,8 @@ glutDisplayFunc(display); glutReshapeFunc(reshape); - glutKeyboardFunc(keyb); + glutKeyboardFunc(key_down); + glutKeyboardUpFunc(key_up); glutMouseFunc(mouse); glutMotionFunc(motion); diff -r 7bdf40403b9c -r cc9e0d8590e2 src/volume.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/volume.cc Sat Dec 27 06:32:28 2014 +0200 @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include "volume.h" + +static char *strip_space(char *s); + + +Volume::~Volume() +{ +} + +int Volume::num_samples(int dim) const +{ + return 0; +} + +void Volume::normalf(float *norm, float x, float y, float z, float delta) +{ + float dx, dy, dz; + dx = dy = dz = delta; + + if(num_samples(0) > 0) { + // discrete volume + dx /= (float)num_samples(0); + dy /= (float)num_samples(1); + dz /= (float)num_samples(2); + } + + norm[0] = valuef(x + dx, y, z) - valuef(x - dx, y, z); + norm[1] = valuef(x, y + dy, z) - valuef(x, y - dy, z); + norm[2] = valuef(x, y, z + dz) - valuef(x, y, z - dz); + + float len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]); + if(len != 0.0) { + norm[0] /= len; + norm[1] /= len; + norm[2] /= len; + } +} + +void Volume::normali(float *norm, int x, int y, int z) +{ + int sz[3]; + + if((sz[0] = num_samples(0)) <= 0) { + // if it's a continuous volume, just call normalf + normalf(norm, x, y, z); + return; + } + sz[1] = num_samples(1); + sz[2] = num_samples(2); + + int prevx = x <= 0 ? 0 : x; + int nextx = x >= sz[0] - 1 ? sz[0] - 1 : x; + int prevy = y <= 0 ? 0 : y; + int nexty = y >= sz[1] - 1 ? sz[1] - 1 : y; + int prevz = z <= 0 ? 0 : z; + int nextz = z >= sz[2] - 1 ? sz[2] - 1 : z; + + norm[0] = valuei(nextx, y, z) - valuei(prevx, y, z); + norm[1] = valuei(x, nexty, z) - valuei(x, prevy, z); + norm[2] = valuei(x, y, nextz) - valuei(x, y, prevz); + + float len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]); + if(len != 0.0) { + norm[0] /= len; + norm[1] /= len; + norm[2] /= len; + } +} + +// ---- VoxelVolume (discrete) implementation ---- +VoxelVolume::VoxelVolume() +{ + size[0] = size[1] = size[2] = 0; +} + +bool VoxelVolume::load(const char *fname) +{ + FILE *fp = fopen(fname, "r"); + if(!fp) { + fprintf(stderr, "failed to open file: %s: %s\n", fname, strerror(errno)); + return false; + } + + char buf[512]; + while(fgets(buf, sizeof buf, fp)) { + char *line = strip_space(buf); + + Image img; + if(!img.load(line)) { + slices.clear(); + return false; + } + + if(slices.empty()) { + size[0] = img.width; + size[1] = img.height; + } else { + if(img.width != size[0] || img.height != size[1]) { + fprintf(stderr, "slice %d \"%s\" size mismatch (%dx%d, %dx%d expected)\n", + (int)slices.size(), line, img.width, img.height, size[0], size[1]); + slices.clear(); + return false; + } + } + + slices.push_back(img); + img.pixels = 0; // otherwise the destructor will free it + } + + size[2] = slices.size(); + fclose(fp); + return true; +} + +int VoxelVolume::num_samples(int dim) const +{ + return size[dim]; +} + +static inline int clamp(int x, int low, int high) +{ + return x < low ? low : (x > high ? high : x); +} + +static inline float lookup(int x0, int y0, int x1, int y1, float tx, float ty, + float *pixels, int width, int height) +{ + float v00, v01, v10, v11; + + v00 = pixels[y0 * width + x0]; + v01 = pixels[y1 * width + x0]; + v10 = pixels[y0 * width + x1]; + v11 = pixels[y1 * width + x1]; + + float v0 = v00 + (v01 - v00) * ty; + float v1 = v10 + (v11 - v10) * ty; + + return v0 + (v1 - v0) * tx; +} + +float VoxelVolume::valuef(float x, float y, float z) const +{ + if(slices.empty()) { + return 0.0f; + } + + float floor_x = floor(x); + float ceil_x = ceil(x); + float tx = x - floor_x; + + float floor_y = floor(y); + float ceil_y = ceil(y); + float ty = y - floor_y; + + float floor_z = floor(z); + float ceil_z = ceil(z); + float tz = z - floor_z; + + int x0 = clamp(floor_x, 0, size[0] - 1); + int x1 = clamp(ceil_x, 0, size[0] - 1); + + int y0 = clamp(floor_y, 0, size[1] - 1); + int y1 = clamp(ceil_y, 0, size[1] - 1); + + int s0 = clamp(floor_z, 0, size[2] - 1); + int s1 = clamp(ceil_z, 0, size[2] - 1); + + float val_s0 = lookup(x0, y0, x1, y1, tx, ty, slices[s0].pixels, size[0], size[1]); + float val_s1 = lookup(x0, y0, x1, y1, tx, ty, slices[s1].pixels, size[0], size[1]); + + return val_s0 + (val_s1 - val_s0) * tz; +} + +float VoxelVolume::valuei(int x, int y, int z) const +{ + x = clamp(x, 0, size[0] - 1); + y = clamp(y, 0, size[1] - 1); + z = clamp(z, 0, size[2] - 1); + + return slices[z].pixels[y * size[0] + x]; +} + +static char *strip_space(char *s) +{ + while(*s && isspace(*s)) s++; + if(!*s) return 0; + + char *end = s + strlen(s) - 1; + while(end > s && isspace(*end)) end--; + end[1] = 0; + + return s; +} diff -r 7bdf40403b9c -r cc9e0d8590e2 src/volume.h --- a/src/volume.h Sat Dec 27 02:35:58 2014 +0200 +++ b/src/volume.h Sat Dec 27 06:32:28 2014 +0200 @@ -1,16 +1,18 @@ #ifndef VOLUME_H_ #define VOLUME_H_ +#include #include "image.h" class Volume { public: virtual ~Volume(); - // returns -1 if the volume is continuously defined + // returns 0 if the volume is continuously defined virtual int num_samples(int dim) const; - // central differences offset will be delta / num_samples + // central differences offset will be delta / num_samples for discrete volumes + // and delta for continuous volumes virtual void normalf(float *norm, float x, float y, float z, float delta = 1.0); virtual void normali(float *norm, int x, int y, int z); @@ -20,11 +22,11 @@ class VoxelVolume : public Volume { protected: + int size[3]; std::vector slices; public: VoxelVolume(); - ~VoxelVolume(); bool load(const char *fname);