Logo Search packages:      
Sourcecode: timfx version File versions  Download package

gl_corner_out.cc

// timfx 
// Copyright 2002, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "gl_corner_out.h"

#include <kino/image_transitions.h>

#include <gtkmm/box.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/label.h>
#include <gtkmm/main.h>
#include <gtkmm/menu.h>
#include <gtkmm/optionmenu.h>
#include <gtkmm/window.h>
#include <sigc++/sigc++.h>

#include <algorithm>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include "kino_opengl_utility.h"

namespace
{

class gl_corner_out :
      public GDKImageTransition
{
public:
      gl_corner_out() :
            m_interlaced(true),
            m_even_field_first(true)
      {
            Gtk::Main main(0, 0);

            // Setup our user interface ...
            Gtk::Menu* const corner_menu = new Gtk::Menu();
            corner_menu->append(*manage(new Gtk::MenuItem("Upper Left")));
            corner_menu->items().back().signal_activate().connect(sigc::mem_fun(*this, &gl_corner_out::on_upper_left));
            
            corner_menu->append(*manage(new Gtk::MenuItem("Upper Right")));
            corner_menu->items().back().signal_activate().connect(sigc::mem_fun(*this, &gl_corner_out::on_upper_right));
            
            corner_menu->append(*manage(new Gtk::MenuItem("Lower Right")));
            corner_menu->items().back().signal_activate().connect(sigc::mem_fun(*this, &gl_corner_out::on_lower_right));
            
            corner_menu->append(*manage(new Gtk::MenuItem("Lower Left")));
            corner_menu->items().back().signal_activate().connect(sigc::mem_fun(*this, &gl_corner_out::on_lower_left));       
            
            m_corner_option_menu.set_menu(*manage(corner_menu));
            m_corner_option_menu.set_history(UPPER_LEFT);
            
            m_interlaced_button.add(*manage(new Gtk::Label("Interlace")));
            m_interlaced_button.set_active(m_interlaced);

            m_even_field_first_button.add(*manage(new Gtk::Label("Even Field First")));
            m_even_field_first_button.set_active(m_even_field_first);

            Gtk::VBox* const vbox = new Gtk::VBox(false, 0);
            vbox->pack_start(m_corner_option_menu, false, true);
            vbox->pack_start(m_interlaced_button, false, true);
            vbox->pack_start(m_even_field_first_button, false, true);
            vbox->show_all();

            m_window.add(*manage(vbox));
      }
      
      char *GetDescription( ) const
      {
            return "Corner Out (OpenGL)"; 
      }

      void GetFrame( uint8_t *io, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
      {
            // Uncomment this to disable pbuffer rendering
//          kino::gl::use_pbuffers(false);      

            if(0 == m_buffer.get())
                  m_buffer.reset(new kino::gl::render_buffer(width, height));

            // Start drawing ...
            m_buffer->start_render();

            // Fill the background with the "A" footage ...
            m_buffer->draw_background(width, height, io);
            
            // Setup matrices
            glMatrixMode(GL_PROJECTION);
            glOrtho(0, 1, 1, 0, -1, 1);

            // Setup environment ...
            glDisable(GL_LIGHTING);

            // Setup our texture ...
            if(0 == position)
                  {
                        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                        std::vector<GLubyte> empty_texture(1024 * 512 * 3, 0);
                        glTexImage2D(GL_TEXTURE_2D, 0, 3, 1024, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, &empty_texture[0]);
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                        glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
                        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
                        glEnable(GL_TEXTURE_2D);
                  }
                                    
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, mesh);         
            kino::gl::push_matrix texture_matrix(GL_TEXTURE);
            glLoadIdentity();
            glScaled(width / 1024.0, height / 512.0, 1.0);

            // Field rendering loop ...   
            for(int field = 0; field < (m_interlaced ? 2 : 1); ++field)
                  {
                        if(m_interlaced)
                              {
                                    m_buffer->render_field(m_even_field_first ? field : 1 - field);
                              }
                        else
                              {
                                    m_buffer->render_frame();
                              }

                        // Offset the position based on which field we're looking at ...
                        const double field_position = position + field * frame_delta * 0.5;

                        // Draw our frame ...
                        glColor3d(1, 1, 1);
                        glBegin(GL_QUADS);
                        
                        switch(m_corner)
                              {
                                    case UPPER_LEFT:
                                          glTexCoord2d(0, 0); glVertex2d(0, 0);
                                          glTexCoord2d(1, 0); glVertex2d(field_position, 0);
                                          glTexCoord2d(1, 1); glVertex2d(field_position, field_position);
                                          glTexCoord2d(0, 1); glVertex2d(0, field_position);
                                          break;
                                    case UPPER_RIGHT:
                                          glTexCoord2d(0, 0); glVertex2d(1-field_position, 0);
                                          glTexCoord2d(1, 0); glVertex2d(1, 0);
                                          glTexCoord2d(1, 1); glVertex2d(1, field_position);
                                          glTexCoord2d(0, 1); glVertex2d(1-field_position, field_position);
                                          break;
                                    case LOWER_RIGHT:
                                          glTexCoord2d(0, 0); glVertex2d(1-field_position, 1-field_position);
                                          glTexCoord2d(1, 0); glVertex2d(1, 1-field_position);
                                          glTexCoord2d(1, 1); glVertex2d(1, 1);
                                          glTexCoord2d(0, 1); glVertex2d(1-field_position, 1);
                                          break;
                                    case LOWER_LEFT:
                                          glTexCoord2d(0, 0); glVertex2d(0, 1-field_position);
                                          glTexCoord2d(1, 0); glVertex2d(field_position, 1-field_position);
                                          glTexCoord2d(1, 1); glVertex2d(field_position, 1);
                                          glTexCoord2d(0, 1); glVertex2d(0, 1);
                                          break;
                              }
                              
                        glEnd();
                  }
                        
            // Finish drawing ...
            m_buffer->finish_render();

            // Copy rendered image back to Kino
            m_buffer->read_pixels(width, height, io);
      }

      void AttachWidgets(GtkBin* bin)
      {
            gtk_widget_reparent( ( GTK_BIN( m_window.gobj() ) )->child, GTK_WIDGET( bin ) );
      }

      void DetachWidgets(GtkBin* bin)
      {
            gtk_widget_reparent( ( GTK_BIN( bin ) )->child, GTK_WIDGET( m_window.gobj() ) );
      }

      void InterpretWidgets( GtkBin *bin )
      {
            m_interlaced = m_interlaced_button.get_active();
            m_even_field_first = m_even_field_first_button.get_active();
            
            m_buffer.reset(0);
      }

private:
      void on_upper_left()
      {
            m_corner = UPPER_LEFT;
      }

      void on_upper_right()
      {
            m_corner = UPPER_RIGHT;
      }

      void on_lower_right()
      {
            m_corner = LOWER_RIGHT;
      }

      void on_lower_left()
      {
            m_corner = LOWER_LEFT;
      }

      typedef enum
      {
            UPPER_LEFT,
            UPPER_RIGHT,
            LOWER_RIGHT,
            LOWER_LEFT
      } corner_type;
      
      corner_type m_corner;
      bool m_interlaced;
      bool m_even_field_first;

      Gtk::Window m_window;
      Gtk::OptionMenu m_corner_option_menu;
      Gtk::CheckButton m_interlaced_button;
      Gtk::CheckButton m_even_field_first_button;
      
      std::auto_ptr<kino::gl::render_buffer> m_buffer;
};

} // namespace

GDKImageTransition* gl_corner_out_factory()
{
      return new gl_corner_out();
}

Generated by  Doxygen 1.6.0   Back to index