| @@ -37,14 +37,15 @@ public: | |||||
| { | { | ||||
| m_size = size; | m_size = size; | ||||
| m_pixels = new u8vec4[size.x * size.y]; | m_pixels = new u8vec4[size.x * size.y]; | ||||
| m_tmppixels = new u8vec4[size.x / 2 * size.y / 2]; | |||||
| m_frame = -1; | 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; | 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_radius = 1.5; | ||||
| m_screenradius = 0.5 * (m_size.x < m_size.y ? m_size.x : m_size.y); | m_screenradius = 0.5 * (m_size.x < m_size.y ? m_size.x : m_size.y); | ||||
| m_ready = false; | m_ready = false; | ||||
| @@ -74,12 +75,13 @@ public: | |||||
| Ticker::Unref(m_mousetext); | Ticker::Unref(m_mousetext); | ||||
| Ticker::Unref(m_zoomtext); | Ticker::Unref(m_zoomtext); | ||||
| delete m_pixels; | delete m_pixels; | ||||
| delete m_tmppixels; | |||||
| } | } | ||||
| inline f64cmplx ScreenToWorldOffset(ivec2 pixel) | 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); | return tmp * (m_radius / m_screenradius); | ||||
| } | } | ||||
| @@ -94,6 +96,8 @@ public: | |||||
| ivec3 buttons = Input::GetMouseButtons(); | ivec3 buttons = Input::GetMouseButtons(); | ||||
| if ((buttons[0] || buttons[2]) && mousepos.x != -1) | 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); | double zoom = pow(2.0, (buttons[0] ? -deltams : deltams) * 0.0015); | ||||
| if (m_radius * zoom > 8.0) | if (m_radius * zoom > 8.0) | ||||
| zoom = 8.0 / m_radius; | zoom = 8.0 / m_radius; | ||||
| @@ -102,9 +106,24 @@ public: | |||||
| m_radius *= zoom; | m_radius *= zoom; | ||||
| m_center = (m_center - worldmouse) * zoom + worldmouse; | m_center = (m_center - worldmouse) * zoom + worldmouse; | ||||
| worldmouse = m_center + ScreenToWorldOffset(mousepos); | 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]; | char buf[128]; | ||||
| sprintf(buf, "center: %+13.11f%+13.11fi", m_center.x, m_center.y); | sprintf(buf, "center: %+13.11f%+13.11fi", m_center.x, m_center.y); | ||||
| m_centertext->SetText(buf); | m_centertext->SetText(buf); | ||||
| @@ -115,9 +134,9 @@ public: | |||||
| u8vec4 *m_pixelstart = m_pixels + m_size.x * m_size.y / 4 * m_frame; | 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 j = ((m_frame + 1) % 4) / 2; j < m_size.y; j += 2) | ||||
| for (int i = m_frame % 2; i < m_size.x; i += 2) | for (int i = m_frame % 2; i < m_size.x; i += 2) | ||||
| @@ -129,6 +148,9 @@ public: | |||||
| f64cmplx r0 = z0; | f64cmplx r0 = z0; | ||||
| //f64cmplx r0(0.28693186889504513, 0.014286693904085048); | //f64cmplx r0(0.28693186889504513, 0.014286693904085048); | ||||
| //f64cmplx r0(0.001643721971153, 0.822467633298876); | //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; | f64cmplx z; | ||||
| int iter = maxiter; | int iter = maxiter; | ||||
| for (z = z0; iter && z.sqlen() < maxlen * maxlen; z = z * z + r0) | for (z = z0; iter && z.sqlen() < maxlen * maxlen; z = z * z + r0) | ||||
| @@ -267,9 +289,9 @@ public: | |||||
| glEnable(GL_TEXTURE_2D); | glEnable(GL_TEXTURE_2D); | ||||
| glBindTexture(GL_TEXTURE_2D, m_texid); | 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, | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_frame * m_size.y / 2, | ||||
| m_size.x / 2, 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); | 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(); | m_shader->Bind(); | ||||
| #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ | #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ | ||||
| glBindBuffer(GL_ARRAY_BUFFER, m_vbo); | glBindBuffer(GL_ARRAY_BUFFER, m_vbo); | ||||
| @@ -320,7 +359,7 @@ public: | |||||
| private: | private: | ||||
| ivec2 m_size; | ivec2 m_size; | ||||
| u8vec4 *m_pixels; | |||||
| u8vec4 *m_pixels, *m_tmppixels; | |||||
| Shader *m_shader; | Shader *m_shader; | ||||
| GLuint m_texid; | GLuint m_texid; | ||||
| #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ | #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ | ||||
| @@ -328,11 +367,13 @@ private: | |||||
| GLuint m_tco; | GLuint m_tco; | ||||
| #endif | #endif | ||||
| int m_vertexattrib, m_texattrib; | int m_vertexattrib, m_texattrib; | ||||
| int m_frame, m_dirty; | |||||
| int m_frame, m_dirty[4]; | |||||
| bool m_ready; | bool m_ready; | ||||
| f64cmplx m_center; | f64cmplx m_center; | ||||
| double m_radius, m_screenradius; | double m_radius, m_screenradius; | ||||
| f64cmplx m_deltashift[4]; | |||||
| double m_deltascale[4]; | |||||
| /* Debug information */ | /* Debug information */ | ||||
| Text *m_centertext, *m_mousetext, *m_zoomtext; | Text *m_centertext, *m_mousetext, *m_zoomtext; | ||||