# HG changeset patch # User John Tsiombikas # Date 1334004177 -10800 # Node ID 8990b5d2c7feab0c1ac2620ffc6b358767d2fa06 # Parent 9d2396738b60d76790d038a6dd0d909fb40f8519 moving to qt diff -r 9d2396738b60 -r 8990b5d2c7fe Makefile --- a/Makefile Sun Apr 08 14:31:03 2012 +0300 +++ b/Makefile Mon Apr 09 23:42:57 2012 +0300 @@ -1,28 +1,228 @@ -src = $(wildcard src/*.c) -obj = $(src:.c=.o) -dep = $(obj:.o=.d) -bin = volray +############################################################################# +# Makefile for building: qvolray +# Generated by qmake (2.01a) (Qt 4.7.4) on: Mon Apr 9 23:25:44 2012 +# Project: qvolray.pro +# Template: app +# Command: /usr/bin/qmake -o Makefile qvolray.pro +############################################################################# -CC = gcc -CFLAGS = -pedantic -Wall -g $(incdir) -LDFLAGS = $(libdir) $(libgl) -limago -lvmath -lm +####### Compiler, tools and options -ifeq ($(shell uname -s), Darwin) - libgl = -framework OpenGL -framework GLUT -lGLEW - incdir = -I/opt/local/include - libdir = -L/opt/local/lib -else - libgl = -lGL -lglut -lGLEW -endif +CC = gcc +CXX = g++ +DEFINES = -DQT_WEBKIT -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtOpenGL -I/usr/include/qt4 -I. -Isrc -I/usr/X11R6/include -I. +LINK = g++ +LFLAGS = -Wl,-O1 +LIBS = $(SUBLIBS) -L/usr/lib -L/usr/X11R6/lib -lQtOpenGL -lQtGui -lQtCore -lGLU -lGL -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p -$(bin): $(obj) - $(CC) -o $@ $(obj) $(LDFLAGS) +####### Output directory --include $(dep) +OBJECTS_DIR = ./ -%.d: %.c - @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ +####### Files -.PHONY: clean -clean: - rm -f $(obj) $(bin) +SOURCES = src/main.cc \ + src/sdr.c \ + src/volray.cc \ + src/volume.cc +OBJECTS = main.o \ + sdr.o \ + volray.o \ + volume.o +DIST = /usr/share/qt4/mkspecs/common/g++.conf \ + /usr/share/qt4/mkspecs/common/unix.conf \ + /usr/share/qt4/mkspecs/common/linux.conf \ + /usr/share/qt4/mkspecs/qconfig.pri \ + /usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \ + /usr/share/qt4/mkspecs/features/qt_functions.prf \ + /usr/share/qt4/mkspecs/features/qt_config.prf \ + /usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt4/mkspecs/features/default_pre.prf \ + /usr/share/qt4/mkspecs/features/release.prf \ + /usr/share/qt4/mkspecs/features/default_post.prf \ + /usr/share/qt4/mkspecs/features/warn_on.prf \ + /usr/share/qt4/mkspecs/features/qt.prf \ + /usr/share/qt4/mkspecs/features/unix/opengl.prf \ + /usr/share/qt4/mkspecs/features/unix/thread.prf \ + /usr/share/qt4/mkspecs/features/moc.prf \ + /usr/share/qt4/mkspecs/features/resources.prf \ + /usr/share/qt4/mkspecs/features/uic.prf \ + /usr/share/qt4/mkspecs/features/yacc.prf \ + /usr/share/qt4/mkspecs/features/lex.prf \ + /usr/share/qt4/mkspecs/features/include_source_dir.prf \ + qvolray.pro +QMAKE_TARGET = qvolray +DESTDIR = +TARGET = qvolray + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + +Makefile: qvolray.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/g++.conf \ + /usr/share/qt4/mkspecs/common/unix.conf \ + /usr/share/qt4/mkspecs/common/linux.conf \ + /usr/share/qt4/mkspecs/qconfig.pri \ + /usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \ + /usr/share/qt4/mkspecs/features/qt_functions.prf \ + /usr/share/qt4/mkspecs/features/qt_config.prf \ + /usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt4/mkspecs/features/default_pre.prf \ + /usr/share/qt4/mkspecs/features/release.prf \ + /usr/share/qt4/mkspecs/features/default_post.prf \ + /usr/share/qt4/mkspecs/features/warn_on.prf \ + /usr/share/qt4/mkspecs/features/qt.prf \ + /usr/share/qt4/mkspecs/features/unix/opengl.prf \ + /usr/share/qt4/mkspecs/features/unix/thread.prf \ + /usr/share/qt4/mkspecs/features/moc.prf \ + /usr/share/qt4/mkspecs/features/resources.prf \ + /usr/share/qt4/mkspecs/features/uic.prf \ + /usr/share/qt4/mkspecs/features/yacc.prf \ + /usr/share/qt4/mkspecs/features/lex.prf \ + /usr/share/qt4/mkspecs/features/include_source_dir.prf \ + /usr/lib/libQtOpenGL.prl \ + /usr/lib/libQtGui.prl \ + /usr/lib/libQtCore.prl + $(QMAKE) -o Makefile qvolray.pro +/usr/share/qt4/mkspecs/common/g++.conf: +/usr/share/qt4/mkspecs/common/unix.conf: +/usr/share/qt4/mkspecs/common/linux.conf: +/usr/share/qt4/mkspecs/qconfig.pri: +/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri: +/usr/share/qt4/mkspecs/features/qt_functions.prf: +/usr/share/qt4/mkspecs/features/qt_config.prf: +/usr/share/qt4/mkspecs/features/exclusive_builds.prf: +/usr/share/qt4/mkspecs/features/default_pre.prf: +/usr/share/qt4/mkspecs/features/release.prf: +/usr/share/qt4/mkspecs/features/default_post.prf: +/usr/share/qt4/mkspecs/features/warn_on.prf: +/usr/share/qt4/mkspecs/features/qt.prf: +/usr/share/qt4/mkspecs/features/unix/opengl.prf: +/usr/share/qt4/mkspecs/features/unix/thread.prf: +/usr/share/qt4/mkspecs/features/moc.prf: +/usr/share/qt4/mkspecs/features/resources.prf: +/usr/share/qt4/mkspecs/features/uic.prf: +/usr/share/qt4/mkspecs/features/yacc.prf: +/usr/share/qt4/mkspecs/features/lex.prf: +/usr/share/qt4/mkspecs/features/include_source_dir.prf: +/usr/lib/libQtOpenGL.prl: +/usr/lib/libQtGui.prl: +/usr/lib/libQtCore.prl: +qmake: FORCE + @$(QMAKE) -o Makefile qvolray.pro + +dist: + @$(CHK_DIR_EXISTS) .tmp/qvolray1.0.0 || $(MKDIR) .tmp/qvolray1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/qvolray1.0.0/ && $(COPY_FILE) --parents src/sdr.h src/volray.h src/volume.h .tmp/qvolray1.0.0/ && $(COPY_FILE) --parents src/main.cc src/sdr.c src/volray.cc src/volume.cc .tmp/qvolray1.0.0/ && (cd `dirname .tmp/qvolray1.0.0` && $(TAR) qvolray1.0.0.tar qvolray1.0.0 && $(COMPRESS) qvolray1.0.0.tar) && $(MOVE) `dirname .tmp/qvolray1.0.0`/qvolray1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/qvolray1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +check: first + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: +compiler_moc_header_clean: +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: main.moc +compiler_moc_source_clean: + -$(DEL_FILE) main.moc +main.moc: src/volray.h \ + src/main.cc + /usr/bin/moc-qt4 $(DEFINES) $(INCPATH) src/main.cc -o main.moc + +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_source_clean + +####### Compile + +main.o: src/main.cc src/volray.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o src/main.cc + +sdr.o: src/sdr.c src/sdr.h + $(CC) -c $(CFLAGS) $(INCPATH) -o sdr.o src/sdr.c + +volray.o: src/volray.cc src/sdr.h \ + src/volume.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o volray.o src/volray.cc + +volume.o: src/volume.cc src/volume.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o volume.o src/volume.cc + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff -r 9d2396738b60 -r 8990b5d2c7fe src/main.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.cc Mon Apr 09 23:42:57 2012 +0300 @@ -0,0 +1,51 @@ +#include +#include +#include +#include "volray.h" + +class GLView : public QGLWidget { +private: + Q_OBJECT; + + void initializeGL(); + void resizeGL(int xsz, int ysz); + void paintGL(); + +public: + GLView(QWidget *parent = 0); +}; + + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QMainWindow win; + GLView glview(&win); + + win.show(); + app.exec(); +} + + +GLView::GLView(QWidget *parent) + : QGLWidget(parent) +{ +} + +void GLView::initializeGL() +{ + glClearColor(1, 0, 0, 1); + + volray_init(); +} + +void GLView::resizeGL(int xsz, int ysz) +{ + volray_resize(xsz, ysz); +} + +void GLView::paintGL() +{ + volray_draw(); +} diff -r 9d2396738b60 -r 8990b5d2c7fe src/volray.c --- a/src/volray.c Sun Apr 08 14:31:03 2012 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -#include -#include -#include - -#include -#ifndef __APPLE__ -#include -#else -#include -#endif - -#include -#include -#include "sdr.h" -#include "volume.h" - -#define XFER_MAP_SZ 512 - -enum { - UIMODE_DEFAULT, - UIMODE_XFER, - UIMODE_CURSOR -}; - -int init(void); -void disp(void); -void render_volume(void); -void draw_slice(void); -void draw_xfer_func(void); -void reshape(int x, int y); -void keyb(unsigned char key, int x, int y); -void keyb_up(unsigned char key, int x, int y); -void mouse(int bn, int state, int x, int y); -void motion(int x, int y); -int parse_args(int argc, char **argv); - -static void create_ray_texture(int xsz, int ysz, float vfov, vec2_t *tex_scale); -static vec3_t get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg); -static int round_pow2(int x); -static void create_transfer_map(float mean, float sdev); - -static float cam_theta = 0, cam_phi = 0, cam_dist = 4.0; -static float cam_x, cam_y, cam_z; - -static vec2_t tex_scale; -static struct volume *volume; -static unsigned int vol_sdr, slice_sdr, ray_tex; -static int win_xsz, win_ysz; -static int raytex_needs_recalc = 1; - -static unsigned int xfer_tex; -static float xfer_mean = 0.7, xfer_sdev = 0.1; -static int xfertex_needs_recalc = 1; - -static int uimode; -static float cur_z = 0.0; -static float ray_step = 0.01; - -static const char *fname; - - -int main(int argc, char **argv) -{ - glutInit(&argc, argv); - glutInitWindowSize(1280, 720); - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); - - if(parse_args(argc, argv) == -1) { - return 1; - } - - glutCreateWindow("Volume Raytracer"); - - glutDisplayFunc(disp); - glutReshapeFunc(reshape); - glutKeyboardFunc(keyb); - glutKeyboardUpFunc(keyb_up); - glutMouseFunc(mouse); - glutMotionFunc(motion); - - glewInit(); - - if(init() == -1) { - return 1; - } - - glutMainLoop(); - return 0; -} - -int init(void) -{ - if(!(vol_sdr = create_program_load("sdr/volray.v.glsl", "sdr/volray.p.glsl"))) { - return -1; - } - set_uniform_int(vol_sdr, "volume", 0); - set_uniform_int(vol_sdr, "ray_tex", 1); - set_uniform_int(vol_sdr, "xfer_tex", 2); - set_uniform_float(vol_sdr, "ray_step", ray_step); - set_uniform_float(vol_sdr, "zclip", cur_z); - - if(!(slice_sdr = create_program_load(0, "sdr/slice.p.glsl"))) { - return -1; - } - set_uniform_int(slice_sdr, "volume", 0); - set_uniform_int(slice_sdr, "xfer_tex", 1); - - if(!(volume = load_volume(fname))) { - return -1; - } - - return 0; -} - -void disp(void) -{ - /* recalculate primary ray texture if needed */ - if(raytex_needs_recalc) { - create_ray_texture(win_xsz, win_ysz, 50.0, &tex_scale); - } - /* recalculate transfer function texture if needed */ - if(xfertex_needs_recalc) { - create_transfer_map(xfer_mean, xfer_sdev); - } - - render_volume(); - draw_slice(); - draw_xfer_func(); - - glutSwapBuffers(); - assert(glGetError() == GL_NO_ERROR); -} - -void render_volume(void) -{ - /* set the camera transformation */ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glRotatef(-90, 1, 0, 0); - glTranslatef(cam_x, cam_y, -cam_z); - glRotatef(cam_theta, 0, 1, 0); - glRotatef(cam_phi, 1, 0, 0); - glTranslatef(0, 0, -cam_dist); - - /* setup the texture matrix to map the useful part of the ray texture to [0,1] */ - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glLoadIdentity(); - glScalef(tex_scale.x, tex_scale.y, 1.0); - - /* tex unit0: volume data 3D texture */ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, volume->tex_vol); - glEnable(GL_TEXTURE_3D); - - /* tex unit1: primary rays in view space */ - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, ray_tex); - glEnable(GL_TEXTURE_2D); - - /* tex unit2: transfer function (1d) */ - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_1D, xfer_tex); - glEnable(GL_TEXTURE_1D); - - bind_program(vol_sdr); - glBegin(GL_QUADS); - glColor3f(1, 1, 1); - glTexCoord2f(0, 1); glVertex2f(-1, -1); - glTexCoord2f(1, 1); glVertex2f(1, -1); - glTexCoord2f(1, 0); glVertex2f(1, 1); - glTexCoord2f(0, 0); glVertex2f(-1, 1); - glEnd(); - bind_program(0); - - glActiveTexture(GL_TEXTURE2); - glDisable(GL_TEXTURE_1D); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_3D); - - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - -void draw_slice(void) -{ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glTranslatef(0.9, 0.9, 0); - glScalef(0.3, 0.3 * ((float)win_xsz / win_ysz), 1); - glTranslatef(-1, -1, 0); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, volume->tex_vol); - glEnable(GL_TEXTURE_3D); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_1D, xfer_tex); - glEnable(GL_TEXTURE_1D); - - bind_program(slice_sdr); - - glBegin(GL_QUADS); - glColor3f(1, 1, 1); - glTexCoord3f(0, 1, cur_z); glVertex2f(-1, -1); - glTexCoord3f(1, 1, cur_z); glVertex2f(1, -1); - glTexCoord3f(1, 0, cur_z); glVertex2f(1, 1); - glTexCoord3f(0, 0, cur_z); glVertex2f(-1, 1); - glEnd(); - - bind_program(0); - - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_1D); - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_3D); - glPopMatrix(); -} - -void draw_xfer_func(void) -{ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glTranslatef(-0.9, -0.9, 0); - glScalef(0.5, 0.1, 1); - - glBindTexture(GL_TEXTURE_1D, xfer_tex); - glEnable(GL_TEXTURE_1D); - - glBegin(GL_QUADS); - glColor3f(1, 1, 1); - glTexCoord1f(1); - glVertex2f(1, 0); - glVertex2f(1, 1); - glTexCoord1f(0); - glVertex2f(0, 1); - glVertex2f(0, 0); - glEnd(); - - glDisable(GL_TEXTURE_1D); - - glLineWidth(2.0); - glBegin(GL_LINE_LOOP); - if(uimode == UIMODE_XFER) { - glColor3f(1, 0, 0); - } else { - glColor3f(0, 0, 1); - } - glVertex2f(0, 0); - glVertex2f(1, 0); - glVertex2f(1, 1); - glVertex2f(0, 1); - glEnd(); - - glPopMatrix(); -} - -void reshape(int x, int y) -{ - glViewport(0, 0, x, y); - - if(x != win_xsz || y != win_ysz) { - raytex_needs_recalc = 1; - win_xsz = x; - win_ysz = y; - } -} - -void keyb(unsigned char key, int x, int y) -{ - switch(key) { - case 27: - exit(0); - - case 'x': - uimode = UIMODE_XFER; - glutPostRedisplay(); - break; - - case 'c': - uimode = UIMODE_CURSOR; - glutPostRedisplay(); - break; - - default: - break; - } -} - -void keyb_up(unsigned char key, int x, int y) -{ - switch(key) { - case 'x': - if(uimode == UIMODE_XFER) { - uimode = UIMODE_DEFAULT; - glutPostRedisplay(); - } - break; - - case 'c': - if(uimode == UIMODE_CURSOR) { - uimode = UIMODE_DEFAULT; - glutPostRedisplay(); - } - break; - - default: - break; - } -} - -static int bnstate[32]; -static int prev_x, prev_y; - -void mouse(int bn, int state, int x, int y) -{ - bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN; - prev_x = x; - prev_y = y; -} - -void motion(int x, int y) -{ - int dx = x - prev_x; - int dy = y - prev_y; - prev_x = x; - prev_y = y; - - switch(uimode) { - case UIMODE_XFER: - if(dx || dy) { - xfer_mean += dx / (float)win_xsz; - xfer_sdev += 0.5 * dy / (float)win_ysz; - - xfer_mean = xfer_mean < 0.0 ? 0.0 : (xfer_mean > 1.0 ? 1.0 : xfer_mean); - xfer_sdev = xfer_sdev < 0.0 ? 0.0 : (xfer_sdev > 1.0 ? 1.0 : xfer_sdev); - - xfertex_needs_recalc = 1; - glutPostRedisplay(); - } - break; - - case UIMODE_CURSOR: - cur_z += 0.5 * dy / (float)win_ysz; - - if(cur_z < 0.0) - cur_z = 0.0; - if(cur_z > 1.0) - cur_z = 1.0; - - set_uniform_float(vol_sdr, "zclip", cur_z); - glutPostRedisplay(); - break; - - default: - /* view control */ - if(bnstate[0]) { - cam_theta += dx * 0.5; - cam_phi += dy * 0.5; - - if(cam_phi <= -90) cam_phi = -89; - if(cam_phi >= 90) cam_phi = 89; - - glutPostRedisplay(); - } - - if(bnstate[1]) { - cam_x += dx * 0.025; - cam_y += dy * 0.025; - glutPostRedisplay(); - } - - if(bnstate[2]) { - cam_dist += dy * 0.025; - if(cam_dist < 0.0) cam_dist = 0.0; - glutPostRedisplay(); - } - } -} - - -int parse_args(int argc, char **argv) -{ - int i; - char *endp; - - for(i=1; i cur_tex_xsz || tex_ysz > cur_tex_ysz) { - glBindTexture(GL_TEXTURE_2D, ray_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, 0); - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, xsz, ysz, GL_RGB, GL_FLOAT, teximg); - free(teximg); - - if(tex_scale) { - tex_scale->x = (float)xsz / (float)tex_xsz; - tex_scale->y = (float)ysz / (float)tex_ysz; - } - raytex_needs_recalc = 0; -} - -static vec3_t get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg) -{ - float vfov = M_PI * vfov_deg / 180.0; - float aspect = (float)w / (float)h; - - float ysz = 2.0; - float xsz = aspect * ysz; - - float px = ((float)x / (float)w) * xsz - xsz / 2.0; - float py = 1.0 - ((float)y / (float)h) * ysz; - float pz = 1.0 / tan(0.5 * vfov); - - float mag = sqrt(px * px + py * py + pz * pz); - - return v3_cons(px / mag, py / mag, pz / mag); -} - -static int round_pow2(int x) -{ - x--; - x = (x >> 1) | x; - x = (x >> 2) | x; - x = (x >> 4) | x; - x = (x >> 8) | x; - x = (x >> 16) | x; - return x + 1; -} - -static void create_transfer_map(float mean, float sdev) -{ - static float map[XFER_MAP_SZ]; - int i; - - if(!xfer_tex) { - glGenTextures(1, &xfer_tex); - glBindTexture(GL_TEXTURE_1D, xfer_tex); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE32F_ARB, XFER_MAP_SZ, 0, GL_LUMINANCE, GL_FLOAT, 0); - } - - for(i=0; i +#include +#include + +#include +#ifndef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include "sdr.h" +#include "volume.h" + +#define XFER_MAP_SZ 512 + +static void render_volume(); +static void draw_slice(); +static void draw_xfer_func(); + +/* +void keyb(unsigned char key, int x, int y); +void keyb_up(unsigned char key, int x, int y); +void mouse(int bn, int state, int x, int y); +void motion(int x, int y); +int parse_args(int argc, char **argv); +*/ + +static void create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale); +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg); +static int round_pow2(int x); +static void create_transfer_map(float mean, float sdev); + +static float cam_theta = 0, cam_phi = 0, cam_dist = 4.0; +static float cam_x, cam_y, cam_z; + +static vec2_t tex_scale; +static unsigned int vol_sdr, slice_sdr, ray_tex; +static int win_xsz, win_ysz; +static bool raytex_needs_recalc = true; + +static unsigned int xfer_tex; +static float xfer_mean = 0.7, xfer_sdev = 0.1; +static bool xfertex_needs_recalc = true; + +static float cur_z = 0.0; +static float ray_step = 0.01; + +static Volume volume; + + +bool volray_init() +{ + glewInit(); + + if(!(vol_sdr = create_program_load("sdr/volray.v.glsl", "sdr/volray.p.glsl"))) { + return false; + } + set_uniform_int(vol_sdr, "volume", 0); + set_uniform_int(vol_sdr, "ray_tex", 1); + set_uniform_int(vol_sdr, "xfer_tex", 2); + set_uniform_float(vol_sdr, "ray_step", ray_step); + set_uniform_float(vol_sdr, "zclip", cur_z); + + if(!(slice_sdr = create_program_load(0, "sdr/slice.p.glsl"))) { + return false; + } + set_uniform_int(slice_sdr, "volume", 0); + set_uniform_int(slice_sdr, "xfer_tex", 1); + + if(!volume.load(fname)) { + return false; + } + return true; +} + +void volray_draw(void) +{ + /* recalculate primary ray texture if needed */ + if(raytex_needs_recalc) { + create_ray_texture(win_xsz, win_ysz, 50.0, &tex_scale); + } + /* recalculate transfer function texture if needed */ + if(xfertex_needs_recalc) { + create_transfer_map(xfer_mean, xfer_sdev); + } + + render_volume(); + draw_slice(); + draw_xfer_func(); + + assert(glGetError() == GL_NO_ERROR); +} + +static void render_volume(void) +{ + /* set the camera transformation */ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glRotatef(-90, 1, 0, 0); + glTranslatef(cam_x, cam_y, -cam_z); + glRotatef(cam_theta, 0, 1, 0); + glRotatef(cam_phi, 1, 0, 0); + glTranslatef(0, 0, -cam_dist); + + /* setup the texture matrix to map the useful part of the ray texture to [0,1] */ + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadIdentity(); + glScalef(tex_scale.x, tex_scale.y, 1.0); + + /* tex unit0: volume data 3D texture */ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, volume.get_texture()); + glEnable(GL_TEXTURE_3D); + + /* tex unit1: primary rays in view space */ + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, ray_tex); + glEnable(GL_TEXTURE_2D); + + /* tex unit2: transfer function (1d) */ + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_1D, xfer_tex); + glEnable(GL_TEXTURE_1D); + + bind_program(vol_sdr); + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glTexCoord2f(0, 1); glVertex2f(-1, -1); + glTexCoord2f(1, 1); glVertex2f(1, -1); + glTexCoord2f(1, 0); glVertex2f(1, 1); + glTexCoord2f(0, 0); glVertex2f(-1, 1); + glEnd(); + bind_program(0); + + glActiveTexture(GL_TEXTURE2); + glDisable(GL_TEXTURE_1D); + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + glDisable(GL_TEXTURE_3D); + + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +static void draw_slice(void) +{ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslatef(0.9, 0.9, 0); + glScalef(0.3, 0.3 * ((float)win_xsz / win_ysz), 1); + glTranslatef(-1, -1, 0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, volume.get_texture()); + glEnable(GL_TEXTURE_3D); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_1D, xfer_tex); + glEnable(GL_TEXTURE_1D); + + bind_program(slice_sdr); + + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glTexCoord3f(0, 1, cur_z); glVertex2f(-1, -1); + glTexCoord3f(1, 1, cur_z); glVertex2f(1, -1); + glTexCoord3f(1, 0, cur_z); glVertex2f(1, 1); + glTexCoord3f(0, 0, cur_z); glVertex2f(-1, 1); + glEnd(); + + bind_program(0); + + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_1D); + glActiveTexture(GL_TEXTURE0); + glDisable(GL_TEXTURE_3D); + glPopMatrix(); +} + +static void draw_xfer_func(void) +{ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslatef(-0.9, -0.9, 0); + glScalef(0.5, 0.1, 1); + + glBindTexture(GL_TEXTURE_1D, xfer_tex); + glEnable(GL_TEXTURE_1D); + + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glTexCoord1f(1); + glVertex2f(1, 0); + glVertex2f(1, 1); + glTexCoord1f(0); + glVertex2f(0, 1); + glVertex2f(0, 0); + glEnd(); + + glDisable(GL_TEXTURE_1D); + + glLineWidth(2.0); + glBegin(GL_LINE_LOOP); + if(uimode == UIMODE_XFER) { + glColor3f(1, 0, 0); + } else { + glColor3f(0, 0, 1); + } + glVertex2f(0, 0); + glVertex2f(1, 0); + glVertex2f(1, 1); + glVertex2f(0, 1); + glEnd(); + + glPopMatrix(); +} + +void volray_resize(int x, int y) +{ + glViewport(0, 0, x, y); + + if(x != win_xsz || y != win_ysz) { + raytex_needs_recalc = true; + win_xsz = x; + win_ysz = y; + } +} + +#if 0 +void keyb(unsigned char key, int x, int y) +{ + switch(key) { + case 27: + exit(0); + + case 'x': + uimode = UIMODE_XFER; + glutPostRedisplay(); + break; + + case 'c': + uimode = UIMODE_CURSOR; + glutPostRedisplay(); + break; + + default: + break; + } +} + +void keyb_up(unsigned char key, int x, int y) +{ + switch(key) { + case 'x': + if(uimode == UIMODE_XFER) { + uimode = UIMODE_DEFAULT; + glutPostRedisplay(); + } + break; + + case 'c': + if(uimode == UIMODE_CURSOR) { + uimode = UIMODE_DEFAULT; + glutPostRedisplay(); + } + break; + + default: + break; + } +} + +static int bnstate[32]; +static int prev_x, prev_y; + +void mouse(int bn, int state, int x, int y) +{ + bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN; + prev_x = x; + prev_y = y; +} + +void motion(int x, int y) +{ + int dx = x - prev_x; + int dy = y - prev_y; + prev_x = x; + prev_y = y; + + switch(uimode) { + case UIMODE_XFER: + if(dx || dy) { + xfer_mean += dx / (float)win_xsz; + xfer_sdev += 0.5 * dy / (float)win_ysz; + + xfer_mean = xfer_mean < 0.0 ? 0.0 : (xfer_mean > 1.0 ? 1.0 : xfer_mean); + xfer_sdev = xfer_sdev < 0.0 ? 0.0 : (xfer_sdev > 1.0 ? 1.0 : xfer_sdev); + + xfertex_needs_recalc = true; + glutPostRedisplay(); + } + break; + + case UIMODE_CURSOR: + cur_z += 0.5 * dy / (float)win_ysz; + + if(cur_z < 0.0) + cur_z = 0.0; + if(cur_z > 1.0) + cur_z = 1.0; + + set_uniform_float(vol_sdr, "zclip", cur_z); + glutPostRedisplay(); + break; + + default: + /* view control */ + if(bnstate[0]) { + cam_theta += dx * 0.5; + cam_phi += dy * 0.5; + + if(cam_phi <= -90) cam_phi = -89; + if(cam_phi >= 90) cam_phi = 89; + + glutPostRedisplay(); + } + + if(bnstate[1]) { + cam_x += dx * 0.025; + cam_y += dy * 0.025; + glutPostRedisplay(); + } + + if(bnstate[2]) { + cam_dist += dy * 0.025; + if(cam_dist < 0.0) cam_dist = 0.0; + glutPostRedisplay(); + } + } +} + + +int parse_args(int argc, char **argv) +{ + int i; + char *endp; + + for(i=1; i cur_tex_xsz || tex_ysz > cur_tex_ysz) { + glBindTexture(GL_TEXTURE_2D, ray_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, 0); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, xsz, ysz, GL_RGB, GL_FLOAT, teximg); + delete [] teximg; + + if(tex_scale) { + tex_scale->x = (float)xsz / (float)tex_xsz; + tex_scale->y = (float)ysz / (float)tex_ysz; + } + raytex_needs_recalc = false; +} + +static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg) +{ + float vfov = M_PI * vfov_deg / 180.0; + float aspect = (float)w / (float)h; + + float ysz = 2.0; + float xsz = aspect * ysz; + + float px = ((float)x / (float)w) * xsz - xsz / 2.0; + float py = 1.0 - ((float)y / (float)h) * ysz; + float pz = 1.0 / tan(0.5 * vfov); + + float mag = sqrt(px * px + py * py + pz * pz); + return Vector3(px / mag, py / mag, pz / mag); +} + +static int round_pow2(int x) +{ + x--; + x = (x >> 1) | x; + x = (x >> 2) | x; + x = (x >> 4) | x; + x = (x >> 8) | x; + x = (x >> 16) | x; + return x + 1; +} + +static void create_transfer_map(float mean, float sdev) +{ + static float map[XFER_MAP_SZ]; + + if(!xfer_tex) { + glGenTextures(1, &xfer_tex); + glBindTexture(GL_TEXTURE_1D, xfer_tex); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE32F_ARB, XFER_MAP_SZ, 0, GL_LUMINANCE, GL_FLOAT, 0); + } + + for(int i=0; i -#include -#include -#include - -#ifndef __APPLE__ -#include -#else -#include -#endif - -#include -#include "volume.h" - -struct slice { - char *name; - struct slice *next; -}; - -static void calc_gradients(float *voxels, int xsz, int ysz, int zsz); -static struct slice *read_voldesc(const char *fname, struct volume *vol); -static char *trim(char *str); - -struct volume *load_volume(const char *fname) -{ - int i; - struct slice *slist; - struct volume *vol = 0; - float *voxels = 0, *vptr; - struct img_pixmap img; - - if(!(vol = malloc(sizeof *vol))) { - perror("failed to allocate volume"); - return 0; - } - memset(vol, 0, sizeof *vol); - vol->zaspect = 1; - - if(!(slist = read_voldesc(fname, vol))) { - goto err; - } - - /* load the first image to determine slice dimensions */ - img_init(&img); - if(img_load(&img, slist->name) == -1) { - fprintf(stderr, "failed to load volume slice: %s\n", slist->name); - goto err; - } - - vol->sz[0] = img.width; - vol->sz[1] = img.height; - printf("volume dimensions: %dx%dx%d\n", img.width, img.height, vol->sz[2]); - - /* allocate the whole volume at once */ - if(!(voxels = malloc(vol->sz[0] * vol->sz[1] * vol->sz[2] * 4 * sizeof *voxels))) { - img_destroy(&img); - goto err; - } - vptr = voxels; - img_destroy(&img); - - /* put the volume data into the alpha component */ - for(i=0; isz[2]; i++) { - int x, y, xsz, ysz; - float *pixels, *src; - struct slice *slice = slist; - slist = slist->next; - - if(!(pixels = img_load_pixels(slice->name, &xsz, &ysz, IMG_FMT_GREYF))) { - fprintf(stderr, "failed to load volume slice: %s\n", slice->name); - goto err; - } - - if(xsz != vol->sz[0] || ysz != vol->sz[1]) { - fprintf(stderr, "inconsistent dimensions for slice %s: %dx%d (%dx%d expected)\n", - slice->name, xsz, ysz, vol->sz[0], vol->sz[1]); - goto err; - } - free(slice->name); - free(slice); - - src = pixels; - for(y=0; ysz[0], vol->sz[1], vol->sz[2]); - - /* create the volume texture */ - glGenTextures(1, &vol->tex_vol); - glBindTexture(GL_TEXTURE_3D, vol->tex_vol); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F_ARB, vol->sz[0], vol->sz[1], vol->sz[2], 0, - GL_RGBA, GL_FLOAT, voxels); - - /* ... and destroy our copy */ - free(voxels); - return vol; - -err: - while(slist) { - struct slice *tmp = slist; - slist = slist->next; - free(tmp->name); - free(tmp); - } - free_volume(vol); - free(voxels); - return 0; -} - -void free_volume(struct volume *vol) -{ - if(vol) { - if(vol->tex_vol) { - glDeleteTextures(1, &vol->tex_vol); - } - free(vol); - } -} - -struct vec4 { float x, y, z, w; }; - -static void calc_gradients(float *voxels, int xsz, int ysz, int zsz) -{ - int x, y, z, slice_pixels = xsz * ysz; - struct vec4 *vptr = (struct vec4*)voxels; - - for(z=0; z 0 ? (vptr - 1)->w : vptr->w; - y0 = y > 0 ? (vptr - xsz)->w : vptr->w; - z0 = z > 0 ? (vptr - slice_pixels)->w : vptr->w; - x1 = x < xsz - 1 ? (vptr + 1)->w : vptr->w; - y1 = y < ysz - 1 ? (vptr + xsz)->w : vptr->w; - z1 = z < zsz - 1 ? (vptr + slice_pixels)->w : vptr->w; - - vptr->x = x1 - x0; - vptr->y = y1 - y0; - vptr->z = z1 - z0; - - vptr++; - } - } - } -} - -static struct slice *read_voldesc(const char *fname, struct volume *vol) -{ - FILE *fp = 0; - char buf[512], *slash, *prefix = ""; - int mode_slices = 0; - struct slice *head = 0, *tail; - - if(!(fp = fopen(fname, "r"))) { - fprintf(stderr, "failed to open volume descriptor: %s\n", fname); - return 0; - } - fgets(buf, sizeof buf, fp); - if(strstr(buf, "VOLDESC") != buf) { - fprintf(stderr, "invalid file format while trying to read volume descriptor: %s\n", fname); - goto err; - } - - if((slash = strrchr(fname, '/'))) { - int len = slash - fname + 1; - prefix = alloca(len + 1); - memcpy(prefix, fname, len); - prefix[len] = 0; - } - - while(fgets(buf, sizeof buf, fp)) { - char *line = trim(buf); - - if(!*line || *line == '#') - continue; - - if(mode_slices) { - /* we're in the part that contains filenames... append to the list */ - struct slice *node = malloc(sizeof *node); - if(!node || !(node->name = malloc(strlen(prefix) + strlen(line) + 1))) { - perror("failed to allocate list node"); - free(node); - goto err; - } - sprintf(node->name, "%s%s", prefix, line); - node->next = 0; - - if(head) { - tail->next = node; - tail = node; - } else { - head = tail = node; - } - vol->sz[2]++; - } else { - /* TODO we're in the options part... parse */ - - if(strcmp(line, "SLICES") == 0) { - mode_slices = 1; - } - } - } - fclose(fp); - - if(!vol->sz[2]) { - fprintf(stderr, "file: %s contains no slices\n", fname); - goto err; - } - - return head; - -err: - while(head) { - struct slice *tmp = head; - head = head->next; - free(tmp->name); - free(tmp); - } - if(fp) { - fclose(fp); - } - return 0; -} - -static char *trim(char *str) -{ - char *tmp = str + strlen(str) - 1; - - while(isspace(*tmp)) - tmp--; - tmp[1] = 0; - - tmp = str; - while(isspace(*tmp)) - tmp++; - return tmp; -} diff -r 9d2396738b60 -r 8990b5d2c7fe src/volume.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/volume.cc Mon Apr 09 23:42:57 2012 +0300 @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include + +#ifndef __APPLE__ +#include +#else +#include +#endif + +#include +#include "volume.h" + +static void calc_gradients(float *voxels, int xsz, int ysz, int zsz); +static struct slice *read_voldesc(const char *fname, struct volume *vol); +static char *trim(char *str); + +Volume::Volume() +{ + sz[0] = sz[1] = sz[2] = 0; + zaspect = 1.0; + tex = 0; +} + +Volume::~Volume() +{ + if(tex) { + glDeleteTextures(1, &tex); + } +} + +bool Volume::load(const char *fname) +{ + std::list slist; + float *voxels = 0, *vptr; + struct img_pixmap img; + + if(!(read_voldesc(fname, &slist))) { + return false; + } + + /* load the first image to determine slice dimensions */ + img_init(&img); + if(img_load(&img, slist.begin().name.c_str()) == -1) { + fprintf(stderr, "failed to load volume slice: %s\n", slist->name); + return false; + } + + sz[0] = img.width; + sz[1] = img.height; + printf("volume dimensions: %dx%dx%d\n", img.width, img.height, vol->sz[2]); + + /* allocate the whole volume at once */ + voxels = new float[sz[0] * sz[1] * sz[2] * 4]; + vptr = voxels; + img_destroy(&img); + + /* put the volume data into the alpha component */ + for(auto slice : slist) { + int x, y, xsz, ysz; + float *pixels, *src; + + if(!(pixels = img_load_pixels(slice.name.c_str(), &xsz, &ysz, IMG_FMT_GREYF))) { + fprintf(stderr, "failed to load volume slice: %s\n", slice.name.c_str()); + delete [] voxels; + return false; + } + + if(xsz != sz[0] || ysz != sz[1]) { + fprintf(stderr, "inconsistent dimensions for slice %s: %dx%d (%dx%d expected)\n", + slice.name.c_str(), xsz, ysz, sz[0], sz[1]); + delete [] voxels; + return false; + } + + src = pixels; + for(y=0; y 0 ? (vptr - 1)->w : vptr->w; + y0 = y > 0 ? (vptr - xsz)->w : vptr->w; + z0 = z > 0 ? (vptr - slice_pixels)->w : vptr->w; + x1 = x < xsz - 1 ? (vptr + 1)->w : vptr->w; + y1 = y < ysz - 1 ? (vptr + xsz)->w : vptr->w; + z1 = z < zsz - 1 ? (vptr + slice_pixels)->w : vptr->w; + + vptr->x = x1 - x0; + vptr->y = y1 - y0; + vptr->z = z1 - z0; + + vptr++; + } + } + } +} + +bool read_voldesc(const char *fname, std::list *slist) const +{ + FILE *fp = 0; + char buf[512], *slash, *prefix = ""; + int mode_slices = 0; + + slist->clear(); + + if(!(fp = fopen(fname, "r"))) { + fprintf(stderr, "failed to open volume descriptor: %s\n", fname); + return false; + } + fgets(buf, sizeof buf, fp); + if(strstr(buf, "VOLDESC") != buf) { + fprintf(stderr, "invalid file format while trying to read volume descriptor: %s\n", fname); + fclose(fp); + return false; + } + + if((slash = strrchr(fname, '/'))) { + int len = slash - fname + 1; + prefix = alloca(len + 1); + memcpy(prefix, fname, len); + prefix[len] = 0; + } + + while(fgets(buf, sizeof buf, fp)) { + char *line = trim(buf); + + if(!*line || *line == '#') + continue; + + if(mode_slices) { + /* we're in the part that contains filenames... append to the list */ + slist->push_back(std::string(prefix) + std::string(line)); + sz[2]++; + } else { + /* TODO we're in the options part... parse */ + if(strcmp(line, "SLICES") == 0) { + mode_slices = 1; + } + } + } + fclose(fp); + + if(slist->empty()) { + fprintf(stderr, "file: %s contains no slices\n", fname); + return false; + } + return true; +} + +static char *trim(char *str) +{ + char *tmp = str + strlen(str) - 1; + + while(isspace(*tmp)) + tmp--; + tmp[1] = 0; + + tmp = str; + while(isspace(*tmp)) + tmp++; + return tmp; +} diff -r 9d2396738b60 -r 8990b5d2c7fe src/volume.h --- a/src/volume.h Sun Apr 08 14:31:03 2012 +0300 +++ b/src/volume.h Mon Apr 09 23:42:57 2012 +0300 @@ -1,15 +1,25 @@ #ifndef VOLUME_H_ #define VOLUME_H_ -#include +#include +#include -struct volume { +class Volume { +private: int sz[3]; float zaspect; - unsigned int tex_vol; + unsigned int tex; + + bool read_voldesc(const char *fname, std::list *slist) const; + +public: + Volume(); + ~Volume(); + + bool load(const char *fname); + + unsigned int get_texture() const; + void bind(int tex_unit = 0) const; }; -struct volume *load_volume(const char *fname); -void free_volume(struct volume *vol); - #endif /* VOLUME_H_ */