draw.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 
33 #ifndef __INCLUDE_MIST_DRAW__
34 #define __INCLUDE_MIST_DRAW__
35 
36 
37 #ifndef __INCLUDE_MIST_H__
38 #include "mist.h"
39 #endif
40 
41 // カラー画像の設定を読み込む
42 #ifndef __INCLUDE_MIST_COLOR_H__
43 #include "config/color.h"
44 #endif
45 
46 #ifndef __INCLUDE_MIST_VECTOR__
47 #include "vector.h"
48 #endif
49 
50 #ifndef __INCLUDE_BITMAP_H__
51 #include "bitmap.h"
52 #endif
53 
54 
55 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
56 #include <windows.h>
57 #endif
58 
59 #include <GL/gl.h>
60 #include <GL/glu.h>
61 #include <cmath>
62 
63 
64 // mist名前空間の始まり
66 
67 
68 namespace pixel_data
69 {
70  // 浮動小数点の場合
71  template < bool b >
72  struct pixel
73  {
74  static float get_value( double v ){ return( static_cast< float >( v ) ); }
75  };
76 
77  template < >
78  struct pixel< false >
79  {
80  static float get_value( double v ){ return( static_cast< float >( v ) / 255.0f ); }
81  };
82 
83  template < class T > struct gl_type_trait { _MIST_CONST( GLenum, gl_type, 0 ); };
84  template <> struct gl_type_trait< unsigned char > { _MIST_CONST( GLenum, gl_type, GL_UNSIGNED_BYTE ); };
85  template <> struct gl_type_trait< unsigned short >{ _MIST_CONST( GLenum, gl_type, GL_UNSIGNED_SHORT ); };
86  template <> struct gl_type_trait< unsigned int > { _MIST_CONST( GLenum, gl_type, GL_UNSIGNED_INT ); };
87  template <> struct gl_type_trait< unsigned long > { _MIST_CONST( GLenum, gl_type, GL_UNSIGNED_INT ); };
88  template <> struct gl_type_trait< signed char > { _MIST_CONST( GLenum, gl_type, GL_BYTE ); };
89  template <> struct gl_type_trait< signed short > { _MIST_CONST( GLenum, gl_type, GL_SHORT ); };
90  template <> struct gl_type_trait< signed int > { _MIST_CONST( GLenum, gl_type, GL_INT ); };
91  template <> struct gl_type_trait< signed long > { _MIST_CONST( GLenum, gl_type, GL_INT ); };
92  template <> struct gl_type_trait< bool > { _MIST_CONST( GLenum, gl_type, GL_UNSIGNED_BYTE ); };
93  template <> struct gl_type_trait< char > { _MIST_CONST( GLenum, gl_type, GL_BYTE ); };
94  template <> struct gl_type_trait< float > { _MIST_CONST( GLenum, gl_type, GL_FLOAT ); };
95  template <> struct gl_type_trait< double > { _MIST_CONST( GLenum, gl_type, GL_DOUBLE ); };
96 // template <> struct gl_type_trait< long double > { _MIST_CONST( GLenum, gl_type, true ); };
97 
98  template < bool color >
99  struct __glTexImage2D__
100  {
101  template < class Array >
102  static void glTexImage2D( const Array &image )
103  {
104  ::glTexImage2D(
105  GL_TEXTURE_2D, 0, GL_RGBA,
106  static_cast< GLsizei >( image.width( ) ),
107  static_cast< GLsizei >( image.height( ) ),
108  0,
109  GL_LUMINANCE,
110  gl_type_trait< typename Array::value_type >::gl_type,
111  static_cast< const GLvoid* >( &( image[0] ) )
112  );
113  }
114  };
115 
116  template < >
117  struct __glTexImage2D__< true >
118  {
119  template < class T, class Allocator >
120  static void glTexImage2D( const array2< rgb< T >, Allocator > &image )
121  {
122  ::glTexImage2D(
123  GL_TEXTURE_2D, 0, GL_RGBA,
124  static_cast< GLsizei >( image.width( ) ),
125  static_cast< GLsizei >( image.height( ) ),
126  0,
127  GL_RGB,
128  gl_type_trait< T >::gl_type,
129  static_cast< const GLvoid* >( &( image[0] ) )
130  );
131  }
132 
133  template < size_t BITS, class Allocator >
134  static void glTexImage2D( const bitmap< BITS, Allocator > &image )
135  {
136  ::glTexImage2D(
137  GL_TEXTURE_2D, 0, GL_RGBA,
138  static_cast< GLsizei >( image.width( ) ),
139  static_cast< GLsizei >( image.height( ) ),
140  0,
141  GL_BGR_EXT,
142  gl_type_trait< unsigned char >::gl_type,
143  static_cast< const GLvoid* >( &( image[0] ) )
144  );
145  }
146 
147  template < class T, class Allocator >
148  static void glTexImage2D( const array2< rgba< T >, Allocator > &image )
149  {
150  ::glTexImage2D(
151  GL_TEXTURE_2D, 0, GL_RGBA,
152  static_cast< GLsizei >( image.width( ) ),
153  static_cast< GLsizei >( image.height( ) ),
154  0,
155  GL_RGBA,
156  gl_type_trait< T >::gl_type,
157  static_cast< const GLvoid* >( &( image[0] ) )
158  );
159  }
160  };
161 
162  template < bool color >
163  struct __glDrawPixels__
164  {
165  template < class Array >
166  static void glDrawPixels( const Array &image, typename Array::size_type w, typename Array::size_type h )
167  {
168  ::glDrawPixels(
169  static_cast< GLsizei >( w ),
170  static_cast< GLsizei >( h ),
171  GL_LUMINANCE,
172  gl_type_trait< typename Array::value_type >::gl_type,
173  static_cast< const GLvoid* >( &( image[0] ) )
174  );
175  }
176  };
177 
178  template < >
179  struct __glDrawPixels__< true >
180  {
181  template < class T, class Allocator >
182  static void glDrawPixels( const array2< rgb< T >, Allocator > &image, typename array2< T, Allocator >::size_type w, typename array2< T, Allocator >::size_type h )
183  {
184  ::glDrawPixels(
185  static_cast< GLsizei >( w ),
186  static_cast< GLsizei >( h ),
187  GL_RGB,
188  gl_type_trait< T >::gl_type,
189  static_cast< const GLvoid* >( &( image[0] ) )
190  );
191  }
192 
193  template < size_t BITS, class Allocator >
194  static void glDrawPixels( const bitmap< BITS, Allocator > &image, typename bitmap< BITS, Allocator >::size_type w, typename bitmap< BITS, Allocator >::size_type h )
195  {
196  ::glDrawPixels(
197  static_cast< GLsizei >( w ),
198  static_cast< GLsizei >( h ),
199  GL_BGR_EXT,
200  gl_type_trait< unsigned char >::gl_type,
201  static_cast< const GLvoid* >( &( image[0] ) )
202  );
203  }
204 
205  template < class T, class Allocator >
206  static void glDrawPixels( const array2< rgba< T >, Allocator > &image, typename array2< T, Allocator >::size_type w, typename array2< T, Allocator >::size_type h )
207  {
208  ::glDrawPixels(
209  static_cast< GLsizei >( w ),
210  static_cast< GLsizei >( h ),
211  GL_RGBA,
212  gl_type_trait< T >::gl_type,
213  static_cast< const GLvoid* >( &( image[0] ) )
214  );
215  }
216  };
217 
218  template< class Array >
219  void glTexImage2D( const Array &image )
220  {
221  __glTexImage2D__< is_color< typename Array::value_type >::value >::glTexImage2D( image );
222  }
223 
224  template< class Array >
225  void glDrawPixels( const Array &image, typename Array::size_type w, typename Array::size_type h )
226  {
227  __glDrawPixels__< is_color< typename Array::value_type >::value >::glDrawPixels( image, w, h );
228  }
229 
230 
231  inline size_t floor_square_index( size_t v )
232  {
233  if( v == 0 )
234  {
235  return( 0 );
236  }
237 
238  for( size_t i = 1, _2 = 2 ; i < 64 ; i++ )
239  {
240  if( v <= _2 )
241  {
242  return( i );
243  }
244  _2 *= 2;
245  }
246 
247  return( 0 );
248  }
249 
250  inline size_t floor_square( size_t v )
251  {
252  if( v == 0 )
253  {
254  return( 0 );
255  }
256 
257  for( size_t i = 1, _2 = 2 ; i < 64 ; i++ )
258  {
259  if( v <= _2 )
260  {
261  return( _2 );
262  }
263  _2 *= 2;
264  }
265 
266  return( 0 );
267  }
268 
269  // 入力された v が2の指数乗であるかどうかをチェックする
270  inline bool is_floor_square( size_t v )
271  {
272  return( ( v & ( v - 1 ) ) == 0 );
273  }
274 }
275 
276 
284 
285 
306 template< class Array >
307 bool draw_buffer( const Array &image,
308  typename Array::size_type image_width, typename Array::size_type image_height,
309  typename Array::size_type window_width, typename Array::size_type window_height,
310  double zoom = 1.0, double xpos = 0.0, double ypos = 0.0, bool interpolate = true )
311 {
312  // 背景の初期化を行う
313  typedef typename Array::value_type value_type;
314  typedef pixel_data::pixel< is_float< value_type >::value > pixel;
315 
316  if( image_width > image.width( ) || image_height > image.height( ) ) return( false );
317  if( image.width( ) != image.height( ) ) return( false );
318 
319  typedef typename Array::size_type size_type;
320 
321  // テクスチャのサイズが2の指数上になっているかどうかをチェック
322  if( !pixel_data::is_floor_square( image.width( ) ) ) return( false );
323 
324 
325  if( image.empty( ) ) return( false );
326 
327  double ttt = static_cast< double >( image.width( ) );
328  int interpolate_ = interpolate ? GL_LINEAR: GL_NEAREST;
329 
330  glMatrixMode( GL_MODELVIEW );
331  glLoadIdentity();
332  glMatrixMode( GL_PROJECTION );
333  glLoadIdentity();
334 
335  GLboolean isLighting = glIsEnabled( GL_LIGHTING );
336  glDisable( GL_LIGHTING );
337  glEnable( GL_BLEND );
338 
339  glViewport( 0, 0, static_cast< GLint >( window_width ), static_cast< GLint >( window_height ) );
340 
341  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
342 
343  glPixelStorei( GL_UNPACK_ROW_LENGTH, static_cast< GLint >( image.width( ) ) );
344  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
345  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
346  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolate_ );
347  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolate_ );
348 // glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
349  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
350 
351  pixel_data::glTexImage2D( image );
352 
353  glEnable( GL_TEXTURE_2D );
354 
355  double v0[2], v1[2], v2[2], v3[2], t0[2], t1[2], t2[2], t3[2];
356  double imgW = static_cast< double >( image_width );
357  double imgH = static_cast< double >( image_height );
358  double winW = static_cast< double >( window_width );
359  double winH = static_cast< double >( window_height );
360 
361  t0[0] = 0.0f;
362  t0[1] = imgH / ttt;
363  t1[0] = imgW / ttt;
364  t1[1] = imgH / ttt;
365  t2[0] = imgW / ttt;
366  t2[1] = 0.0;
367  t3[0] = 0.0;
368  t3[1] = 0.0;
369 
370  v0[0] = ( -1.0 - xpos / imgW ) * zoom;
371  v0[1] = ( -1.0 + ypos / imgH ) * zoom;
372  v1[0] = ( 1.0 - xpos / imgW ) * zoom;
373  v1[1] = ( -1.0 + ypos / imgH ) * zoom;
374  v2[0] = ( 1.0 - xpos / imgW ) * zoom;
375  v2[1] = ( 1.0 + ypos / imgH ) * zoom;
376  v3[0] = ( -1.0 - xpos / imgW ) * zoom;
377  v3[1] = ( 1.0 + ypos / imgH ) * zoom;
378 
379  double win_aspect = winH / winW;
380  double aspect = imgH * image.reso2( ) / image.reso1( ) / imgW;
381  if( win_aspect < aspect )
382  {
383  v0[0] *= win_aspect / aspect;
384  v1[0] *= win_aspect / aspect;
385  v2[0] *= win_aspect / aspect;
386  v3[0] *= win_aspect / aspect;
387  //fprintf(stdout, "draw1 %f %f (%f,%f) (%f,%f)\r", win_aspect, double(ia->h)*aspect/double(ia->w), v0[0], v0[1], v1[0], v1[1]);
388  }
389  else
390  {
391  v0[1] /= win_aspect / aspect;
392  v1[1] /= win_aspect / aspect;
393  v2[1] /= win_aspect / aspect;
394  v3[1] /= win_aspect / aspect;
395  //fprintf(stdout, "draw2 %f %f (%f,%f) (%f,%f)\r", win_aspect, double(ia->h)*aspect/double(ia->w), v0[0], v0[1], v1[0], v1[1]);
396  }
397 
398  glBegin( GL_QUADS );
399  glTexCoord2d( t0[0], t0[1] );
400  glVertex2d ( v0[0], v0[1] );
401  glTexCoord2d( t1[0], t1[1] );
402  glVertex2d ( v1[0], v1[1] );
403  glTexCoord2d( t2[0], t2[1] );
404  glVertex2d ( v2[0], v2[1] );
405  glTexCoord2d( t3[0], t3[1] );
406  glVertex2d ( v3[0], v3[1] );
407  glEnd( );
408 
409  glDisable( GL_TEXTURE_2D );
410 
411  if( isLighting == GL_TRUE ) glEnable( GL_LIGHTING );
412 
413  return( true );
414 }
415 
416 
458 template< class Array >
459 bool draw_image( const Array &image, typename Array::size_type window_width, typename Array::size_type window_height,
460  double zoom = 1.0, double xpos = 0.0, double ypos = 0.0, double back_r = 0.0, double back_g = 0.0, double back_b = 0.0, bool interpolate = true, bool blend = false )
461 {
462  typedef typename Array::size_type size_type;
463  typedef typename Array::value_type value_type;
464  typedef pixel_data::pixel< is_float< value_type >::value > pixel;
465  size_type size = image.width( ) > image.height( ) ? image.width( ) : image.height( );
466  size_type ttt = pixel_data::floor_square( size );
467 
468  if( !blend )
469  {
470  float r = pixel::get_value( back_r );
471  float g = pixel::get_value( back_g );
472  float b = pixel::get_value( back_b );
473 
474  glClearColor( r, g, b, 1.0f );
475  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
476  }
477 
478  if( ttt == image.width( ) && ttt == image.height( ) )
479  {
480  return( draw_buffer( image, ttt, ttt, window_width, window_height, zoom, xpos, ypos, interpolate ) );
481  }
482  else
483  {
484  static Array img;
485 
486  if( ttt > img.width( ) )
487  {
488  img.resize( ttt, ttt );
489  }
490  img.reso1( image.reso1( ) );
491  img.reso2( image.reso2( ) );
492 
493  size_type i, j;
494  for( j = 0 ; j < image.height( ) ; j++ )
495  {
496  for( i = 0 ; i < image.width( ) ; i++ )
497  {
498  img( i, j ) = image( i, j );
499  }
500  }
501 
502  return( draw_buffer( img, image.width( ), image.height( ), window_width, window_height, zoom, xpos, ypos, interpolate ) );
503  }
504 }
505 
506 
539 template< class Array >
540 bool draw_pixels( const Array &image, typename Array::size_type window_width, typename Array::size_type window_height,
541  typename Array::difference_type xpos = 0, typename Array::difference_type ypos = 0, bool blend = false )
542 {
543  typedef typename Array::size_type size_type;
544  typedef typename Array::value_type value_type;
545  typedef pixel_data::pixel< is_float< value_type >::value > pixel;
546 
547  if( image.empty( ) ) return( false );
548 
549  if( !blend )
550  {
551  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
552  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
553  }
554 
555  GLsizei w = static_cast< GLsizei >( window_width / 2 );
556  GLsizei h = static_cast< GLsizei >( window_height / 2 );
557 
558  glMatrixMode( GL_PROJECTION );
559  glLoadIdentity( );
560  gluOrtho2D( -w, w, -h, h );
561 
562  glMatrixMode( GL_MODELVIEW );
563  glLoadIdentity( );
564 
565  // 左上を原点とする画像座標系を設定
566  gluLookAt( w, h, -1, w, h, 0, 0, -1, 0 );
567 
568  GLboolean isLighting = glIsEnabled( GL_LIGHTING );
569  glDisable( GL_LIGHTING );
570  glEnable( GL_BLEND );
571 
572  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
573 
574  size_type ww = image.width( );
575  size_type hh = image.height( );
576 
577  glPixelStorei( GL_UNPACK_ROW_LENGTH, static_cast< GLint >( image.width( ) ) );
578  if( xpos < 0 )
579  {
580  glPixelStorei( GL_UNPACK_SKIP_PIXELS, static_cast< GLint >( -xpos ) );
581  ww = ww + xpos;
582  xpos = 0;
583  }
584  if( ypos < 0 )
585  {
586  glPixelStorei( GL_UNPACK_SKIP_ROWS, static_cast< GLint >( -ypos ) );
587  hh = hh + ypos;
588  ypos = 0;
589  }
590 
591  glRasterPos2i( static_cast< GLsizei >( xpos ), static_cast< GLsizei >( ypos ) );
592  glPixelZoom( 1.0f, -1.0f );
593  pixel_data::glDrawPixels( image, ww, hh );
594 
595  if( isLighting == GL_TRUE ) glEnable( GL_LIGHTING );
596 
597  return( true );
598 }
599 
600 
617 inline vector2< double > screen2point( const vector2< double > &pt, double imgX, double imgY, double aspect,
618  double winW, double winH, double zoom, double posx, double posy )
619 {
620  if( imgX == 0.0 || imgY == 0.0 || winW == 0.0 || winH == 0.0 )
621  {
622  return( vector2< double >( 0.0, 0.0 ) );
623  }
624 
625  double xx = ( pt.x - winW / 2.0 ) / winW * 2.0;
626  double yy = ( winH / 2.0 - pt.y ) / winH * 2.0;
627  double win_aspect = winH / winW;
628  aspect = imgY * aspect / imgX;
629  if( win_aspect < aspect )
630  {
631  xx = xx / win_aspect * aspect / zoom + posx / imgX;
632  yy = -( yy / zoom - posy / imgY );
633  }
634  else
635  {
636  xx = xx / zoom + posx / imgX;
637  yy = -( yy * win_aspect / aspect / zoom - posy / imgY );
638  }
639 
640  return( vector2< double >( ( xx + 1.0 ) * imgX * 0.5, ( yy + 1.0 ) * imgY * 0.5 ) );
641 }
642 
659 inline vector2< double > point2screen( const vector2< double > &pt, double imgX, double imgY, double aspect,
660  double winW, double winH, double zoom, double posx, double posy )
661 {
662  if( imgX == 0.0 || imgY == 0.0 || winW == 0.0 || winH == 0.0 )
663  {
664  return( vector2< double >( 0.0, 0.0 ) );
665  }
666 
667  double xx = ( pt.x - imgX / 2.0 ) / imgX * 2.0;
668  double yy = ( imgY / 2.0 - pt.y ) / imgY * 2.0;
669  double win_aspect = winH / winW;
670  aspect = imgY * aspect / imgX;
671  if( win_aspect < aspect )
672  {
673  xx = ( xx - posx / imgX ) * zoom * win_aspect / aspect;
674  yy = ( yy + posy / imgY ) * zoom;
675  }
676  else
677  {
678  xx = ( xx - posx / imgX ) * zoom;
679  yy = ( yy + posy / imgY ) * zoom / win_aspect * aspect;
680  }
681  return( vector2< double >( ( xx + 1.0 ) * winW * 0.5, ( 1.0 - yy ) * winH * 0.5 ) );
682 }
683 
684 
686 // 画像描画グループの終わり
687 
688 
689 // mist名前空間の終わり
690 _MIST_END
691 
692 
693 #endif // __INCLUDE_MIST_DRAW__
694 

Generated on Wed Nov 12 2014 19:44:14 for MIST by doxygen 1.8.1.2