| @@ -37,14 +37,15 @@ public: | |||
| { | |||
| m_size = size; | |||
| m_pixels = new u8vec4[size.x * size.y]; | |||
| m_tmppixels = new u8vec4[size.x / 2 * size.y / 2]; | |||
| m_frame = -1; | |||
| m_dirty = 8; | |||
| for (int i = 0; i < 4; i++) | |||
| { | |||
| m_deltashift[i] = 0.0; | |||
| m_deltascale[i] = 1.0; | |||
| m_dirty[i] = 2; | |||
| } | |||
| m_center = -0.75; | |||
| //f64cmplx(0.001643721971153, 0.822467633298876); | |||
| //f64cmplx(-1.207205434596, 0.315432814901); | |||
| //f64cmplx(-0.79192956889854, -0.14632423080102); | |||
| //f64cmplx(0.3245046418497685, 0.04855101129280834); | |||
| //f64cmplx(0.28693186889504513, 0.014286693904085048); | |||
| m_radius = 1.5; | |||
| m_screenradius = 0.5 * (m_size.x < m_size.y ? m_size.x : m_size.y); | |||
| m_ready = false; | |||
| @@ -74,12 +75,13 @@ public: | |||
| Ticker::Unref(m_mousetext); | |||
| Ticker::Unref(m_zoomtext); | |||
| delete m_pixels; | |||
| delete m_tmppixels; | |||
| } | |||
| inline f64cmplx ScreenToWorldOffset(ivec2 pixel) | |||
| { | |||
| f64cmplx tmp = f64cmplx(pixel.x - m_size.x / 2, | |||
| m_size.y / 2 - pixel.y); | |||
| f64cmplx tmp = f64cmplx(0.5 + pixel.x - m_size.x / 2, | |||
| 0.5 + m_size.y / 2 - pixel.y); | |||
| return tmp * (m_radius / m_screenradius); | |||
| } | |||
| @@ -94,6 +96,8 @@ public: | |||
| ivec3 buttons = Input::GetMouseButtons(); | |||
| if ((buttons[0] || buttons[2]) && mousepos.x != -1) | |||
| { | |||
| f64cmplx oldcenter = m_center; | |||
| double oldradius = m_radius; | |||
| double zoom = pow(2.0, (buttons[0] ? -deltams : deltams) * 0.0015); | |||
| if (m_radius * zoom > 8.0) | |||
| zoom = 8.0 / m_radius; | |||
| @@ -102,9 +106,24 @@ public: | |||
| m_radius *= zoom; | |||
| m_center = (m_center - worldmouse) * zoom + worldmouse; | |||
| worldmouse = m_center + ScreenToWorldOffset(mousepos); | |||
| m_dirty = 8; | |||
| /* Store the transformation properties to go from m_frame-1 | |||
| * to m_frame. */ | |||
| m_deltashift[m_frame] = (oldcenter - m_center) / m_radius; | |||
| m_deltascale[m_frame] = oldradius / m_radius; | |||
| m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2; | |||
| } | |||
| else | |||
| { | |||
| /* If settings didn't change, set transformation from previous | |||
| * frame to identity. */ | |||
| m_deltashift[m_frame] = 0.0; | |||
| m_deltascale[m_frame] = 1.0; | |||
| } | |||
| if (buttons[1]) | |||
| m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2; | |||
| char buf[128]; | |||
| sprintf(buf, "center: %+13.11f%+13.11fi", m_center.x, m_center.y); | |||
| m_centertext->SetText(buf); | |||
| @@ -115,9 +134,9 @@ public: | |||
| u8vec4 *m_pixelstart = m_pixels + m_size.x * m_size.y / 4 * m_frame; | |||
| if (m_dirty) | |||
| if (m_dirty[m_frame]) | |||
| { | |||
| m_dirty--; | |||
| m_dirty[m_frame]--; | |||
| for (int j = ((m_frame + 1) % 4) / 2; j < m_size.y; j += 2) | |||
| for (int i = m_frame % 2; i < m_size.x; i += 2) | |||
| @@ -129,6 +148,9 @@ public: | |||
| f64cmplx r0 = z0; | |||
| //f64cmplx r0(0.28693186889504513, 0.014286693904085048); | |||
| //f64cmplx r0(0.001643721971153, 0.822467633298876); | |||
| //f64cmplx r0(-1.207205434596, 0.315432814901); | |||
| //f64cmplx r0(-0.79192956889854, -0.14632423080102); | |||
| //f64cmplx r0(0.3245046418497685, 0.04855101129280834); | |||
| f64cmplx z; | |||
| int iter = maxiter; | |||
| for (z = z0; iter && z.sqlen() < maxlen * maxlen; z = z * z + r0) | |||
| @@ -267,9 +289,9 @@ public: | |||
| glEnable(GL_TEXTURE_2D); | |||
| glBindTexture(GL_TEXTURE_2D, m_texid); | |||
| if (m_dirty) | |||
| if (m_dirty[m_frame]) | |||
| { | |||
| m_dirty--; | |||
| m_dirty[m_frame]--; | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_frame * m_size.y / 2, | |||
| m_size.x / 2, m_size.y / 2, | |||
| @@ -282,6 +304,23 @@ public: | |||
| m_pixels + m_size.x * m_size.y / 4 * m_frame); | |||
| } | |||
| /* If other frames are dirty, upload fake data for now */ | |||
| for (int i = 0; i < 4; i++) | |||
| { | |||
| if (m_dirty[i]) | |||
| { | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i * m_size.y / 2, | |||
| m_size.x / 2, m_size.y / 2, | |||
| #if !defined __CELLOS_LV2__ | |||
| GL_RGBA, GL_UNSIGNED_BYTE, | |||
| #else | |||
| /* The PS3 is big-endian */ | |||
| GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, | |||
| #endif | |||
| m_pixels + m_size.x * m_size.y / 4 * m_frame); | |||
| } | |||
| } | |||
| m_shader->Bind(); | |||
| #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ | |||
| glBindBuffer(GL_ARRAY_BUFFER, m_vbo); | |||
| @@ -320,7 +359,7 @@ public: | |||
| private: | |||
| ivec2 m_size; | |||
| u8vec4 *m_pixels; | |||
| u8vec4 *m_pixels, *m_tmppixels; | |||
| Shader *m_shader; | |||
| GLuint m_texid; | |||
| #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ | |||
| @@ -328,11 +367,13 @@ private: | |||
| GLuint m_tco; | |||
| #endif | |||
| int m_vertexattrib, m_texattrib; | |||
| int m_frame, m_dirty; | |||
| int m_frame, m_dirty[4]; | |||
| bool m_ready; | |||
| f64cmplx m_center; | |||
| double m_radius, m_screenradius; | |||
| f64cmplx m_deltashift[4]; | |||
| double m_deltascale[4]; | |||
| /* Debug information */ | |||
| Text *m_centertext, *m_mousetext, *m_zoomtext; | |||