1 | /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
---|
2 | /* |
---|
3 | * Copyright (C) 2004-2013 HUBzero Foundation, LLC |
---|
4 | * |
---|
5 | */ |
---|
6 | #include "nvconf.h" |
---|
7 | |
---|
8 | #include <math.h> |
---|
9 | |
---|
10 | #include <GL/glew.h> |
---|
11 | #include <GL/gl.h> |
---|
12 | |
---|
13 | #include <vrmath/Vector3f.h> |
---|
14 | #include <util/FilePath.h> |
---|
15 | #include <Image.h> |
---|
16 | #include <ImageLoaderFactory.h> |
---|
17 | #include <ImageLoader.h> |
---|
18 | |
---|
19 | #include "nanovis.h" |
---|
20 | #include "VelocityArrowsSlice.h" |
---|
21 | #include "Volume.h" |
---|
22 | #include "Shader.h" |
---|
23 | #include "Camera.h" |
---|
24 | |
---|
25 | using namespace nv; |
---|
26 | using namespace nv::util; |
---|
27 | using namespace vrmath; |
---|
28 | |
---|
29 | static inline float deg2rad(float deg) |
---|
30 | { |
---|
31 | return ((deg * M_PI) / 180.); |
---|
32 | } |
---|
33 | |
---|
34 | static inline float rad2deg(float rad) |
---|
35 | { |
---|
36 | return ((rad * 180.) / M_PI); |
---|
37 | } |
---|
38 | |
---|
39 | VelocityArrowsSlice::VelocityArrowsSlice() : |
---|
40 | _vectorFieldGraphicsID(0), |
---|
41 | _slicePos(0.5f), |
---|
42 | _axis(AXIS_Z), |
---|
43 | _fbo(0), |
---|
44 | _tex(0), |
---|
45 | _maxPointSize(1.0f), |
---|
46 | _renderTargetWidth(128), |
---|
47 | _renderTargetHeight(128), |
---|
48 | _velocities(NULL), |
---|
49 | _projectionVector(1, 1, 0), |
---|
50 | _tickCountForMinSizeAxis(10), |
---|
51 | _tickCountX(0), |
---|
52 | _tickCountY(0), |
---|
53 | _tickCountZ(0), |
---|
54 | _pointCount(0), |
---|
55 | _maxVelocityScale(1, 1, 1), |
---|
56 | _arrowColor(1, 1, 0), |
---|
57 | _visible(false), |
---|
58 | _dirty(true), |
---|
59 | _vertexBufferGraphicsID(0), |
---|
60 | _arrowsTex(NULL), |
---|
61 | _renderMode(LINES) |
---|
62 | { |
---|
63 | setSliceAxis(AXIS_Z); |
---|
64 | |
---|
65 | _queryVelocityFP.loadFragmentProgram("queryvelocity.cg"); |
---|
66 | |
---|
67 | // Delay loading of shaders only required for glyph style rendering |
---|
68 | if (_renderMode == GLYPHS) { |
---|
69 | _particleShader.loadVertexProgram("velocityslicevp.cg"); |
---|
70 | _particleShader.loadFragmentProgram("velocityslicefp.cg"); |
---|
71 | } |
---|
72 | |
---|
73 | createRenderTarget(); |
---|
74 | |
---|
75 | std::string path = FilePath::getInstance()->getPath("arrows.bmp"); |
---|
76 | if (!path.empty()) { |
---|
77 | ImageLoader *loader = ImageLoaderFactory::getInstance()->createLoader("bmp"); |
---|
78 | if (loader != NULL) { |
---|
79 | Image *image = loader->load(path.c_str(), Image::IMG_RGBA); |
---|
80 | if (image != NULL) { |
---|
81 | unsigned char *bytes = (unsigned char *)image->getImageBuffer(); |
---|
82 | if (bytes != NULL) { |
---|
83 | _arrowsTex = new Texture2D(image->getWidth(), image->getHeight(), |
---|
84 | GL_UNSIGNED_BYTE, GL_LINEAR, 4, NULL); |
---|
85 | _arrowsTex->setWrapS(GL_MIRRORED_REPEAT); |
---|
86 | _arrowsTex->setWrapT(GL_MIRRORED_REPEAT); |
---|
87 | _arrowsTex->initialize(image->getImageBuffer()); |
---|
88 | } |
---|
89 | delete image; |
---|
90 | } else { |
---|
91 | ERROR("Failed to load arrows image"); |
---|
92 | } |
---|
93 | delete loader; |
---|
94 | } else { |
---|
95 | ERROR("Couldn't find loader for arrows image"); |
---|
96 | } |
---|
97 | } else { |
---|
98 | ERROR("Couldn't find arrows image"); |
---|
99 | } |
---|
100 | |
---|
101 | GLfloat minMax[2]; |
---|
102 | glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, minMax); |
---|
103 | TRACE("Aliased point size range: %g %g", minMax[0], minMax[1]); |
---|
104 | _maxPointSize = minMax[1]; |
---|
105 | glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, minMax); |
---|
106 | TRACE("Smooth point size range: %g %g", minMax[0], minMax[1]); |
---|
107 | _maxPointSize = minMax[1] > _maxPointSize ? minMax[1] : _maxPointSize; |
---|
108 | TRACE("Max point size: %g", _maxPointSize); |
---|
109 | |
---|
110 | TRACE("Leaving VelocityArrowsSlice constructor"); |
---|
111 | } |
---|
112 | |
---|
113 | VelocityArrowsSlice::~VelocityArrowsSlice() |
---|
114 | { |
---|
115 | if (_tex != 0) { |
---|
116 | glDeleteTextures(1, &_tex); |
---|
117 | } |
---|
118 | if (_fbo != 0) { |
---|
119 | glDeleteFramebuffersEXT(1, &_fbo); |
---|
120 | } |
---|
121 | if (_arrowsTex != NULL) { |
---|
122 | delete _arrowsTex; |
---|
123 | } |
---|
124 | if (_vertexBufferGraphicsID != 0) { |
---|
125 | glDeleteBuffers(1, &_vertexBufferGraphicsID); |
---|
126 | } |
---|
127 | if (_velocities != NULL) { |
---|
128 | delete [] _velocities; |
---|
129 | } |
---|
130 | } |
---|
131 | |
---|
132 | void VelocityArrowsSlice::createRenderTarget() |
---|
133 | { |
---|
134 | if (_velocities != NULL) { |
---|
135 | delete [] _velocities; |
---|
136 | } |
---|
137 | _velocities = new Vector3f[_renderTargetWidth * _renderTargetHeight]; |
---|
138 | |
---|
139 | if (_vertexBufferGraphicsID != 0) { |
---|
140 | glDeleteBuffers(1, &_vertexBufferGraphicsID); |
---|
141 | } |
---|
142 | |
---|
143 | glGenBuffers(1, &_vertexBufferGraphicsID); |
---|
144 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vertexBufferGraphicsID); |
---|
145 | glBufferDataARB(GL_ARRAY_BUFFER_ARB, _renderTargetWidth * _renderTargetHeight * 3 * sizeof(float), |
---|
146 | 0, GL_DYNAMIC_DRAW_ARB); |
---|
147 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); |
---|
148 | |
---|
149 | if (_tex != 0) { |
---|
150 | glDeleteTextures(1, &_tex); |
---|
151 | } |
---|
152 | if (_fbo != 0) { |
---|
153 | glDeleteFramebuffersEXT(1, &_fbo); |
---|
154 | } |
---|
155 | |
---|
156 | glGenFramebuffersEXT(1, &_fbo); |
---|
157 | glGenTextures(1, &_tex); |
---|
158 | int fboOrig; |
---|
159 | glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig); |
---|
160 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); |
---|
161 | |
---|
162 | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _tex); |
---|
163 | glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
---|
164 | glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
---|
165 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
---|
166 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
---|
167 | |
---|
168 | glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, |
---|
169 | _renderTargetWidth, _renderTargetHeight, 0, |
---|
170 | GL_RGBA, GL_FLOAT, NULL); |
---|
171 | |
---|
172 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
---|
173 | GL_TEXTURE_RECTANGLE_ARB, _tex, 0); |
---|
174 | |
---|
175 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig); |
---|
176 | } |
---|
177 | |
---|
178 | void VelocityArrowsSlice::setSliceAxis(FlowSliceAxis axis) |
---|
179 | { |
---|
180 | _axis = axis; |
---|
181 | switch (_axis) { |
---|
182 | case AXIS_X: |
---|
183 | _projectionVector.x = 0; |
---|
184 | _projectionVector.y = 1; |
---|
185 | _projectionVector.z = 1; |
---|
186 | break; |
---|
187 | case AXIS_Y: |
---|
188 | _projectionVector.x = 1; |
---|
189 | _projectionVector.y = 0; |
---|
190 | _projectionVector.z = 1; |
---|
191 | break; |
---|
192 | case AXIS_Z: |
---|
193 | _projectionVector.x = 1; |
---|
194 | _projectionVector.y = 1; |
---|
195 | _projectionVector.z = 0; |
---|
196 | break; |
---|
197 | } |
---|
198 | _dirty = true; |
---|
199 | } |
---|
200 | |
---|
201 | void VelocityArrowsSlice::queryVelocity() |
---|
202 | { |
---|
203 | glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); |
---|
204 | int fboOrig; |
---|
205 | glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboOrig); |
---|
206 | |
---|
207 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); |
---|
208 | |
---|
209 | _queryVelocityFP.bind(); |
---|
210 | _queryVelocityFP.setFPTextureParameter("vfield", _vectorFieldGraphicsID); |
---|
211 | |
---|
212 | glDisable(GL_DEPTH_TEST); |
---|
213 | glViewport(0, 0, _renderTargetWidth, _renderTargetHeight); |
---|
214 | glMatrixMode(GL_PROJECTION); |
---|
215 | glPushMatrix(); |
---|
216 | glLoadIdentity(); |
---|
217 | glOrtho(0, _renderTargetWidth, 0, _renderTargetHeight, -10.0f, 10.0f); |
---|
218 | glMatrixMode(GL_MODELVIEW); |
---|
219 | glPushMatrix(); |
---|
220 | glLoadIdentity(); |
---|
221 | |
---|
222 | glBegin(GL_QUADS); |
---|
223 | switch (_axis) { |
---|
224 | case 0: |
---|
225 | glTexCoord3f(_slicePos, 0, 0); glVertex2i(0, 0); |
---|
226 | glTexCoord3f(_slicePos, 1, 0); glVertex2i(_renderTargetWidth, 0); |
---|
227 | glTexCoord3f(_slicePos, 1, 1); glVertex2i(_renderTargetWidth, _renderTargetHeight); |
---|
228 | glTexCoord3f(_slicePos, 0, 1); glVertex2i(0, _renderTargetHeight); |
---|
229 | break; |
---|
230 | case 1: |
---|
231 | glTexCoord3f(0, _slicePos, 0); glVertex2i(0, 0); |
---|
232 | glTexCoord3f(1, _slicePos, 0); glVertex2i(_renderTargetWidth, 0); |
---|
233 | glTexCoord3f(1, _slicePos, 1); glVertex2i(_renderTargetWidth, _renderTargetHeight); |
---|
234 | glTexCoord3f(0, _slicePos, 1); glVertex2i(0, _renderTargetHeight); |
---|
235 | break; |
---|
236 | case 2: |
---|
237 | default: |
---|
238 | glTexCoord3f(0, 0, _slicePos); glVertex2i(0, 0); |
---|
239 | glTexCoord3f(1, 0, _slicePos); glVertex2i(_renderTargetWidth, 0); |
---|
240 | glTexCoord3f(1, 1, _slicePos); glVertex2i(_renderTargetWidth, _renderTargetHeight); |
---|
241 | glTexCoord3f(0, 1, _slicePos); glVertex2i(0, _renderTargetHeight); |
---|
242 | break; |
---|
243 | } |
---|
244 | glEnd(); |
---|
245 | |
---|
246 | _queryVelocityFP.disableFPTextureParameter("vfield"); |
---|
247 | _queryVelocityFP.unbind(); |
---|
248 | |
---|
249 | glReadPixels(0, 0, _renderTargetWidth, _renderTargetHeight, GL_RGB, GL_FLOAT, _velocities); |
---|
250 | |
---|
251 | glMatrixMode(GL_PROJECTION); |
---|
252 | glPopMatrix(); |
---|
253 | glMatrixMode(GL_MODELVIEW); |
---|
254 | glPopMatrix(); |
---|
255 | |
---|
256 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig); |
---|
257 | |
---|
258 | glPopAttrib(); |
---|
259 | } |
---|
260 | |
---|
261 | static void drawLineArrow(int axis) |
---|
262 | { |
---|
263 | glBegin(GL_LINES); |
---|
264 | switch (axis) { |
---|
265 | case 0: // ZY plane |
---|
266 | glVertex3f(0.0, 0.0, 0.0); |
---|
267 | glVertex3f(0.0, 0.0, 1.0); |
---|
268 | |
---|
269 | glVertex3f(0.0, 0.0, 1.0); |
---|
270 | glVertex3f(0.0, 0.25, 0.75); |
---|
271 | |
---|
272 | glVertex3f(0.0, 0.0, 1.0); |
---|
273 | glVertex3f(0.0, -0.25, 0.75); |
---|
274 | break; |
---|
275 | case 1: // XZ plane |
---|
276 | glVertex3f(0.0, 0.0, 0.0); |
---|
277 | glVertex3f(1.0, 0.0, 0.0); |
---|
278 | |
---|
279 | glVertex3f(1.0, 0.0, 0.0); |
---|
280 | glVertex3f(0.75, 0.0, 0.25); |
---|
281 | |
---|
282 | glVertex3f(1.0, 0.0, 0.0); |
---|
283 | glVertex3f(0.75, 0.0, -0.25); |
---|
284 | break; |
---|
285 | case 2: // XY plane |
---|
286 | default: |
---|
287 | glVertex3f(0.0, 0.0, 0.0); |
---|
288 | glVertex3f(1.0, 0.0, 0.0); |
---|
289 | |
---|
290 | glVertex3f(1.0, 0.0, 0.0); |
---|
291 | glVertex3f(0.75, 0.25, 0.0); |
---|
292 | |
---|
293 | glVertex3f(1.0, 0.0, 0.0); |
---|
294 | glVertex3f(0.75, -0.25, 0.0); |
---|
295 | break; |
---|
296 | } |
---|
297 | glEnd(); |
---|
298 | } |
---|
299 | |
---|
300 | void VelocityArrowsSlice::render() |
---|
301 | { |
---|
302 | if (!_visible) |
---|
303 | return; |
---|
304 | |
---|
305 | if (_dirty) { |
---|
306 | computeSamplingTicks(); |
---|
307 | queryVelocity(); |
---|
308 | _dirty = false; |
---|
309 | } |
---|
310 | |
---|
311 | TRACE("_scale: %g %g %g", _scale.x, _scale.y, _scale.z); |
---|
312 | TRACE("_maxVelocityScale: %g %g %g", |
---|
313 | _maxVelocityScale.x, _maxVelocityScale.y, _maxVelocityScale.z); |
---|
314 | |
---|
315 | glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
316 | |
---|
317 | glMatrixMode(GL_MODELVIEW); |
---|
318 | glPushMatrix(); |
---|
319 | |
---|
320 | glTranslatef(_origin.x, _origin.y, _origin.z); |
---|
321 | glScalef(_scale.x, _scale.y, _scale.z); |
---|
322 | |
---|
323 | if (_renderMode == LINES) { |
---|
324 | glDisable(GL_TEXTURE_2D); |
---|
325 | glDisable(GL_LIGHTING); |
---|
326 | glLineWidth(2.0); |
---|
327 | glColor3f(_arrowColor.x, _arrowColor.y, _arrowColor.z); |
---|
328 | |
---|
329 | Vector3f pos; |
---|
330 | Vector3f vel; |
---|
331 | Vector3f refVec; |
---|
332 | Vector3f blue(0, 0, 1); |
---|
333 | Vector3f red(1, 0, 0); |
---|
334 | |
---|
335 | int index = 0, icount, jcount; |
---|
336 | switch (_axis) { |
---|
337 | case 0: |
---|
338 | icount = _tickCountZ; |
---|
339 | jcount = _tickCountY; |
---|
340 | refVec.set(0, 0, 1); |
---|
341 | break; |
---|
342 | case 1: |
---|
343 | icount = _tickCountZ; |
---|
344 | jcount = _tickCountX; |
---|
345 | refVec.set(1, 0, 0); |
---|
346 | break; |
---|
347 | case 2: |
---|
348 | default: |
---|
349 | icount = _tickCountY; |
---|
350 | jcount = _tickCountX; |
---|
351 | refVec.set(1, 0, 0); |
---|
352 | break; |
---|
353 | } |
---|
354 | |
---|
355 | for (int i = 0; i < icount; ++i) { |
---|
356 | for (int j = 0; j < jcount; ++j, ++index) { |
---|
357 | pos = _samplingPositions[index]; |
---|
358 | // Normalized velocity: [-1,1] components |
---|
359 | // Project 3D vector onto sample plane |
---|
360 | vel = _velocities[index].scale(_projectionVector); |
---|
361 | // Length: [0,1] |
---|
362 | double length = vel.length(); |
---|
363 | if (length < 0.0 || length > 1.0) { |
---|
364 | TRACE("***vec: (%g, %g, %g) length: %g***", vel.x, vel.y, vel.z, length); |
---|
365 | continue; |
---|
366 | } |
---|
367 | if (length > 0.0) { |
---|
368 | Vector3f vnorm = vel.normalize(); |
---|
369 | Vector3f rotationAxis = refVec.cross(vnorm); |
---|
370 | double angle = rad2deg(acos(refVec.dot(vnorm))); |
---|
371 | Vector3f color = blue * (1.0 - length) + red * length; |
---|
372 | float scale = length; |
---|
373 | if (scale < 0.10) scale = 0.10; |
---|
374 | glMatrixMode(GL_MODELVIEW); |
---|
375 | glPushMatrix(); |
---|
376 | glColor3f(color.x, color.y, color.z); |
---|
377 | glTranslatef(pos.x, pos.y, pos.z); |
---|
378 | glScalef(2.0 * _maxVelocityScale.x, |
---|
379 | 2.0 * _maxVelocityScale.y, |
---|
380 | 2.0 * _maxVelocityScale.z); |
---|
381 | glScalef(scale, scale, scale); |
---|
382 | if (angle > 1.0e-6 || angle < -1.0e-6) |
---|
383 | glRotated(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); |
---|
384 | drawLineArrow(_axis); |
---|
385 | glPopMatrix(); |
---|
386 | } |
---|
387 | } |
---|
388 | } |
---|
389 | |
---|
390 | glLineWidth(1.0); |
---|
391 | } else { |
---|
392 | glColor4f(_arrowColor.x, _arrowColor.y, _arrowColor.z, 1.0f); |
---|
393 | glEnable(GL_DEPTH_TEST); |
---|
394 | glDisable(GL_LIGHTING); |
---|
395 | #if 0 |
---|
396 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); |
---|
397 | glEnable(GL_BLEND); |
---|
398 | glDepthMask(GL_FALSE); |
---|
399 | #else |
---|
400 | glDisable(GL_BLEND); |
---|
401 | #endif |
---|
402 | glAlphaFunc(GL_GREATER, 0.6); |
---|
403 | glEnable(GL_ALPHA_TEST); |
---|
404 | glEnable(GL_POINT_SPRITE_ARB); |
---|
405 | glPointSize(20); |
---|
406 | glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); |
---|
407 | |
---|
408 | _arrowsTex->activate(); |
---|
409 | glEnable(GL_TEXTURE_2D); |
---|
410 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
---|
411 | |
---|
412 | GLfloat atten[] = {1, 0, 0}; |
---|
413 | glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, atten); |
---|
414 | glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.0f); |
---|
415 | glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 1.0f); |
---|
416 | glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, _maxPointSize); |
---|
417 | glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); |
---|
418 | |
---|
419 | // FIXME: This vertex shader won't compile with ARB_vertex_program, |
---|
420 | // so it should use GLSL |
---|
421 | if (!_particleShader.isVertexProgramLoaded()) { |
---|
422 | _particleShader.loadVertexProgram("velocityslicevp.cg"); |
---|
423 | } |
---|
424 | if (!_particleShader.isFragmentProgramLoaded()) { |
---|
425 | _particleShader.loadFragmentProgram("velocityslicefp.cg"); |
---|
426 | } |
---|
427 | |
---|
428 | _particleShader.bind(); |
---|
429 | _particleShader.setVPTextureParameter("vfield", _vectorFieldGraphicsID); |
---|
430 | _particleShader.setFPTextureParameter("arrows", _arrowsTex->id()); |
---|
431 | _particleShader.setVPParameter1f("tanHalfFOV", |
---|
432 | tan(NanoVis::getCamera()->getFov() * 0.5) * NanoVis::winHeight * 0.5); |
---|
433 | _particleShader.setGLStateMatrixVPParameter("modelview", |
---|
434 | Shader::MODELVIEW_MATRIX, |
---|
435 | Shader::MATRIX_IDENTITY); |
---|
436 | _particleShader.setGLStateMatrixVPParameter("mvp", |
---|
437 | Shader::MODELVIEW_PROJECTION_MATRIX, |
---|
438 | Shader::MATRIX_IDENTITY); |
---|
439 | |
---|
440 | glEnableClientState(GL_VERTEX_ARRAY); |
---|
441 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vertexBufferGraphicsID); |
---|
442 | glVertexPointer(3, GL_FLOAT, 0, 0); |
---|
443 | //glEnableClientState(GL_COLOR_ARRAY); |
---|
444 | |
---|
445 | // TBD.. |
---|
446 | glDrawArrays(GL_POINTS, 0, _pointCount); |
---|
447 | glPointSize(1); |
---|
448 | |
---|
449 | glDisableClientState(GL_VERTEX_ARRAY); |
---|
450 | glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); |
---|
451 | glDisable(GL_POINT_SPRITE_ARB); |
---|
452 | |
---|
453 | _particleShader.disableVPTextureParameter("vfield"); |
---|
454 | _particleShader.disableFPTextureParameter("arrows"); |
---|
455 | _particleShader.unbind(); |
---|
456 | |
---|
457 | glActiveTexture(GL_TEXTURE0); |
---|
458 | glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); |
---|
459 | _arrowsTex->deactivate(); |
---|
460 | } |
---|
461 | |
---|
462 | glPopMatrix(); |
---|
463 | glPopAttrib(); |
---|
464 | } |
---|
465 | |
---|
466 | void |
---|
467 | VelocityArrowsSlice::setVectorField(Volume *volume) |
---|
468 | { |
---|
469 | _vectorFieldGraphicsID = volume->textureID(); |
---|
470 | Vector3f bmin, bmax; |
---|
471 | volume->getBounds(bmin, bmax); |
---|
472 | _origin.set(bmin.x, bmin.y, bmin.z); |
---|
473 | _scale.set(bmax.x-bmin.x, bmax.y-bmin.y, bmax.z-bmin.z); |
---|
474 | |
---|
475 | _dirty = true; |
---|
476 | } |
---|
477 | |
---|
478 | void VelocityArrowsSlice::computeSamplingTicks() |
---|
479 | { |
---|
480 | if (_scale.x < _scale.y) { |
---|
481 | if (_scale.x < _scale.z || _scale.z == 0.0) { |
---|
482 | // _scale.x |
---|
483 | _tickCountX = _tickCountForMinSizeAxis; |
---|
484 | |
---|
485 | float step = _scale.x / (_tickCountX + 1); |
---|
486 | _tickCountY = (int)(_scale.y/step); |
---|
487 | _tickCountZ = (int)(_scale.z/step); |
---|
488 | } else { |
---|
489 | // _scale.z |
---|
490 | _tickCountZ = _tickCountForMinSizeAxis; |
---|
491 | |
---|
492 | float step = _scale.z / (_tickCountZ + 1); |
---|
493 | _tickCountX = (int)(_scale.x/step); |
---|
494 | _tickCountY = (int)(_scale.y/step); |
---|
495 | } |
---|
496 | } else { |
---|
497 | if (_scale.y < _scale.z || _scale.z == 0.0) { |
---|
498 | // _scale.y |
---|
499 | _tickCountY = _tickCountForMinSizeAxis; |
---|
500 | |
---|
501 | float step = _scale.y / (_tickCountY + 1); |
---|
502 | _tickCountX = (int)(_scale.x/step); |
---|
503 | _tickCountZ = (int)(_scale.z/step); |
---|
504 | } else { |
---|
505 | // _scale.z |
---|
506 | _tickCountZ = _tickCountForMinSizeAxis; |
---|
507 | |
---|
508 | float step = _scale.z / (_tickCountZ + 1); |
---|
509 | _tickCountX = (int)(_scale.x/step); |
---|
510 | _tickCountY = (int)(_scale.y/step); |
---|
511 | } |
---|
512 | } |
---|
513 | |
---|
514 | switch (_axis) { |
---|
515 | case 0: |
---|
516 | _tickCountX = 1; |
---|
517 | _renderTargetWidth = _tickCountY; |
---|
518 | _renderTargetHeight = _tickCountZ; |
---|
519 | break; |
---|
520 | case 1: |
---|
521 | _tickCountY = 1; |
---|
522 | _renderTargetWidth = _tickCountX; |
---|
523 | _renderTargetHeight = _tickCountZ; |
---|
524 | break; |
---|
525 | default: |
---|
526 | case 2: |
---|
527 | _tickCountZ = 1; |
---|
528 | _renderTargetWidth = _tickCountX; |
---|
529 | _renderTargetHeight = _tickCountY; |
---|
530 | break; |
---|
531 | } |
---|
532 | |
---|
533 | _maxVelocityScale.x = (1.0f / _tickCountX) * 0.8f; |
---|
534 | _maxVelocityScale.y = (1.0f / _tickCountY) * 0.8f; |
---|
535 | _maxVelocityScale.z = (1.0f / _tickCountZ) * 0.8f; |
---|
536 | |
---|
537 | TRACE("Tick counts: %d %d %d", _tickCountX, _tickCountY, _tickCountZ); |
---|
538 | |
---|
539 | int pointCount = _tickCountX * _tickCountY * _tickCountZ; |
---|
540 | if (_pointCount != pointCount) { |
---|
541 | _samplingPositions.clear(); |
---|
542 | _samplingPositions.reserve(pointCount); |
---|
543 | _pointCount = pointCount; |
---|
544 | } |
---|
545 | |
---|
546 | createRenderTarget(); |
---|
547 | |
---|
548 | Vector3f pos; |
---|
549 | Vector3f *pinfo = NULL; |
---|
550 | if (_renderMode == GLYPHS) { |
---|
551 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vertexBufferGraphicsID); |
---|
552 | pinfo = (Vector3f *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); |
---|
553 | } |
---|
554 | |
---|
555 | if (_axis == 2) { |
---|
556 | for (int y = 1; y <= _tickCountY; ++y) { |
---|
557 | for (int x = 1; x <= _tickCountX; ++x) { |
---|
558 | pos.x = (1.0f / (_tickCountX + 1)) * x; |
---|
559 | pos.y = (1.0f / (_tickCountY + 1)) * y; |
---|
560 | pos.z = _slicePos; |
---|
561 | if (_renderMode == LINES) { |
---|
562 | _samplingPositions.push_back(pos); |
---|
563 | } else { |
---|
564 | *pinfo = pos; |
---|
565 | ++pinfo; |
---|
566 | } |
---|
567 | } |
---|
568 | } |
---|
569 | } else if (_axis == 1) { |
---|
570 | for (int z = 1; z <= _tickCountZ; ++z) { |
---|
571 | for (int x = 1; x <= _tickCountX; ++x) { |
---|
572 | pos.x = (1.0f / (_tickCountX + 1)) * x; |
---|
573 | pos.y = _slicePos; |
---|
574 | pos.z = (1.0f / (_tickCountZ + 1)) * z; |
---|
575 | if (_renderMode == LINES) { |
---|
576 | _samplingPositions.push_back(pos); |
---|
577 | } else { |
---|
578 | *pinfo = pos; |
---|
579 | ++pinfo; |
---|
580 | } |
---|
581 | } |
---|
582 | } |
---|
583 | } else if (_axis == 0) { |
---|
584 | for (int z = 1; z <= _tickCountZ; ++z) { |
---|
585 | for (int y = 1; y <= _tickCountY; ++y) { |
---|
586 | pos.x = _slicePos; |
---|
587 | pos.y = (1.0f / (_tickCountY + 1)) * y; |
---|
588 | pos.z = (1.0f / (_tickCountZ + 1)) * z; |
---|
589 | if (_renderMode == LINES) { |
---|
590 | _samplingPositions.push_back(pos); |
---|
591 | } else { |
---|
592 | *pinfo = pos; |
---|
593 | ++pinfo; |
---|
594 | } |
---|
595 | } |
---|
596 | } |
---|
597 | } |
---|
598 | |
---|
599 | if (_renderMode == GLYPHS) { |
---|
600 | glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); |
---|
601 | } |
---|
602 | } |
---|