- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

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名前空間の始まり
65 _MIST_BEGIN
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