Blame view

stim/gl/gl_texture.h 8.77 KB
197e13de   Pavel Govyadinov   Added new class g...
1
2
3
  #ifndef STIM_GL_TEXTURE_H
  #define STIM_GL_TEXTURE_H
  
197e13de   Pavel Govyadinov   Added new class g...
4
5
  #include <math.h>
  #include <iostream>
197e13de   Pavel Govyadinov   Added new class g...
6
  #include <vector>
197e13de   Pavel Govyadinov   Added new class g...
7
  #include "../grids/image_stack.h"
26da82c8   David Mayerich   finalized stim::g...
8
9
10
11
12
  //Visual Studio requires GLEW
  #ifdef _WIN32
  	#include <GL/glew.h>
  #endif
  //#include <GL/glut.h>
983b730b   David Mayerich   texture updates
13
  #include <stim/gl/error.h>	
197e13de   Pavel Govyadinov   Added new class g...
14
15
  namespace stim{
  
a4042c24   Pavel Govyadinov   Updated the gl_te...
16
17
18
19
20
  /*
  class gl_texture
  	Uses image_stack class in order to create a texture object.
  */
  
26da82c8   David Mayerich   finalized stim::g...
21
22
  template<typename T, typename F = float>
  class gl_texture : public virtual image_stack<T, F>
197e13de   Pavel Govyadinov   Added new class g...
23
  {
197e13de   Pavel Govyadinov   Added new class g...
24
  	protected:
983b730b   David Mayerich   texture updates
25
  		//std::string path;
372b5963   Pavel Govyadinov   added support for...
26
27
  		GLuint texID;				//OpenGL object
  		GLenum texture_type;			//1D, 2D, 3D
26da82c8   David Mayerich   finalized stim::g...
28
29
30
31
32
  		GLint interpolation;
  		GLint wrap;	
  		GLenum cpu_type;
  		GLenum gpu_type;
  		GLenum format;					//format for the texture (GL_RGBA, GL_LUMINANCE, etc.)
a4042c24   Pavel Govyadinov   Updated the gl_te...
33
  		using image_stack<T>::R;
26da82c8   David Mayerich   finalized stim::g...
34
  		//using image_stack<T>::S;
a4042c24   Pavel Govyadinov   Updated the gl_te...
35
  		using image_stack<T>::ptr;
197e13de   Pavel Govyadinov   Added new class g...
36
  
983b730b   David Mayerich   texture updates
37
38
39
40
41
42
43
44
45
46
47
48
49
  		///	Sets the internal texture_type, based on the data dimensions
  		void setTextureType(){
  			if (R[3] > 1)						//if the third dimension is greater than 1
  				texture_type = GL_TEXTURE_3D;	//this is a 3D texture
  			else if (R[2] > 1)					//if the second dimension is greater than 1
  				texture_type = GL_TEXTURE_2D;	//this is a 2D texture
  			else if (R[1] > 1)					//if the dimension value is greater than 1
  				texture_type = GL_TEXTURE_1D;	//this is a 1D texture
  		}
  
  		//initializes important variables
  		void init() {
  			texID = 0;							//initialize texture ID to zero, default if OpenGL returns an error
26da82c8   David Mayerich   finalized stim::g...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  			memset(R, 0, sizeof(size_t));
  			memset(S, 0, sizeof(F));
  		}
  
  		//guesses the color format of the texture
  		GLenum guess_format(){
  			size_t channels = R[0];
  			switch(channels){
  			case 1:
  				return GL_LUMINANCE;
  			case 2:
  				return GL_RG;
  			case 3:
  				return GL_RGB;
  			case 4:
  				return GL_RGBA;
  			default:
  				std::cout<<"Error in stim::gl_texture - unable to guess texture format based on number of channels ("<<R[4]<<")"<<std::endl;
  				exit(1);
  			}
  		}
  
  		//guesses the OpenGL CPU data type based on T
  		GLenum guess_cpu_type(){
  			// The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution
  
  			//if(std::is_same<T, unsigned char>::value)	return CV_MAKETYPE(CV_8U, (int)C());
  			//if(std::is_same<T, char>::value)			return CV_MAKETYPE(CV_8S, (int)C());
  			//if(std::is_same<T, unsigned short>::value)	return CV_MAKETYPE(CV_16U, (int)C());
  			//if(std::is_same<T, short>::value)			return CV_MAKETYPE(CV_16S, (int)C());
  			//if(std::is_same<T, int>::value)				return CV_MAKETYPE(CV_32S, (int)C());
  			//if(std::is_same<T, float>::value)			return CV_MAKETYPE(CV_32F, (int)C());
  			//if(std::is_same<T, double>::value)			return CV_MAKETYPE(CV_64F, (int)C());
  
  			if(typeid(T) == typeid(unsigned char))		return GL_UNSIGNED_BYTE;
  			if(typeid(T) == typeid(char))				return GL_BYTE;
  			if(typeid(T) == typeid(unsigned short))		return GL_UNSIGNED_SHORT;
  			if(typeid(T) == typeid(short))				return GL_SHORT;
  			if(typeid(T) == typeid(unsigned int))		return GL_UNSIGNED_INT;
  			if(typeid(T) == typeid(int))				return GL_INT;
  			if(typeid(T) == typeid(float))				return GL_FLOAT;
  
  			std::cout<<"ERROR in stim::gl_texture - no valid data type found"<<std::endl;
  			exit(1);
  		}
  
  		//Guesses the "internal format" of the texture to closely approximate the original format
  		GLint guess_gpu_type(){
  			switch(format){
  			case GL_LUMINANCE:
  				switch(cpu_type){
  				case GL_BYTE:
  				case GL_UNSIGNED_BYTE:
  					return GL_LUMINANCE8;
  				case GL_SHORT:
  				case GL_UNSIGNED_SHORT:
  					return GL_LUMINANCE16;
  				case GL_INT:
  				case GL_UNSIGNED_INT:
  					return GL_LUMINANCE32I_EXT;
  				case GL_FLOAT:
  					return GL_LUMINANCE32F_ARB;
  				default:
  					std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl;
  					exit(1);
  				}
  			case GL_RGB:
  				switch(cpu_type){
  				case GL_BYTE:
  				case GL_UNSIGNED_BYTE:
  					return GL_RGB8;
  				case GL_SHORT:
  				case GL_UNSIGNED_SHORT:
  					return GL_RGB16;
  				case GL_INT:
  				case GL_UNSIGNED_INT:
  					return GL_RGB32I;
  				case GL_FLOAT:
  					return GL_RGB32F;
  				default:
  					std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl;
  					exit(1);
  				}
  			case GL_RGBA:
  				switch(cpu_type){
  				case GL_BYTE:
  				case GL_UNSIGNED_BYTE:
  					return GL_RGBA8;
  				case GL_SHORT:
  				case GL_UNSIGNED_SHORT:
  					return GL_RGBA16;
  				case GL_INT:
  				case GL_UNSIGNED_INT:
  					return GL_RGBA32I;
  				case GL_FLOAT:
  					return GL_RGBA32F;
  				default:
  					std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl;
  					exit(1);
  				}
  			default:
  				std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl;
  				exit(1);
  			}
  		}
  		///	creates this texture in the current OpenGL context
  		void generate_texture(){
  			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  			CHECK_OPENGL_ERROR
  			glGenTextures(1, &texID);
  			CHECK_OPENGL_ERROR
  			glBindTexture(texture_type, texID);
  			CHECK_OPENGL_ERROR
  			glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpolation);
  			CHECK_OPENGL_ERROR
  			glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpolation);
  			CHECK_OPENGL_ERROR
  			switch(texture_type){
  				case GL_TEXTURE_3D:
  					glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap);
  					glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap);
  					glTexParameteri(texture_type, GL_TEXTURE_WRAP_R, wrap);
  					glTexImage3D(texture_type, 0, gpu_type, (GLsizei)R[1], (GLsizei)R[2], (GLsizei)R[3], 0, format, cpu_type, ptr);
  					break;
  				case GL_TEXTURE_2D:
  					glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap);
  					CHECK_OPENGL_ERROR
  					glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap);
  					CHECK_OPENGL_ERROR
  					glTexImage2D(texture_type, 0, gpu_type, (GLsizei)R[1], (GLsizei)R[2], 0, format, cpu_type, ptr);
  					CHECK_OPENGL_ERROR
  					break;
  				case GL_TEXTURE_1D:
  					glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap);
  					CHECK_OPENGL_ERROR
  					glTexImage1D(texture_type, 0, gpu_type, (GLsizei)R[1], 0, format, cpu_type, ptr);
  					CHECK_OPENGL_ERROR
  					break;
  				default:
  					std::cout<<"Error in stim::gl_texture - unrecognized texture target when generating texture"<<std::endl;
  					exit(1);
  					break;
  			}
  			CHECK_OPENGL_ERROR
983b730b   David Mayerich   texture updates
194
195
  		}
  
197e13de   Pavel Govyadinov   Added new class g...
196
197
  	public:
  
035d798f   Pavel Govyadinov   modified the spid...
198
  		///default constructor
26da82c8   David Mayerich   finalized stim::g...
199
200
201
202
203
204
  		gl_texture(	GLint interp = GL_LINEAR,					//default to linear interpolation
  					GLint twrap = GL_REPEAT)					//default repeating the texture at the edges					
  						: image_stack<T>() {
  			init();												//initialize the texture with NULL values
  			interpolation = interp;								//store the interpolation type
  			wrap = twrap;										//store the wrap type
a4042c24   Pavel Govyadinov   Updated the gl_te...
205
  		}
197e13de   Pavel Govyadinov   Added new class g...
206
  
035d798f   Pavel Govyadinov   modified the spid...
207
208
  		///@param string path to the directory with the image files.
  		///Creates an instance of the gl_texture object with a path to the data.
372b5963   Pavel Govyadinov   added support for...
209
  
26da82c8   David Mayerich   finalized stim::g...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  		gl_texture(std::string file_mask, GLint interp = GL_LINEAR, GLint twrap = GL_REPEAT){
  			init();
  			interpolation = interp;								//store interpolation type
  			wrap = twrap;										//store wrap type
  			load(file_mask);
  		}
  
  		///Attaches the texture to the current OpenGL context and makes it ready to render
  		void attach(){
  			if(texID == 0) generate_texture();					//generate the texture if it doesn't already exist
  			else{
  				std::cout<<"Texture has already been attached to a context."<<std::endl;
  				exit(1);
  			}
  		}
  
  		//binds a texture to be the current render source
  		void bind(){
  			glBindTexture(texture_type, texID);					//bind the texture to the appropriate texture target
  			CHECK_OPENGL_ERROR
197e13de   Pavel Govyadinov   Added new class g...
230
  		}
035d798f   Pavel Govyadinov   modified the spid...
231
232
  
  		///returns the dimentions of the data in the x, y, z directions. 
983b730b   David Mayerich   texture updates
233
  		vec<int> getSize(){
b710b044   Pavel Govyadinov   Added more tempor...
234
235
236
  			stim::vec<int> size(R[1], R[2], R[3]);
  			return size;
  		}
a4042c24   Pavel Govyadinov   Updated the gl_te...
237
  
983b730b   David Mayerich   texture updates
238
239
240
241
  		void getSize(size_t& x, size_t& y, size_t& z) {
  			x = R[0]; y = R[1]; z = R[2];
  		}
  
385d2447   Pavel Govyadinov   Checkpoint: Conve...
242
243
244
245
  		///@param x size of the voxel in x direction
  		///@param y size of the voxel in y direction
  		///@param z size of the voxel in z direction
  		///	Sets the dimenstions of the voxels.
983b730b   David Mayerich   texture updates
246
247
248
249
  		void setSpacing(float sx, float sy, float sz){
  			S[1] = sx;
  			S[2] = sy;
  			S[3] = sz;
385d2447   Pavel Govyadinov   Checkpoint: Conve...
250
251
  		}
  
035d798f   Pavel Govyadinov   modified the spid...
252
  		///Returns a stim::vec that contains the x, y, z sizes of the voxel.
983b730b   David Mayerich   texture updates
253
  		vec<float> getDims(){
385d2447   Pavel Govyadinov   Checkpoint: Conve...
254
255
256
257
  			vec<float> dims(S[1], S[2], S[3]);
  			return dims;
  		}	
  
983b730b   David Mayerich   texture updates
258
  		///@param file_mask specifies the file(s) to be loaded
385d2447   Pavel Govyadinov   Checkpoint: Conve...
259
  		///	Sets the path and calls the loader on that path.
983b730b   David Mayerich   texture updates
260
  		void load(std::string file_mask){
26da82c8   David Mayerich   finalized stim::g...
261
262
263
264
265
  			image_stack<T>::load_images(file_mask);				//load images
  			setTextureType();									//set the texture type: 1D, 2D, 3D
  			format = guess_format();							//guess the texture format based on the number of image channels
  			cpu_type = guess_cpu_type();						//guess the CPU type based on the template
  			gpu_type = guess_gpu_type();						//guess the GPU type based on the format and template
197e13de   Pavel Govyadinov   Added new class g...
266
  		}
a4042c24   Pavel Govyadinov   Updated the gl_te...
267
  
035d798f   Pavel Govyadinov   modified the spid...
268
  		///	Returns the GLuint id of the texture created by/associated with the 
983b730b   David Mayerich   texture updates
269
270
  		///	instance of the gl_texture class.				
  		GLuint getTexture(){
a4042c24   Pavel Govyadinov   Updated the gl_te...
271
  			return texID;
197e13de   Pavel Govyadinov   Added new class g...
272
  		}
385d2447   Pavel Govyadinov   Checkpoint: Conve...
273
  		
63fcb5c8   Pavel Govyadinov   added some tempor...
274
  		
26da82c8   David Mayerich   finalized stim::g...
275
  		T* getData(){
63fcb5c8   Pavel Govyadinov   added some tempor...
276
277
278
  			return ptr;
  		}
  		
197e13de   Pavel Govyadinov   Added new class g...
279
  		
a4042c24   Pavel Govyadinov   Updated the gl_te...
280
  	};
197e13de   Pavel Govyadinov   Added new class g...
281
282
283
284
285
286
287
288
  }
  
  
  	
  	
  
  
  #endif