Volume Rendering problem

Started by
1 comment, last by fcoutel 19 years, 3 months ago
Hi! I have a problem with the code below. It loads a model in rvf format and render it using 2D textures. The problem is that when I use modify the opacity of the color palette, the model disappears and I can't find why. Note that I am running it on Linux RHEL 3.0 with ATI9200 graphics card (direct rendering enabled). I can send the project by email if necessary. Many thanks.



/*
 * file  : volume.c

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <GL/glut.h>
#include "texture3d.h"
#include "tga.h"
#include "bmp.h"

/* display list */
#define Z_FRONT 1
#define Z_BACK  2
#define Y_FRONT 3
#define Y_BACK  4
#define X_FRONT 5
#define X_BACK  6

/* palette */
#define PALETTE_SIZE    32
#define PALETTE_XOFFSET  5
#define PALETTE_YOFFSET  5

/* mouse mode */
#define ROTATION        1
#define COLOR_SELECTION 2

/* globals */
int   xs=500,ys=400;
/* BLEND and DEPTH_TEST */
int   alpha=1,depth=0;
int   drawCube=1,projection=1;
int   s1,s2,s3;
/* rotation & mouse */
float scaleFactor=1.;
int   oldx=0,oldy=0,xrot=0,yrot=0;
int   dx,dy;
int   inverseZ=1;
int   mode=ROTATION;
int   color_1,color_2;
/* texture */
tex3   tex;
int    px,py,pz;
GLuint *XTextureId;
GLuint *YTextureId;
GLuint *ZTextureId;
unsigned char *tex_buf;
/* palette */
char   *palname="default.pal";
GLuint checkerId;
unsigned char *pal;
unsigned char *reset_pal;
//char *filename="vht.rvf";
char *filename="brainsmall.rvf";
//char *filename="teddybear.raw"; // 128*128*62
//char   *filename="head.raw";
//char *filename="engine.raw";
//char* filename="nucleon.raw";
//char *filename="CT_Head_small.raw";
/* profiling */
int frame=0;
int oldtime=0;





int power[10]={
	1,2,4,8,16,32,64,128,256,512};

/* find the nearest power of two after t */
int nextPower(int t){
	int i;
	for(i=0;i<10;i++){
		if (power>=t)
			return power;
	}
	return 512;
}

/* load a nice default palette */
void load_default_palette(unsigned char *pal){
	int i;
	for(i=0;i<85;i++){
		pal[4*i+0]=i*3;
		pal[4*i+1]=0;
		pal[4*i+2]=0;
		pal[4*i+3]=i;
	}
	for(i=0;i<85;i++){
		pal[4*(i+85)+0]=255;
		pal[4*(i+85)+1]=i*3;
		pal[4*(i+85)+2]=0;
		pal[4*(i+85)+3]=i+85;
	}
	for(i=0;i<86;i++){
		pal[4*(i+85+85)+0]=(85-i)*3;
		pal[4*(i+85+85)+1]=255;
		pal[4*(i+85+85)+2]=i*3;
		pal[4*(i+85+85)+3]=i+85+85;
	}
}

/* load a palette from an ASCII file (unix's return style )*/
int load_palette(char *name,unsigned char *c){
	FILE *fp;
	int index=0;
	fp=fopen(name,"r");
	if (fp==NULL)
		return -1;
	while(fscanf(fp,"%d %d %d %d",c+index*4+0,c+index*4+1,c+index*4+2,c+index*4+3)==4){
		//		glutSetColor(index,(float)c[index*4]/256.,(float)c[index*4+1]/256.,(float)c[index*4+2]/256.);
		index++;
	}
	fclose(fp);
	return index!=256;
}

/* make the palette from c1 to c2 transparent */
void zeroAlpha(unsigned char *c,int c1,int c2){
	int i;
	if (c1>c2){
		i=c1;
		c1=c2;
		c2=i;
	}
	for(i=c1;i<=c2;i++){
		c[i*4+3]=0;
	}
}

/* reset the palette from c1 to c2 */
void resetAlpha(unsigned char *c,int c1,int c2){
	int i;
	if (c1>c2){
		i=c1;
		c1=c2;
		c2=i;
	}
	for(i=c1;i<=c2;i++){
		c[i*4+3]=reset_pal[i*4+3];
	}
}


void init_palette(){
	/* try to load the palette */
	pal=(unsigned char*)malloc(256*4);
	if (pal==NULL){
		fprintf(stderr,"Out of memory\n");
		exit(-1);
	}
	reset_pal=(unsigned char *)malloc(4*256);
	if (reset_pal==NULL){
		fprintf(stderr,"load_default_palette() : Out of memory\n");
		exit(-1);
	}
	if (load_palette(palname,reset_pal)){
		printf("no palette found (making default)\n");
		load_default_palette(reset_pal);
	}
	/* copy it */
	memcpy(pal,reset_pal,4*256);
	
	// test opacity
	zeroAlpha(pal,0,20);
	zeroAlpha(pal,240,255);
}

/* load a volume and create slices of it */
void load_tex(char *name){
	unsigned char *checker_buf;
	int i,j,k;
	float x,y,z;

	init_palette();
	/* load it */
	printf("loading 3d texture '%s' ... ",name);
	fflush(stdout);
	//	if (load_raw(&tex,name,128,128,62)){
	if (load_rvf(&tex,name)){
		fprintf(stderr,"abort\n");
		exit(-1);
	}
	px=nextPower(tex.x);
	py=nextPower(tex.y);
	pz=nextPower(tex.z);
	printf("done (%dx%dx%d)->(%dx%dx%d)\n",tex.x,tex.y,tex.z,px,py,pz);
	/* ask for some textures */
	XTextureId=(GLuint *)malloc(sizeof(GLuint)*tex.x);
	if (XTextureId==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	YTextureId=(GLuint *)malloc(sizeof(GLuint)*tex.y);
	if (YTextureId==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	ZTextureId=(GLuint *)malloc(sizeof(GLuint)*tex.z);
	if (ZTextureId==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}

	/* generate textures */
	glGenTextures(tex.x,XTextureId);
	glGenTextures(tex.y,YTextureId);
	glGenTextures(tex.z,ZTextureId);
	glGenTextures(1,&checkerId);

	/* create slices */
	printf("creating slices [");
	fflush(stdout);

	/* xy slices */
	/* allocate a texture buffer */
	tex_buf=(unsigned char *)calloc(4*px*py,1);
	if (tex_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}

	/* xy-->z */
	for (k=0;k<tex.z;k+=1){
		if (floor(10.*k/tex.z)==(10.*k/tex.z)){
			printf("#");
			fflush(stdout);
		}
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glBindTexture(GL_TEXTURE_2D,ZTextureId[k]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		for(i=0;i<tex.x;i++){
			for(j=0;j<tex.y;j++){
				tex_buf[(i+j*px)*4+0]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+0];
				tex_buf[(i+j*px)*4+1]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+1];
				tex_buf[(i+j*px)*4+2]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+2];
				tex_buf[(i+j*px)*4+3]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+3];
			}
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, px,py,0,GL_RGBA,GL_UNSIGNED_BYTE,tex_buf);
	}
	free(tex_buf);
	printf("|");
	fflush(stdout);

	/* yz slices */
	/* allocate a new texture buffer */

	tex_buf=(unsigned char *)calloc(4*pz*py,1);
	memset(tex_buf,0,4*pz*py);
	if (tex_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	/* zy-->x */
	for (i=0;i<tex.x;i+=1){
		if (floor(10.*i/tex.x)==(10.*i/tex.x)){
			printf("#");
			fflush(stdout);
		}
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glBindTexture(GL_TEXTURE_2D,XTextureId);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		for(k=0;k<tex.z;k++){
			for(j=0;j<tex.y;j++){
				tex_buf[(k+j*pz)*4+0]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+0];
				tex_buf[(k+j*pz)*4+1]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+1];
				tex_buf[(k+j*pz)*4+2]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+2];
				tex_buf[(k+j*pz)*4+3]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+3];
			}
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pz,py,0,GL_RGBA,GL_UNSIGNED_BYTE,tex_buf);
	}
	free(tex_buf);
	printf("|");
	fflush(stdout);

	/* xz slices */
	/* allocate a new texture buffer */

	tex_buf=(unsigned char *)calloc(4*pz*px,1);
	if (tex_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	/* xz-->y */
	for (j=0;j<tex.y;j+=1){
		if (floor(10.*j/tex.y)==(10.*j/tex.y)){
			printf("#");
			fflush(stdout);
		}
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glBindTexture(GL_TEXTURE_2D,YTextureId[j]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		for(k=0;k<tex.z;k++){
			for(i=0;i<tex.x;i++){
				tex_buf[(i+k*px)*4+0]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+0];
				tex_buf[(i+k*px)*4+1]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+1];
				tex_buf[(i+k*px)*4+2]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+2];
				tex_buf[(i+k*px)*4+3]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+3];
			}
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, px,pz,0,GL_RGBA,GL_UNSIGNED_BYTE,tex_buf);
	}
	free(tex_buf);

	printf("] done\n");
	fflush(stdout);


	/* a nice checker texture for the palette's background */
	checker_buf=(unsigned char *)malloc(4*PALETTE_SIZE*256);
	if (checker_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glBindTexture(GL_TEXTURE_2D,checkerId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	for(i=0;i<PALETTE_SIZE;i++){
		for(j=0;j<256;j++){
			int a,b,c,step;
			step=8;
			a=!((i/step)%2*255);
			b=((j/step)%2*255);
			c=a?(b?255:0):
			(b?0:255);
			checker_buf[(i+j*PALETTE_SIZE)*4+0]=c;
			checker_buf[(i+j*PALETTE_SIZE)*4+1]=c;
			checker_buf[(i+j*PALETTE_SIZE)*4+2]=c;
			checker_buf[(i+j*PALETTE_SIZE)*4+3]=(!c)*255;
		}
	}
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,PALETTE_SIZE,256,0,GL_RGBA,GL_UNSIGNED_BYTE,checker_buf);
	free(checker_buf);

	/* display lists */
	printf("making the display list ... ");
	fflush(stdout);
	/* We must draw slices from back to front in order to have a correct blending.
	* That's why we have to create a list for each case
	*/
	glNewList(Z_FRONT,GL_COMPILE);
	for(k=pz-tex.z;k<pz;k++){
		z=1.-2.*k/pz;
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,ZTextureId[pz-k-1]);
		glBegin(GL_QUADS);
		glTexCoord2f(0,1);
		glVertex3f(-1,1,z);
		glTexCoord2f(1,1);
		glVertex3f(1,1,z);
		glTexCoord2f(1,0);
		glVertex3f(1,-1,z);
		glTexCoord2f(0,0);
		glVertex3f(-1,-1,z);
		glEnd();
	}
	glEndList();

	glNewList(Z_BACK,GL_COMPILE);
	for(k=pz;k>(pz-tex.z);k--){
		z=1.-2.*k/pz;
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,ZTextureId[pz-k]);
		glBegin(GL_QUADS);
		glTexCoord2f(0,1);
		glVertex3f(-1,1,z);
		glTexCoord2f(1,1);
		glVertex3f(1,1,z);
		glTexCoord2f(1,0);
		glVertex3f(1,-1,z);
		glTexCoord2f(0,0);
		glVertex3f(-1,-1,z);
		glEnd();
	}
	glEndList();

	glNewList(X_FRONT,GL_COMPILE);
	for(i=px;i>(px-tex.x);i--){
		x=-1.+2.*i/px;
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,XTextureId[tex.x-px+i-1]);
		glBegin(GL_QUADS);
		glTexCoord2f(0,0);
		glVertex3f(x,-1,-1);
		glTexCoord2f(0,1);
		glVertex3f(x,1,-1);
		glTexCoord2f(1,1);
		glVertex3f(x,1,1);
		glTexCoord2f(1,0);
		glVertex3f(x,-1,1);
		glEnd();
	}
	glEndList();

	glNewList(X_BACK,GL_COMPILE);
	for(i=px;i>(px-tex.x);i--){
		x=1.-2.*i/px;
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,XTextureId[px-i]);
		glBegin(GL_QUADS);
 		glTexCoord2f(0,0);
		glVertex3f(x,-1,-1);
		glTexCoord2f(0,1);
		glVertex3f(x,1,-1);
		glTexCoord2f(1,1);
		glVertex3f(x,1,1);
		glTexCoord2f(1,0);
		glVertex3f(x,-1,1);
		glEnd();
	}
	glEndList();

	glNewList(Y_FRONT,GL_COMPILE);
	for(j=py;j>(py-tex.y);j--){
		y=-1.+2.*j/py;
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,YTextureId[tex.y-py+j-1]);
		glBegin(GL_QUADS);
		glTexCoord2f(0,0);
		glVertex3f(-1,y,-1);
		glTexCoord2f(0,1);
		glVertex3f(-1,y,1);
		glTexCoord2f(1,1);
		glVertex3f(1,y,1);
		glTexCoord2f(1,0);
		glVertex3f(1,y,-1);
		glEnd();
	}
	glEndList();

	glNewList(Y_BACK,GL_COMPILE);
	for(j=py;j>(py-tex.y);j--){
		y=1.-2.*j/py;
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,YTextureId[py-j]);
		glBegin(GL_QUADS);
		glTexCoord2f(0,0);
		glVertex3f(-1,y,-1);
		glTexCoord2f(0,1);
		glVertex3f(-1,y,1);
		glTexCoord2f(1,1);
		glVertex3f(1,y,1);
		glTexCoord2f(1,0);
		glVertex3f(1,y,-1);
		glEnd();
	}
	glEndList();

	printf("done\n");
}

/* my nvidia tnt2 doesn't have the paletted texture extension */
void update_tex(){
	int i,j,k;
//	float x,y,z;

	/* delete old textures */
	printf("updating 3d texture ... [");
	fflush(stdout);
	glDeleteTextures(tex.x,XTextureId);
	glDeleteTextures(tex.y,YTextureId);
	glDeleteTextures(tex.z,ZTextureId);
	if (XTextureId==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	if (YTextureId==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	if (ZTextureId==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	/* generate textures */
	glGenTextures(tex.x,XTextureId);
	glGenTextures(tex.y,YTextureId);
	glGenTextures(tex.z,ZTextureId);

	// xy-->z
	tex_buf=(unsigned char *)calloc(4*px*py,1);
	memset(tex_buf,0,4*px*py);
	if (tex_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}

	for (k=0;k<tex.z;k+=1){
		if (floor(10.*k/tex.z)==10.*k/tex.z){
			printf("#");
			fflush(stdout);
		}
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glBindTexture(GL_TEXTURE_2D,ZTextureId[k]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		for(i=0;i<tex.x;i++){
			for(j=0;j<tex.y;j++){
				tex_buf[(i+j*px)*4+0]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+0];
				tex_buf[(i+j*px)*4+1]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+1];
				tex_buf[(i+j*px)*4+2]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+2];
				tex_buf[(i+j*px)*4+3]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+3];
			}
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, px,py,0,GL_RGBA,GL_UNSIGNED_BYTE,tex_buf);
	}
	free(tex_buf);

	// zy-->x
	tex_buf=(unsigned char *)calloc(4*pz*py,1);
	memset(tex_buf,0,4*pz*py);
	if (tex_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	for (i=0;i<tex.x;i+=1){
		if (floor(10.*i/tex.x)==10.*i/tex.x){
			printf("#");
			fflush(stdout);
		}
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glBindTexture(GL_TEXTURE_2D,XTextureId);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		for(k=0;k<tex.z;k++){
			for(j=0;j<tex.y;j++){
				tex_buf[(k+j*pz)*4+0]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+0];
				tex_buf[(k+j*pz)*4+1]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+1];
				tex_buf[(k+j*pz)*4+2]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+2];
				tex_buf[(k+j*pz)*4+3]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+3];
			}
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pz,py,0,GL_RGBA,GL_UNSIGNED_BYTE,tex_buf);
	}
	free(tex_buf);

	tex_buf=(unsigned char *)calloc(4*pz*px,1);
	memset(tex_buf,0,4*pz*px);
	if (tex_buf==NULL){
		fprintf(stderr,"load_tex() : Out of memory\n");
		exit(-1);
	}
	// xz-->y
	for (j=0;
	j<tex.y;
	j+=1){
		if (floor(10.*j/tex.y)==10.*j/tex.y){
			printf("#");
			fflush(stdout);
		}
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glBindTexture(GL_TEXTURE_2D,YTextureId[j]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		for(k=0;k<tex.z;k++){
			for(i=0;i<tex.x;i++){
				tex_buf[(i+k*px)*4+0]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+0];
				tex_buf[(i+k*px)*4+1]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+1];
				tex_buf[(i+k*px)*4+2]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+2];
				tex_buf[(i+k*px)*4+3]=pal[tex.texture[i+tex.x*(j+tex.y*k)]*4+3];
			}
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, px,pz,0,GL_RGBA,GL_UNSIGNED_BYTE,tex_buf);
	}
	free(tex_buf);

	printf("] done\n");
	
}

/* draw the palette */
void drawPalette(unsigned char *pal){
	int i;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0,xs,0,ys,0.001,1000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glColor3f(0.5,0.5,0.5);
	/* background */
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,checkerId);
	glBegin(GL_QUADS);
	glTexCoord2f(0,1);
	glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET,PALETTE_YOFFSET,-1);
	glTexCoord2f(1,1);
	glVertex3f(xs-PALETTE_XOFFSET,PALETTE_YOFFSET,-1);
	glTexCoord2f(1,0);
	glVertex3f(xs-PALETTE_XOFFSET,256+PALETTE_YOFFSET,-1);
	glTexCoord2f(0,0);
	glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET,256+PALETTE_YOFFSET,-1);
	glEnd();
	glDisable(GL_TEXTURE_2D);
	/* palette */
	for(i=0;i<256;i++){
		glColor4ub(pal[i*4+0],pal[i*4+1],pal[i*4+2],pal[i*4+3]);
		glBegin(GL_LINES);
		glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET,i+PALETTE_YOFFSET,-1);
		glVertex3f(xs-PALETTE_XOFFSET,i+PALETTE_YOFFSET,-1);
		glEnd();
	}
	glColor3f(0,0,0);
	glBegin(GL_LINE_LOOP);
	glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET-3,PALETTE_YOFFSET-3,-1);
	glVertex3f(xs-PALETTE_XOFFSET+3,PALETTE_YOFFSET-3,-1);
	glVertex3f(xs-PALETTE_XOFFSET+3,256+PALETTE_YOFFSET+3,-1);
	glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET-3,256+PALETTE_YOFFSET+3,-1);
	glEnd();
	/* selection */
	if (mode==COLOR_SELECTION){
		glColor3f(0,0,0);
		glBegin(GL_LINE_LOOP);
		glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET,color_1+PALETTE_YOFFSET,-1);
		glVertex3f(xs-PALETTE_XOFFSET,color_1+PALETTE_YOFFSET,-1);
		glVertex3f(xs-PALETTE_XOFFSET,color_2+PALETTE_YOFFSET,-1);
		glVertex3f(xs-PALETTE_SIZE-PALETTE_XOFFSET,color_2+PALETTE_YOFFSET,-1);
		glEnd();
	}
}

void draw(){
//	float z;
//	int k;

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (projection)
		gluPerspective(40.,(float)(xs-PALETTE_SIZE)/(float)ys,0.1,1000);
	else
		glOrtho(-2,2,-2,2,0,1000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0,2,-5,0,0,0,0,1,0);
	glRotatef(yrot,-1,0,0);
	glRotatef(xrot,0,1,0);
	glScalef(scaleFactor,(inverseZ?-1:1)*scaleFactor,scaleFactor);

	glEnable(GL_TEXTURE_2D);
	glColor3f(1,1,1);
	/* select which set of slices we should draw */
	if (yrot>23&&yrot<(23+90)){
		glCallList(Y_FRONT);
	}
	else{
		if (yrot<293&&yrot>(293-90)){
			glCallList(Y_BACK);
		}
		else{
			if (xrot>=315||xrot<=45){
				glCallList(Z_FRONT);
			}
			else {
				if (xrot>=135&&xrot<=225){
					glCallList(Z_BACK);
				}
				else{
					if (xrot>=45&&xrot<=135){
						glCallList(X_BACK);
					}
					else {
						glCallList(X_FRONT);
					}
				}
			}
		}
	}
	/* cube */
	if (drawCube){
		glDisable(GL_TEXTURE_2D);
		glColor3f(0,0,0);
		glLineWidth(1.5);
		glutWireCube(2);
	}
	/* palette */
	drawPalette(pal);
	glutSwapBuffers();
	frame++;
}


void reshape(int w, int h){
	xs=w;
	ys=h;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (projection)
		gluPerspective(40.,(float)(w-PALETTE_SIZE)/(float)h,0.1,1000);
	else
		glOrtho(-2,2,-2,2,0,1000);
	glEnable(GL_TEXTURE_2D);
}

void mouse(int b,int state,int x,int y){
	if(state == GLUT_DOWN) {
		color_1=ys-y-PALETTE_YOFFSET;
		if (x>(xs-PALETTE_SIZE-PALETTE_XOFFSET)&&x<(xs-PALETTE_XOFFSET)){
			if (color_1>=0&&color_1<256){
				mode=COLOR_SELECTION;
				color_2=color_1;
				return;
			}
		}
		mode=ROTATION;
		oldx = x;
		oldy = y;
	}
	if (state==GLUT_UP){
		if (mode==COLOR_SELECTION){
			color_2=ys-y-PALETTE_YOFFSET;
			if (color_2<0)
				color_2=0;
			else
			    if (color_2>255)
				color_2=255;
			/* make the selection transparent */
			if (b==GLUT_LEFT_BUTTON)
				zeroAlpha(pal,color_1,color_2);
			if (b==GLUT_RIGHT_BUTTON)
				resetAlpha(pal,color_1,color_2);
			mode=ROTATION;
			update_tex();
		}
	}
	draw();
}

void motion(int x, int y) {
	if (mode==ROTATION){
		dx = x - oldx;
		dy = y - oldy;
		oldx = x;
		oldy = y;
		xrot+=dx/2;
		yrot+=dy/2;
		xrot=xrot<0?(xrot%360)+360:xrot%360;
		yrot=yrot<0?(yrot%360)+360:yrot%360;
	}
	if (mode==COLOR_SELECTION){
		color_2=ys-y-PALETTE_YOFFSET;
		if (color_2<0)
			color_2=0;
		else
		    if (color_2>255)
			color_2=255;
	}
	draw();
}

void idle(){
	char title[256];
	if (clock()-oldtime>CLOCKS_PER_SEC){
		sprintf(title,"Volume rendering with gl (%dfps)",frame);
		glutSetWindowTitle(title);
		frame=0;
		oldtime=clock();
	}
//	draw();
}

void keyboard(unsigned char key, int x, int y){
//	tga_t tga;
	bmp_t bmp;
	unsigned char *buf;
	char fn[256];
	static int id=0;

	switch (key) {
	case 'h':
		printf("    - take a snapshot \n");
		printf(" [+|-] - zoom \n");
		printf(" [c]   - toggle axis \n");
		printf(" <p>   - toggle projection mode\n");
		printf(" [z]   - inverse z axis\n");
		printf(" [r]   - reset palette\n");
		break;
	case 's':
		init_bmp(&bmp,xs,ys,24);
		buf=(unsigned char*)malloc(3*xs*ys);
		if (buf==NULL){
			fprintf(stderr,"Out of memory\n");
			return;
		}
		glReadPixels(0, 0,xs,ys,GL_RGB,GL_UNSIGNED_BYTE, buf);
		sprintf(fn,"%s.%02d.bmp",filename,id);
		save_bmp(bmp,buf,fn);
		free(buf);
		id++;
		break;
	case '+':
		scaleFactor+=0.2;
		glutPostRedisplay();
		break;
	case '-':
		scaleFactor-=0.2;
		glutPostRedisplay();
		break;
	case 'a':
		if (alpha=!alpha)
			glEnable(GL_BLEND);
		else
		    glDisable(GL_BLEND);
		glutPostRedisplay();
		printf("alpha [%s]\n",alpha?"on":"off");
		break;
	case 'd':
		if (depth=!depth)
			glEnable(GL_DEPTH_TEST);
		else
		    glDisable(GL_DEPTH_TEST);
		glutPostRedisplay();
		printf("depth [%s]\n",depth?"on":"off");
		break;
	case 'c':
		printf("cube [%s]\n",(drawCube=!drawCube)?"on":"off");
		glutPostRedisplay();
		break;
	case 'p':
		printf("projection [%s]\n",(projection=!projection)?"perspective":"orthogonal");
		reshape(xs,ys);
		glutPostRedisplay();
		break;
	case 'z':
		printf("z [%s]\n",(inverseZ=!inverseZ)?"on":"off");
		glutPostRedisplay();
		break;
	case 'r':
		printf("reset palette\n");
		memcpy(pal,reset_pal,256*4);
		update_tex();
		break;
	case 27:
		if (tex.texture)
			free(tex.texture);
		exit(0);
		break;
	}
}


int main(int argc, char** argv){
	glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);

/*	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);*/
	glutInitWindowSize (xs,ys);
	glutInitWindowPosition (0,0);
	glutCreateWindow("Volume rendering with gl");
	glutReshapeFunc(reshape);
	glutDisplayFunc(draw);
	glutMouseFunc(mouse);
	glutMotionFunc(motion);
	glutKeyboardFunc (keyboard);
	glutIdleFunc(idle);
	/* enable transparency */
	glEnable(GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	/* disable depth test */
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);
	/* check if there is an argument */
	filename=argc&gt;1?argv[1]:filename;
	/* load the volume */
	load_tex(filename);
	/* I like this color */
	glClearColor(1,1,1,1);
	glutMainLoop();
	return 0;
}

</pre>
Advertisement
first of all, no one is going to look at it as is, add [_source_] [_/source_] tags (with out the underscores) around your code, but also, no one WANTS to go through line after line of your(?) code, if nothing else, point us to certain portions of it to show us where you think the problem is and that youve done work on it before (well, youve doen that to some extent) but seriously large chunks of code scare people away

hope that helps
-Dan
When General Patton died after World War 2 he went to the gates of Heaven to talk to St. Peter. The first thing he asked is if there were any Marines in heaven. St. Peter told him no, Marines are too rowdy for heaven. He then asked why Patton wanted to know. Patton told him he was sick of the Marines overshadowing the Army because they did more with less and were all hard-core sons of bitches. St. Peter reassured him there were no Marines so Patton went into Heaven. As he was checking out his new home he rounded a corner and saw someone in Marine Dress Blues. He ran back to St. Peter and yelled "You lied to me! There are Marines in heaven!" St. Peter said "Who him? That's just God. He wishes he were a Marine."
On the contrary I thought that someone would like to see most of the code, plus it is fairly short!
Anyways I think the problem comes from the function update_tex() which is called when the opacity is changed. I can't see what's wrong with it.

Thanks,

This topic is closed to new replies.

Advertisement