void Video_DX9::init_context() {
    // Enable Alpha Blitting
    m_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    m_d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    m_d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    m_d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);

    // Configure Texture Stages
    m_d3d_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
    m_d3d_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
    m_d3d_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
    m_d3d_device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);

    // Set Lighting Variables
    m_d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, true);

    // Multisampling
    m_d3d_device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, DWORD(get_multisampling() > 1));

    // More basic stuff
    set_2d();
    set_color(get_color());
    set_clear_color(get_clear_color());
    set_backface_culling(get_backface_culling());
    set_lighting(get_lighting());
    set_ambient_lighting(get_ambient_lighting());
    set_alpha_test(is_alpha_test_enabled(), get_alpha_test_function(), get_alpha_test_value());
    set_zwrite(is_zwrite_enabled());
    set_ztest(is_ztest_enabled());
  }
Example #2
0
void View::resize(int w_, int h_) {
    
    if (w == w_ && h == h_) {
        
        did_resize(w_,h_);
        return;
    }
    
    w = w_; h = h_;
    View temp(w,h);

    std::swap(image, temp.image);
    std::swap(display, temp.display);
    
    if (is_alpha) {
        set_clear_color(clear_color);
        fill_with_color(clear_color);
    }
    
    SDL_Rect dest_rect = {0, 0, w, h};
	SDL_BlitSurface(temp.image, 0, image, &dest_rect);

    mark_changed();
    did_resize(w_,h_);
}
Example #3
0
int main() {

  test_colors();
  test_dynamic_array();
  test_vectors();
  test_physics();

  int pixels[] = {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
		  0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
		  0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
		  0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
		  0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
		  0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff};
  
  color pixels2[10000];
  for (int i = 0; i < 10000; i++) pixels2[i] = 0xE650E1FF;

  int window_width = 800;
  int window_height = 600;
  
  init_graphics();

  renderer_handle rend = create_window(window_width, window_height, "TEST", 0);
  texture_handle tex = load_texture_data(rend, pixels, 6, 6);
  texture_handle tex2 = load_texture_data(rend, pixels2, 100, 100);
  set_clear_color(rend, get_color(0,0,0,0xFF));

  while (SDL_GetTicks() < 10000) {
    clear(rend);
    double theta = (double) SDL_GetTicks() / 300;
    double r = 200 * cos(3*theta/5);

    int x1 = r*cos(theta) - 3 + window_width/2;
    int y1 = r*sin(theta) - 3 + window_height/2;
    int x2 = r*cos(theta + 2*PI/3) - 3 + window_width/2;
    int y2 = r*sin(theta + 2*PI/3) - 3 + window_height/2;
    int x3 = r*cos(theta - 2*PI/3) - 3 + window_width/2;
    int y3 = r*sin(theta - 2*PI/3) - 3 + window_height/2;

    double scale = .75 - .25 * cos(6*theta/5);
    int s = 100 * scale;

    draw(rend, tex2, (window_width - s) / 2, (window_height - s) / 2, -theta, s/2, s/2, 0, 0, scale);
    draw(rend, tex, x1, y1, 0, 0, 0, 0, 0, 1);
    draw(rend, tex, x2, y2, 0, 0, 0, 0, 0, 1);
    draw(rend, tex, x3, y3, 0, 0, 0, 0, 0, 1);
    show(rend);
    SDL_Delay(16);
  }

  destroy_window(rend);
  cleanup();
  
  return 0;
}
void DropDownMenu::init_menu_view(int text_size_) {
    
    
    // Init main view
    resize(get_w(), text_size_ + vertical_padding*2);
    text_size = text_size_;
    selected_entry_idx = 0;
    menu = 0; clicked = false;
    
    set_clear_color(green_color_c);
    fill_with_color(get_clear_color());
    

    // Init menu view
    
    int row_size = (text_size + vertical_padding*2);
    menu = new View(get_w(), (int)(entries.size() ? entries.size() : 1) * row_size);
    
    // always display at least one entry
    menu->draw_onto_self(GUIImage("GUIImages/dropdown_row.bmp"), DispPoint());

    // display full menu
    int i = 0;
    for (list<string>::iterator it = entries.begin(); it != entries.end(); ++it, ++i) {
        
//        menu->attach_subview(new MenuEntry(*it, text_size, *this, i),
//                                                    DispPoint(0, i * row_size));
        
        menu->draw_onto_self(GUIImage("GUIImages/dropdown_row.bmp"),
                             DispPoint(0, i * row_size));

        menu->attach_subview(createTextView(*it, text_size),
                                                    DispPoint(0, i * row_size));

    }
    
    attach_subview(menu, DispPoint());
    
}
ScrollView::ScrollView(int w_, int h_, View *display_view_)
:View(w_,h_), 
scroll_bar(SCROLL_BAR_W, h_ * h_/display_view_->get_h(), this),
scroll_bar_bg(SCROLL_BAR_W, h_, this), 
arrow_up(true, GUIImage("GUIImages/scroll_bar_vert2.bmp")),
arrow_down(false, GUIImage("GUIImages/scroll_bar_vert3.bmp")),
display_view(display_view_),
w_init(w_), h_init(h_),
scroll_y(0), scroll_y_vel(0), scrolling(false)
{
    SDL_Color clear = {0xff, 0, 0xff};
    GUIImage bg = GUIImage::create_filled(w_, h_, clear);
    draw_onto_self(bg, VGPoint());
    set_clear_color(clear);
    
    attach_subview(display_view_, VGPoint());
    
    if (display_view->get_h() <= get_h()) {
        scrollable = false;
        
        resize(min(display_view->get_w(), w_),
               min(display_view->get_h(), h_));
        
        return; // todo Remove to so you can resize later.
    }
    scrollable = true;    
    
    scroll_bar_bg.display();
    scroll_bar.display();
    
    scroll_bar_x = get_w()-scroll_bar_bg.get_w();
    attach_subview(&scroll_bar_bg, VGPoint(scroll_bar_x, 0));
    attach_subview(&arrow_up, VGPoint(scroll_bar_x, scroll_bar_bottom-7)); // HACK!!
    attach_subview(&arrow_down, VGPoint(scroll_bar_x, scroll_bar_bottom-7+arrow_up.get_h())); // HACK!!
    
    attach_subview(&scroll_bar, VGPoint(scroll_bar_x, scroll_bar_top));
    
}
	renderer::renderer(const renderer_settings& settings) : current_settings(settings) {
#if BUILD_OPENGL
		LOG("Calling gladLoadGL: %x.", intptr_t(gladLoadGL));
		if (!gladLoadGL()) {
			LOG("Calling gladLoadGL failed.");
			throw renderer_error("Failed to initialize GLAD!"); 		
		}
#endif

		LOG("glBlendFuncSeparate ADDR: %x", intptr_t(glBlendFuncSeparate));

		LOG("Calling gladLoadGL succeeded.");
		
		set_blending(true);

		set_standard_blending();
		set_clear_color(black);
		 
		GL_CHECK(glDisable(GL_DITHER));
		GL_CHECK(glDisable(GL_LINE_SMOOTH));
		GL_CHECK(glDisable(GL_POLYGON_SMOOTH));
		GL_CHECK(glDisable(GL_MULTISAMPLE));
		GL_CHECK(glDisable(GL_DEPTH_TEST));
		GL_CHECK(glDepthMask(GL_FALSE));

		GL_CHECK(glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST));
		GL_CHECK(glHint(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST));
		
		GL_CHECK(glGenVertexArrays(1, &vao_buffer));
		GL_CHECK(glBindVertexArray(vao_buffer));
		
		GL_CHECK(glGenBuffers(1, &imgui_elements_id));

		GL_CHECK(glGenBuffers(1, &triangle_buffer_id));
		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, triangle_buffer_id));

		GL_CHECK(glEnableVertexAttribArray(static_cast<int>(vertex_attribute::position)));
		GL_CHECK(glEnableVertexAttribArray(static_cast<int>(vertex_attribute::texcoord)));
		GL_CHECK(glEnableVertexAttribArray(static_cast<int>(vertex_attribute::color)));

		GL_CHECK(glVertexAttribPointer(static_cast<int>(vertex_attribute::position), 2, GL_FLOAT, GL_FALSE, sizeof(vertex), nullptr));
		GL_CHECK(glVertexAttribPointer(static_cast<int>(vertex_attribute::texcoord), 2, GL_FLOAT, GL_FALSE, sizeof(vertex), reinterpret_cast<char*>(sizeof(float) * 2)));
		GL_CHECK(glVertexAttribPointer(static_cast<int>(vertex_attribute::color), 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(vertex), reinterpret_cast<char*>(sizeof(float) * 2 + sizeof(float) * 2)));

		GL_CHECK(glGenBuffers(1, &special_buffer_id));
		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, special_buffer_id));

		enable_special_vertex_attribute();
		GL_CHECK(glVertexAttribPointer(static_cast<int>(vertex_attribute::special), sizeof(special) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(special), nullptr));
		disable_special_vertex_attribute();

		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, triangle_buffer_id));
	
#if USE_BUFFER_SUB_DATA
		/* Preallocate necessary space */

		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, triangle_buffer_id));
		GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) * 30000, nullptr, GL_STREAM_DRAW));
		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, special_buffer_id));
		GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(special) * 6000, nullptr, GL_STREAM_DRAW));
		GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, imgui_elements_id));
		GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned) * 12000, nullptr, GL_STREAM_DRAW));
#endif

#if BUILD_OPENGL
		GLint read_size = 0;
		GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &read_size));
		ensure(read_size >= 0);
		max_texture_size = static_cast<unsigned>(read_size);
#else
		max_texture_size = 0u;
#endif

		apply(settings, true);
	}
Example #7
0
  void Video_GL::init() {
    std::cout << "Initializing OpenGL" << std::endl;

    //double buffer, no stencil, no accumulation buffer
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);

    if(get_multisampling() > 1) {
      SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, get_multisampling());
      SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
    }

    set_opengl_flag(true);
    Video::init();

#if SDL_VERSION_ATLEAST(1,3,0)
    m_context = SDL_GL_CreateContext(get_window());
#endif

    {
      const GLenum err = glewInit();
      if(GLEW_OK != err) {
        std::cerr << "GLEW Error: " << glewGetErrorString(err) << std::endl;
        throw Video_Init_Failure();
      }
    }

    // Set Fill/Shade Mode
    glShadeModel(GL_SMOOTH);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glEnable(GL_NORMALIZE); //GL_RESCALE_NORMALIZE);

    // Enable Alpha Blitting
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    //glBlendEquation(GL_FUNC_ADD); // default // would require ARB ext

    // Set lighting variables
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
    glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
    if(glGetError() == GL_INVALID_ENUM)
      std::cerr << "Quality Warning:  Your graphics card does not support separate specular lighting in OpenGL.\n";

    // Initialize Assorted Variables
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    //glPointSize(static_cast<GLfloat>(sqrt(pow(double(get_screen_width()), 2.) * pow(double(get_screen_height()), 2.)) / 1000000));
    //glLineWidth(static_cast<GLfloat>(sqrt(pow(double(get_screen_width()), 2.) * pow(double(get_screen_height()), 2.)) / 1000000));

    // Finish with a few function calls
    set_2d();
    set_color(get_color());
    set_clear_color(get_clear_color());
    set_backface_culling(get_backface_culling());
    set_lighting(get_lighting());
    set_ambient_lighting(get_ambient_lighting());
    set_alpha_test(is_alpha_test_enabled(), get_alpha_test_function(), get_alpha_test_value());
    set_zwrite(is_zwrite_enabled());
    set_ztest(is_ztest_enabled());

    union {
      void * v;
#ifdef _LINUX
      PFNGLXSWAPINTERVALEXTPROC pglSwapIntervalEXT;
      PFNGLXSWAPINTERVALSGIPROC pglSwapIntervalSGI;
#endif
      PFNGLBINDBUFFERARBPROC pglBindBufferARB;
      PFNGLDELETEBUFFERSARBPROC pglDeleteBuffersARB;
      PFNGLGENBUFFERSARBPROC pglGenBuffersARB;
      PFNGLBUFFERDATAARBPROC pglBufferDataARB;
    } ptr;

#ifdef _LINUX
    ptr.v = SDL_GL_GetProcAddress("glXSwapIntervalEXT");
    if(!ptr.v)
      ptr.v = SDL_GL_GetProcAddress("wglSwapIntervalEXT");
    m_pglSwapIntervalEXT = ptr.pglSwapIntervalEXT;

    ptr.v = SDL_GL_GetProcAddress("glXSwapIntervalSGI");
    if(!ptr.v)
      ptr.v = SDL_GL_GetProcAddress("wglSwapIntervalSGI");
    m_pglSwapIntervalSGI = ptr.pglSwapIntervalSGI;
#endif

    // Has to be done after finding the function pointer
    set_vertical_sync(get_vertical_sync());

    m_vertex_buffers = strstr(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)), "ARB_vertex_buffer_object") != 0;
    if(m_vertex_buffers) {
      ptr.v = SDL_GL_GetProcAddress("glBindBufferARB");
      m_pglBindBufferARB = ptr.pglBindBufferARB;

      ptr.v = SDL_GL_GetProcAddress("glDeleteBuffersARB");
      m_pglDeleteBuffersARB = ptr.pglDeleteBuffersARB;

      ptr.v = SDL_GL_GetProcAddress("glGenBuffersARB");
      m_pglGenBuffersARB = ptr.pglGenBuffersARB;

      ptr.v = SDL_GL_GetProcAddress("glBufferDataARB");
      m_pglBufferDataARB = ptr.pglBufferDataARB;
    }
    else
      std::cerr << "Performance Warning:  Your graphics card does not offer Vertex Buffer Objects (VBO) in OpenGL.\n";

    if(strstr((char*)glGetString(GL_EXTENSIONS), "GL_EXT_texture_filter_anisotropic"))
      glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, reinterpret_cast<GLint *>(&m_maximum_anisotropy));
    else
      m_maximum_anisotropy = 0;
  }
void sphere()
{    
    SetGeomScreen(1000);     
    MATRIX m;
    VECTOR trans = {0, 0, 300};
    TransMatrix(&m, &trans);
    SetTransMatrix(&m);      
    const int SPHERE_LATITUDE = 24;
    const int SPHERE_LONGITUDE = 24;
    const int SPHERE_RADIUS = 50;
    SVECTOR* sphere_vector = (SVECTOR*)MemoryManager::malloc(SPHERE_LATITUDE * SPHERE_LONGITUDE * sizeof(*sphere_vector));   
    POLY_G4* poly_sphere = (POLY_G4*)MemoryManager::malloc(SPHERE_LATITUDE * SPHERE_LONGITUDE * sizeof(*poly_sphere));
    {
        /**
         *  x <- r * sin(\alpha) * cos(\beta)
         *  y <- r * sin(\alpha) * sin(\beta)
         *  z <- r * cos(\alpha)
         * avec:
         *   \alpha \in [0, pi] : latitude
         *   \beta \in [0, 2*pi] : longitude
         */ 
        SVECTOR* v = sphere_vector;
        for ( int la = 0; la < SPHERE_LATITUDE; la++ ) {
            int alpha = (TRIGO_PI * la) / SPHERE_LATITUDE;
            int sa = sin4k[alpha];
            int ca = cos4k[alpha];
            for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, v++ ) {
                int beta = (2 * TRIGO_PI * lo) / SPHERE_LONGITUDE;
                unsigned short x = (SPHERE_RADIUS * sa * cos4k[beta]) / (TRIGO_SCALE * TRIGO_SCALE);
                unsigned short y = (SPHERE_RADIUS * sa * sin4k[beta]) / (TRIGO_SCALE *TRIGO_SCALE);
                unsigned short z = (SPHERE_RADIUS * ca) / TRIGO_SCALE;
                setVector(v, x, y, z);             
            }            
        }
        POLY_G4* p = poly_sphere;        
        for ( int la = 0; la < SPHERE_LATITUDE; la++ ) {
            for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, p++ ) {
                SetPolyG4(p);
            }
        }        
    }
    set_clear_color(0);
    static const int SPHERE_TRANSITION_STEP = 200;
    static const int SPHERE_STEP_TIME = 600;
            
    enum { SCENE_LAT_FLAT = 1, 
           SCENE_LAT_SMOOTH,
           SCENE_LIGHT_FIX_EDGE,
           SCENE_LIGHT_FIX_SQUARE,
           SCENE_LIGHT_FIX,
           SCENE_LIGHT_MOVE,
           SCENE_LIGHT_CUTOFF,
           SCENE_ZOOM,
           SCENE_LIGHT_SINUS_WAVE, };
    int current_scene = SCENE_LAT_FLAT;
    int t = 0;
    enable_auto_clear_color_buffer();    
    while ( t < SCENE_LIGHT_SINUS_WAVE * SPHERE_STEP_TIME)
    {
        SVECTOR rot = {8*t%4096, 4*t%4096, 10*t%4096};
        RotMatrix(&rot, &m);
        SetRotMatrix(&m);
        
        // update sphere    
        POLY_G4* p = poly_sphere;        
        
        // offset plasma
        static int off = 0; 
        if ( t >= 100 && t % 5 == 0 ) off++;  
                
        // light move
        static int light_move_lat = 0;
        static int light_move_long = 0;
        static int light_move_dlat = 1;
        static int light_move_dlong = 1;           
        if ( t % 1 == 0 ) {
            if ( t % 3 == 0 ) {
                light_move_lat += light_move_dlat; 
                if ( light_move_lat < 0 ) light_move_lat = 0; 
                if ( light_move_lat >= SPHERE_LATITUDE ) light_move_lat = SPHERE_LATITUDE-1;
                if ( light_move_lat == 0 || light_move_lat == SPHERE_LATITUDE-1 ) light_move_dlat *= -1;
            }
            if ( t % 1 == 0 ) {
                light_move_long += light_move_dlong; 
                if ( light_move_long < 0 ) light_move_long = 0; 
                if ( light_move_long >= SPHERE_LONGITUDE ) light_move_long = SPHERE_LONGITUDE-1;
                if ( light_move_long == 0 || light_move_long == SPHERE_LONGITUDE-1 ) light_move_long *= -1;
            }
        }     

        // dynamic cutoff
        static int light_dynamic_distance_max = 50;        
        if ( current_scene == SCENE_LIGHT_CUTOFF && t % 1 == 0 ) {            
            static const int LIGHT_DYNAMIC_DISTANCE_MIN = 20;
            static const int LIGHT_DYNAMIC_DISTANCE_MAX = 60;
            static int light_dynamic_ddist = -1;
            light_dynamic_distance_max += light_dynamic_ddist;
            if ( light_dynamic_distance_max <= LIGHT_DYNAMIC_DISTANCE_MIN || light_dynamic_distance_max >= LIGHT_DYNAMIC_DISTANCE_MAX ) light_dynamic_ddist *= -1;
        }
        int light_dynamic_distance_max2 = light_dynamic_distance_max * light_dynamic_distance_max;   
        
        // dynamic radius         
        if ( current_scene >= SCENE_ZOOM && t % 1 == 0 ) {                        
            static const int ZOOM_MIN = 150;
            static const int ZOOM_MAX = 900;
            static int zoom_stride = 15;
            static int zoom = 300;            
            SetGeomScreen(zoom);            
            zoom += zoom_stride;
            if ( zoom <= ZOOM_MIN || zoom >= ZOOM_MAX ) zoom_stride *= -1;
        }        
                
        int dt = 1;
        for ( int la = 0; la < SPHERE_LATITUDE; la++ ) {
            for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, p++ ) {                
                int lo_next = (lo+1)%SPHERE_LONGITUDE;
                int la_next = SignalProcessing::min(la+1, SPHERE_LATITUDE-1);                
                SVECTOR* v0 = &sphere_vector[la*SPHERE_LONGITUDE+lo];
                SVECTOR* v1 = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                SVECTOR* v2 = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];
                SVECTOR* v3 = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                
                long dmy, flag;
                int otz = 0;
                otz += RotTransPers(v0, (long*)&p->x0, &dmy, &flag);                 
                otz += RotTransPers(v1, (long*)&p->x1, &dmy, &flag);                 
                otz += RotTransPers(v2, (long*)&p->x2, &dmy, &flag);                
                otz += RotTransPers(v3, (long*)&p->x3, &dmy, &flag);
                otz /= 4;
                limitRange(otz, 0, OT_LENGTH-1);
                AddPrim(ot + OT_LENGTH - 1 - otz, p);                
                if ( t < SCENE_LAT_FLAT*SPHERE_STEP_TIME ) { // latitude same flat color
                    current_scene = SCENE_LAT_FLAT;
                    unsigned char b = 255 * la / SPHERE_LATITUDE;                     
                    setRGB0(p, b, b, b);
                    setRGB1(p, b, b, b);
                    setRGB2(p, b, b, b);
                    setRGB3(p, b, b, b);
                } else if ( t < SCENE_LAT_SMOOTH*SPHERE_STEP_TIME ) { // latitude same smooth color
                    current_scene = SCENE_LAT_SMOOTH;
                    unsigned char b = 255 * la / SPHERE_LATITUDE;  
                    unsigned char bb = 255 * ((la+1)%SPHERE_LATITUDE) / SPHERE_LATITUDE;
                    if ( t < (SCENE_LAT_SMOOTH-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB1(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB3(p, bb, bb, bb);
                } else if ( t < SCENE_LIGHT_FIX_EDGE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix
                    dt = 3;
                    current_scene = SCENE_LIGHT_FIX_EDGE;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    const int LIGHT_LAT = 3*SPHERE_LATITUDE/4;
                    const int LIGHT_LONG = SPHERE_LONGITUDE/4;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG];
                    SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];
                    SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];
                    int d = SignalProcessing::dist2(l, v);
                    int dd = SignalProcessing::dist2(l, vv);
                    b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                    bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                    // smooth
                    if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB1(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB3(p, bb, bb, bb);
                } else if ( t < SCENE_LIGHT_FIX_SQUARE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix
                    dt = 3;
                    current_scene = SCENE_LIGHT_FIX_SQUARE;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    const int LIGHT_LAT = 3*SPHERE_LATITUDE/4;
                    const int LIGHT_LONG = SPHERE_LONGITUDE/4;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG];
                    SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                    SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                    int d = SignalProcessing::dist2(l, v);
                    int dd = SignalProcessing::dist2(l, vv);
                    int ddd = SignalProcessing::dist2(l, vvv);
                    int dddd = SignalProcessing::dist2(l, vvvv);
                    b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                    bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                    bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2;
                    bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2;                    
                    // smooth
                    if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB1(p, bb, bb, bb);
                    setRGB2(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);                     
                } else if ( t < SCENE_LIGHT_FIX*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix
                    dt = 1;
                    current_scene = SCENE_LIGHT_FIX;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    const int LIGHT_LAT = 3*SPHERE_LATITUDE/4;
                    const int LIGHT_LONG = SPHERE_LONGITUDE/4;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG];
                    SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                    SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                    int d = SignalProcessing::dist2(l, v);
                    int dd = SignalProcessing::dist2(l, vv);
                    int ddd = SignalProcessing::dist2(l, vvv);
                    int dddd = SignalProcessing::dist2(l, vvvv);
                    b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                    bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                    bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2;
                    bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2;                    
                    // smooth
                    if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);                    
                } else if ( t < SCENE_LIGHT_MOVE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move
                    current_scene = SCENE_LIGHT_MOVE;
                    unsigned char b = 255;
                    unsigned char bb = 255;                    
                    unsigned char bbb = 255;                    
                    unsigned char bbbb = 255;                    
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                        bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                        bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2;
                        bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2;                       
                    }
                    // smooth
                    if ( t < (SCENE_LIGHT_MOVE-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);      
                } else if ( t < SCENE_LIGHT_CUTOFF*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move + dynamic cutoff 
                    current_scene = SCENE_LIGHT_CUTOFF;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, light_dynamic_distance_max2 - d) * b) / light_dynamic_distance_max2;
                        bb = (SignalProcessing::max(0,  light_dynamic_distance_max2 - dd) * bb) / light_dynamic_distance_max2;                    
                        bbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - ddd) * bbb) / light_dynamic_distance_max2;
                        bbbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dddd) * bbbb) / light_dynamic_distance_max2;
                    }
                    // smooth
                    if ( t < (SCENE_LIGHT_CUTOFF-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);     
                } else if ( t < SCENE_ZOOM*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move + dynamic cutoff + zoom
                    current_scene = SCENE_ZOOM;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, light_dynamic_distance_max2 - d) * b) / light_dynamic_distance_max2;
                        bb = (SignalProcessing::max(0,  light_dynamic_distance_max2 - dd) * bb) / light_dynamic_distance_max2;                    
                        bbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - ddd) * bbb) / light_dynamic_distance_max2;
                        bbbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dddd) * bbbb) / light_dynamic_distance_max2;                   
                    }
                    // smooth
                    if ( t < (SCENE_ZOOM-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);
                }                 
                else { // smooth bande move + lighting move
                    current_scene = SCENE_LIGHT_SINUS_WAVE;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    const int NB_COLOR = 5;                    
                    unsigned char b = (255 * (((la+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    unsigned char bb = (255 * (((la+1+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    unsigned char bbb = (255 * (((la+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    unsigned char bbbb = (255 * (((la+1+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                        bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; 
                        bbb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2; 
                        bbbb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2; 
                    }
                    // smooth
                    if ( t < 5*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);
                }                
            }
        }        
        display();
        t += dt;
    }    
    MemoryManager::free(sphere_vector);    
    MemoryManager::free(poly_sphere);    
}