Browse Source

tutorial: navigate in the fractal using the mouse.

legacy
Sam Hocevar sam 13 years ago
parent
commit
849461fb6f
1 changed files with 117 additions and 67 deletions
  1. +117
    -67
      test/tutorial/tut03.cpp

+ 117
- 67
test/tutorial/tut03.cpp View File

@@ -38,78 +38,117 @@ public:
m_size = size; m_size = size;
m_pixels = new u8vec4[size.x * size.y]; m_pixels = new u8vec4[size.x * size.y];
m_frame = -1; m_frame = -1;
m_center = 0;
//m_target = f64cmplx(0.001643721971153, 0.822467633298876);
m_target = f64cmplx(-1.207205434596, 0.315432814901);
//m_target = f64cmplx(-0.79192956889854, -0.14632423080102);
//m_target = f64cmplx(0.3245046418497685, 0.04855101129280834);
//m_target = f64cmplx(0.28693186889504513, 0.014286693904085048);
m_angle = 0.0;
m_radius = 8.0;
m_dirty = 8;
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; m_ready = false;

m_centertext = new Text(NULL, "gfx/font/ascii.png");
m_centertext->SetPos(ivec3(5, m_size.y - 15, 1));
Ticker::Ref(m_centertext);

m_mousetext = new Text(NULL, "gfx/font/ascii.png");
m_mousetext->SetPos(ivec3(5, m_size.y - 29, 1));
Ticker::Ref(m_mousetext);

position = ivec3(0, 0, 0);
bbox[0] = position;
bbox[1] = ivec3(size, 0);
Input::TrackMouse(this);
} }


~Fractal() ~Fractal()
{ {
Input::UntrackMouse(this);
Ticker::Unref(m_centertext);
Ticker::Unref(m_mousetext);
delete m_pixels; delete m_pixels;
} }


inline f64cmplx ScreenToWorldOffset(ivec2 pixel)
{
f64cmplx tmp = f64cmplx(pixel.x - m_size.x / 2,
m_size.y / 2 - pixel.y);
return tmp * (m_radius / m_screenradius);
}

virtual void TickGame(float deltams) virtual void TickGame(float deltams)
{ {
WorldEntity::TickGame(deltams); WorldEntity::TickGame(deltams);


m_frame = (m_frame + 1) % 4; m_frame = (m_frame + 1) % 4;


double zoom = pow(2.0, -deltams * 0.0005);
m_radius *= zoom;
m_center = (m_center - m_target) * zoom * zoom + m_target;
f64cmplx worldmouse = m_center + ScreenToWorldOffset(mousepos);


double step = m_radius / (m_size.x > m_size.y ? m_size.x : m_size.y);
// m_angle -= deltams * 0.00015;
f64cmplx transform = step * f64cmplx(cos(m_angle), sin(m_angle));
ivec3 buttons = Input::GetMouseButtons();
if ((buttons[0] || buttons[2]) && mousepos.x != -1)
{
double zoom = pow(2.0, (buttons[0] ? -deltams : deltams) * 0.0015);
if (m_radius * zoom > 1.5)
zoom = 1.0;
m_radius *= zoom;
m_center = (m_center - worldmouse) * zoom + worldmouse;
worldmouse = m_center + ScreenToWorldOffset(mousepos);
m_dirty = 8;
}

char buf[128];
sprintf(buf, "center: %+13.11f%+13.11fi", m_center.x, m_center.y);
m_centertext->SetText(buf);
sprintf(buf, " mouse: %+13.11f%+13.11fi", worldmouse.x, worldmouse.y);
m_mousetext->SetText(buf);


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;


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)
if (m_dirty)
{ {
double const maxlen = 32;
int const maxiter = 170;

f64cmplx delta(i - m_size.x / 2, j - m_size.y / 2);

f64cmplx z0 = m_center + transform * delta;
f64cmplx r0 = z0;
//f64cmplx r0(0.28693186889504513, 0.014286693904085048);
//f64cmplx r0(0.001643721971153, 0.822467633298876);
f64cmplx z;
int iter = maxiter;
for (z = z0; iter && z.sqlen() < maxlen * maxlen; z = z * z + r0)
--iter;

double f = iter;
double n = z.sqlen();

double k = log(n) * 0.5f / log(maxlen);
/* Approximate log2(k) in [1,2]. */
f += (- 0.344847817623168308695977510213252644185 * k
+ 2.024664188044341212602376988171727038739) * k
- 1.674876738008591047163498125918330313237;

if (iter)
{
double r = 0.5 * sin(f * 0.27 - 2.0) + 0.5;
double g = 0.5 * sin(f * 0.13 + 1.0) + 0.5;
double b = 0.5 * sin(f * 0.21) + 0.5;

uint8_t red = r * 255.0f;
uint8_t green = g * 255.0f;
uint8_t blue = b * 255.0f;
*m_pixelstart++ = u8vec4(red, green, blue, 0);
}
else
m_dirty--;

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)
{ {
*m_pixelstart++ = u8vec4(0, 0, 0, 0);
double const maxlen = 32;
int const maxiter = 170;

f64cmplx z0 = m_center + ScreenToWorldOffset(ivec2(i, j));
f64cmplx r0 = z0;
//f64cmplx r0(0.28693186889504513, 0.014286693904085048);
//f64cmplx r0(0.001643721971153, 0.822467633298876);
f64cmplx z;
int iter = maxiter;
for (z = z0; iter && z.sqlen() < maxlen * maxlen; z = z * z + r0)
--iter;

double f = iter;
double n = z.sqlen();

double k = log(n) * 0.5f / log(maxlen);
/* Approximate log2(k) in [1,2]. */
f += (- 0.344847817623168308695977510213252644185 * k
+ 2.024664188044341212602376988171727038739) * k
- 1.674876738008591047163498125918330313237;

if (iter)
{
double r = 0.5 * sin(f * 0.27 - 1.5) + 0.5;
double g = 0.5 * sin(f * 0.13 + 1.3) + 0.5;
double b = 0.5 * sin(f * 0.21 + 0.4) + 0.5;

uint8_t red = r * 255.0f;
uint8_t green = g * 255.0f;
uint8_t blue = b * 255.0f;
*m_pixelstart++ = u8vec4(red, green, blue, 0);
}
else
{
*m_pixelstart++ = u8vec4(0, 0, 0, 0);
}
} }
} }
} }
@@ -130,12 +169,12 @@ public:


static float const texcoords[] = static float const texcoords[] =
{ {
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f,
}; };


if (!m_ready) if (!m_ready)
@@ -166,9 +205,11 @@ public:
/* gl_FragCoord is centered inside the pixel, so we remove /* gl_FragCoord is centered inside the pixel, so we remove
* 0.5 from gl_FragCoord.x. Also, (0,0) is at the bottom * 0.5 from gl_FragCoord.x. Also, (0,0) is at the bottom
* left whereas our images have (0,0) at the top left, so we * left whereas our images have (0,0) at the top left, so we
* _add_ 0.5 to gl_FragCoord.y. */
* _add_ 0.5 to gl_FragCoord.y. (XXX: this is no longer true
* but will be again when mouse coordinates are back to
* being top-left again). */
" float i = mod(gl_FragCoord.x - 0.5, 2.0);" " float i = mod(gl_FragCoord.x - 0.5, 2.0);"
" float j = mod(gl_FragCoord.y + 0.5 + i, 2.0);"
" float j = mod(gl_FragCoord.y - 0.5 + i, 2.0);"
" coord.y += i + j * 2;" " coord.y += i + j * 2;"
" coord.y *= 0.25;" " coord.y *= 0.25;"
" vec4 p = texture2D(in_Texture, coord);" " vec4 p = texture2D(in_Texture, coord);"
@@ -216,15 +257,21 @@ public:


glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_texid); glBindTexture(GL_TEXTURE_2D, m_texid);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, m_frame * m_size.y / 2, m_size.x / 2, m_size.y / 2,

if (m_dirty)
{
m_dirty--;

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_frame * m_size.y / 2,
m_size.x / 2, m_size.y / 2,
#if !defined __CELLOS_LV2__ #if !defined __CELLOS_LV2__
GL_RGBA, GL_UNSIGNED_BYTE,
GL_RGBA, GL_UNSIGNED_BYTE,
#else #else
/* The PS3 is big-endian */
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
/* The PS3 is big-endian */
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
#endif #endif
m_pixels + m_size.x * m_size.y / 4 * m_frame);
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__
@@ -272,11 +319,14 @@ private:
GLuint m_tco; GLuint m_tco;
#endif #endif
int m_vertexattrib, m_texattrib; int m_vertexattrib, m_texattrib;
int m_frame;
int m_frame, m_dirty;
bool m_ready; bool m_ready;


f64cmplx m_center, m_target;
double m_radius, m_angle;
f64cmplx m_center;
double m_radius, m_screenradius;

/* Debug information */
Text *m_centertext, *m_mousetext;
}; };


int main() int main()


Loading…
Cancel
Save