diff --git a/libc3/window/sdl2/demo/earth.c b/libc3/window/sdl2/demo/earth.c
index 34ee0af..74857ad 100644
--- a/libc3/window/sdl2/demo/earth.c
+++ b/libc3/window/sdl2/demo/earth.c
@@ -19,7 +19,10 @@
#include "../gl_sphere.h"
#include "earth.h"
-#define EARTH_SEGMENTS 10
+#define EARTH_CAMERA_ROTATION_X_SPEED 0.01
+#define EARTH_CAMERA_ROTATION_Z_SPEED 0.1
+#define EARTH_SEGMENTS_U 20
+#define EARTH_SEGMENTS_V 10
s_sdl2_sprite g_sprite_earth = {0};
@@ -34,7 +37,7 @@ bool earth_load (s_sequence *seq,
camera = gl_camera_new(window->w, window->h);
if (! camera)
return false;
- sphere = gl_sphere_new(EARTH_SEGMENTS);
+ sphere = gl_sphere_new(EARTH_SEGMENTS_U, EARTH_SEGMENTS_V);
if (! sphere)
return false;
if (! tag_map(&seq->tag, 2))
@@ -53,6 +56,7 @@ bool earth_render (s_sequence *seq, s_window_sdl2 *window,
s_gl_camera *camera;
s_map *map;
s_gl_sphere *sphere;
+ f64 sphere_radius;
assert(seq);
assert(window);
(void) context;
@@ -70,13 +74,26 @@ bool earth_render (s_sequence *seq, s_window_sdl2 *window,
camera = map->value[0].data.ptr.p;
sphere = map->value[1].data.ptr.p;
gl_camera_set_aspect_ratio(camera, window->w, window->h);
+ camera->rotation.x += seq->dt * EARTH_CAMERA_ROTATION_X_SPEED *
+ 360.0;
+ camera->rotation.z += seq->dt * EARTH_CAMERA_ROTATION_Z_SPEED *
+ 360.0;
gl_camera_render(camera);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ glPushMatrix();
+ sphere_radius = 5.0;
+ glScalef(sphere_radius, sphere_radius, sphere_radius);
+ glEnable(GL_TEXTURE_2D);
+ sdl2_sprite_bind(&g_sprite_earth, 0);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glDisable(GL_TEXTURE_2D);
- //sdl2_sprite_bind(&g_sprite_earth, 0);
- glPointSize(4.0);
gl_sphere_render(sphere);
+ /*
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ gl_sphere_render_wireframe(sphere);
+ */
+ glPopMatrix();
return true;
}
diff --git a/libc3/window/sdl2/demo/macos/Makefile b/libc3/window/sdl2/demo/macos/Makefile
index 8a10e78..d4d8978 100644
--- a/libc3/window/sdl2/demo/macos/Makefile
+++ b/libc3/window/sdl2/demo/macos/Makefile
@@ -20,6 +20,7 @@ CLEANFILES += ${CLEANFILES_COV}
DISTCLEANFILES = ${CLEANFILES} config.mk
IMG_SOURCES = \
+ ../../../../../img/earth.png \
../../../../../img/flaps.png \
../../../../../img/fly-dead.png \
../../../../../img/fly-noto.png \
diff --git a/libc3/window/sdl2/demo/window_sdl2_demo.c b/libc3/window/sdl2/demo/window_sdl2_demo.c
index 0bfb7a0..f846055 100644
--- a/libc3/window/sdl2/demo/window_sdl2_demo.c
+++ b/libc3/window/sdl2/demo/window_sdl2_demo.c
@@ -155,6 +155,9 @@ bool window_sdl2_demo_load (s_window_sdl2 *window)
window_sdl2_sequence_init(window->sequence + 3, 60.0,
"04. Flies",
flies_load, flies_render);
+ if (! sdl2_sprite_init(&g_sprite_earth, "img/earth.png",
+ 1, 1, 1))
+ return false;
window_sdl2_sequence_init(window->sequence + 4, 60.0,
"05. Earth",
earth_load, earth_render);
diff --git a/libc3/window/sdl2/gl.c b/libc3/window/sdl2/gl.c
index 258af60..a2b53e5 100644
--- a/libc3/window/sdl2/gl.c
+++ b/libc3/window/sdl2/gl.c
@@ -12,7 +12,17 @@
*/
#include "gl.h"
-void gl_vertex_3d (const s_gl_3d *p)
+void gl_normal_3d (const s_gl_3d *normal)
{
- glVertex3dv(&p->x);
+ glNormal3dv(&normal->x);
+}
+
+void gl_tex_coord_2d (const s_gl_2d *tex_coord)
+{
+ glTexCoord2dv(&tex_coord->x);
+}
+
+void gl_vertex_3d (const s_gl_3d *vertex)
+{
+ glVertex3dv(&vertex->x);
}
diff --git a/libc3/window/sdl2/gl.h b/libc3/window/sdl2/gl.h
index 66db000..fe84eb3 100644
--- a/libc3/window/sdl2/gl.h
+++ b/libc3/window/sdl2/gl.h
@@ -15,7 +15,8 @@
#include "types.h"
-void gl_tex_coord_2d (const s_gl_2d *p);
-void gl_vertex_3d (const s_gl_3d *p);
+void gl_normal_3d (const s_gl_3d *normal);
+void gl_tex_coord_2d (const s_gl_2d *tex_coord);
+void gl_vertex_3d (const s_gl_3d *vertex);
#endif /* LIBC3_WINDOW_SDL2_GL_H */
diff --git a/libc3/window/sdl2/gl_camera.c b/libc3/window/sdl2/gl_camera.c
index a63fdea..02dd038 100644
--- a/libc3/window/sdl2/gl_camera.c
+++ b/libc3/window/sdl2/gl_camera.c
@@ -21,13 +21,16 @@ s_gl_camera * gl_camera_init (s_gl_camera *camera, uw w, uw h)
assert(window);
assert(window->w);
assert(window->h);
+ gl_camera_set_aspect_ratio(camera, w, h);
+ camera->clip_z_far = 1000;
+ camera->clip_z_near = 0.1;
+ camera->fov_y = 90.0;
camera->position.x = 0.0;
camera->position.y = 0.0;
camera->position.z = -10.0;
- camera->fov_y = 90.0;
- camera->clip_z_far = 1000;
- camera->clip_z_near = 0.1;
- gl_camera_set_aspect_ratio(camera, w, h);
+ camera->rotation.x = 90.0;
+ camera->rotation.y = 0.0;
+ camera->rotation.z = 0.0;
return camera;
}
@@ -60,8 +63,11 @@ void gl_camera_render (const s_gl_camera *camera)
camera->clip_z_near, camera->clip_z_far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- glTranslated(-camera->position.x, -camera->position.y,
- -camera->position.z);
+ glTranslated(camera->position.x, camera->position.y,
+ camera->position.z);
+ glRotated(camera->rotation.x, 1.0, 0.0, 0.0);
+ glRotated(camera->rotation.y, 0.0, 1.0, 0.0);
+ glRotated(camera->rotation.z, 0.0, 0.0, 1.0);
}
s_gl_camera * gl_camera_set_aspect_ratio (s_gl_camera *camera, uw w,
diff --git a/libc3/window/sdl2/gl_sphere.c b/libc3/window/sdl2/gl_sphere.c
index 7ffdfde..393e6be 100644
--- a/libc3/window/sdl2/gl_sphere.c
+++ b/libc3/window/sdl2/gl_sphere.c
@@ -29,7 +29,8 @@ void gl_sphere_delete (s_gl_sphere *sphere)
free(sphere);
}
-s_gl_sphere * gl_sphere_init (s_gl_sphere *sphere, uw segments)
+s_gl_sphere * gl_sphere_init (s_gl_sphere *sphere, uw segments_u,
+ uw segments_v)
{
f64 angle_i;
f64 angle_j;
@@ -39,23 +40,27 @@ s_gl_sphere * gl_sphere_init (s_gl_sphere *sphere, uw segments)
f64 r;
f64 z;
assert(s);
- if (! segments)
- segments = 10;
- sphere->segments = segments;
- p = calloc(segments * segments, sizeof(s_gl_3d));
+ if (! segments_u)
+ segments_u = 3;
+ if (! segments_v)
+ segments_v = 2;
+ sphere->segments_u = segments_u;
+ sphere->segments_v = segments_v;
+ p = calloc(segments_u * segments_v + 2, sizeof(s_gl_3d));
if (! p) {
- warn("gl_sphere_init(%lu): point array", segments);
+ warn("gl_sphere_init(%lu, %lu): point array", segments_u,
+ segments_v);
return NULL;
}
sphere->vertex = p;
i = 0;
- while (i < segments) {
- angle_i = (f64) i / segments * M_PI * 2.0;
- r = cos(angle_i);
- z = sin(angle_i);
+ while (i < segments_v) {
+ angle_i = (i + 1) * M_PI / (segments_v + 1);
+ r = sin(angle_i);
+ z = cos(angle_i);
j = 0;
- while (j < segments) {
- angle_j = (f64) j / segments * M_PI * 2.0;
+ while (j < segments_u) {
+ angle_j = j * M_PI * 2.0 / segments_u;
p->x = cos(angle_j) * r;
p->y = sin(angle_j) * r;
p->z = z;
@@ -64,10 +69,17 @@ s_gl_sphere * gl_sphere_init (s_gl_sphere *sphere, uw segments)
}
i++;
}
+ p->x = 0.0;
+ p->y = 0.0;
+ p->z = 1.0;
+ p++;
+ p->x = 0.0;
+ p->y = 0.0;
+ p->z = -1.0;
return sphere;
}
-s_gl_sphere * gl_sphere_new (uw segments)
+s_gl_sphere * gl_sphere_new (uw segments_u, uw segments_w)
{
s_gl_sphere *sphere;
sphere = calloc(1, sizeof(s_gl_sphere));
@@ -75,7 +87,7 @@ s_gl_sphere * gl_sphere_new (uw segments)
warn("gl_sphere_new: sphere");
return NULL;
}
- if (! gl_sphere_init(sphere, segments)) {
+ if (! gl_sphere_init(sphere, segments_u, segments_w)) {
free(sphere);
return NULL;
}
@@ -86,21 +98,115 @@ void gl_sphere_render (const s_gl_sphere *sphere)
{
uw i;
uw j;
- s_gl_3d *p;
- uw seg;
+ s_gl_3d *p[3];
+ s_gl_2d tex_coord[3];
+ uw seg_u;
+ uw seg_v;
assert(sphere);
- seg = sphere->segments;
- glBegin(GL_POINTS);
- p = sphere->vertex;
- i = 0;
- while (i < seg) {
+ seg_u = sphere->segments_u;
+ seg_v = sphere->segments_v;
+ // first row
+ glBegin(GL_QUAD_STRIP);
+ tex_coord[0].y = 0.0;
+ tex_coord[1].y = 1.0 / (seg_v + 1);
+ p[0] = sphere->vertex + seg_u * seg_v;
+ j = 0;
+ while (j < seg_u + 1) {
+ p[1] = sphere->vertex + j % seg_u;
+ tex_coord[0].x = tex_coord[1].x = (f64) j / seg_u;
+ gl_tex_coord_2d(tex_coord);
+ gl_vertex_3d(p[0]);
+ gl_tex_coord_2d(tex_coord + 1);
+ gl_vertex_3d(p[1]);
+ j++;
+ }
+ glEnd();
+ // whole
+ i = 1;
+ while (i < seg_v) {
+ glBegin(GL_QUAD_STRIP);
+ tex_coord[0].y = (f64) (i + 1) / (seg_v + 1);
+ tex_coord[1].y = (f64) i / (seg_v + 1);
j = 0;
- while (j < seg) {
- gl_vertex_3d(p);
- p++;
+ while (j < seg_u + 1) {
+ p[0] = sphere->vertex + i * seg_u + j % seg_u;
+ p[1] = sphere->vertex + (i - 1) * seg_u + j % seg_u;
+ tex_coord[0].x = tex_coord[1].x = (f64) j / seg_u;
+ gl_tex_coord_2d(tex_coord);
+ gl_vertex_3d(p[0]);
+ gl_tex_coord_2d(tex_coord + 1);
+ gl_vertex_3d(p[1]);
+ j++;
+ }
+ glEnd();
+ i++;
+ }
+ // last row
+ glBegin(GL_QUAD_STRIP);
+ tex_coord[0].y = 1.0;
+ tex_coord[1].y = (f64) seg_v / (seg_v + 1);
+ p[0] = sphere->vertex + seg_u * seg_v + 1;
+ j = 0;
+ while (j < seg_u + 1) {
+ p[1] = sphere->vertex + (seg_v - 1) * seg_u + j % seg_u;
+ tex_coord[0].x = tex_coord[1].x = (f64) j / seg_u;
+ gl_tex_coord_2d(tex_coord);
+ gl_vertex_3d(p[0]);
+ gl_tex_coord_2d(tex_coord + 1);
+ gl_vertex_3d(p[1]);
+ j++;
+ }
+ glEnd();
+}
+
+void gl_sphere_render_wireframe (const s_gl_sphere *sphere)
+{
+ uw i;
+ uw j;
+ s_gl_3d *p[3];
+ uw seg_u;
+ uw seg_v;
+ assert(sphere);
+ seg_u = sphere->segments_u;
+ seg_v = sphere->segments_v;
+ // first row
+ j = 0;
+ while (j < seg_u + 1) {
+ glBegin(GL_LINE_STRIP);
+ p[0] = sphere->vertex + seg_u * seg_v;
+ p[1] = sphere->vertex + j % seg_u;
+ p[2] = sphere->vertex + (j + 1) % seg_u;
+ gl_vertex_3d(p[0]);
+ gl_vertex_3d(p[1]);
+ gl_vertex_3d(p[2]);
+ glEnd();
+ j++;
+ }
+ // whole
+ i = 1;
+ while (i < seg_v) {
+ j = 0;
+ while (j < seg_u + 1) {
+ glBegin(GL_LINE_STRIP);
+ p[0] = sphere->vertex + (i - 1) * seg_u + j % seg_u;
+ p[1] = sphere->vertex + i * seg_u + j % seg_u;
+ p[2] = sphere->vertex + i * seg_u + (j + 1) % seg_u;
+ gl_vertex_3d(p[0]);
+ gl_vertex_3d(p[1]);
+ gl_vertex_3d(p[2]);
+ glEnd();
j++;
}
i++;
}
+ glBegin(GL_LINES);
+ j = 0;
+ while (j < seg_u + 1) {
+ p[0] = sphere->vertex + seg_u * seg_v + 1;
+ p[1] = sphere->vertex + (seg_v - 1) * seg_u + j % seg_u;
+ gl_vertex_3d(p[0]);
+ gl_vertex_3d(p[1]);
+ j++;
+ }
glEnd();
}
diff --git a/libc3/window/sdl2/gl_sphere.h b/libc3/window/sdl2/gl_sphere.h
index b68eed1..37aa5ce 100644
--- a/libc3/window/sdl2/gl_sphere.h
+++ b/libc3/window/sdl2/gl_sphere.h
@@ -18,13 +18,15 @@
/* Stack-allocation compatible functions, call gl_sphere_clean after
use. */
void gl_sphere_clean (s_gl_sphere *sphere);
-s_gl_sphere * gl_sphere_init (s_gl_sphere *sphere, uw segments);
+s_gl_sphere * gl_sphere_init (s_gl_sphere *sphere, uw segments_u,
+ uw segments_v);
/* Heap-allocation functions, call gl_sphere_delete after use. */
void gl_sphere_delete (s_gl_sphere *sphere);
-s_gl_sphere * gl_sphere_new (uw segments);
+s_gl_sphere * gl_sphere_new (uw segments_u, uw segments_v);
/* Observers. */
void gl_sphere_render (const s_gl_sphere *sphere);
+void gl_sphere_render_wireframe (const s_gl_sphere *sphere);
#endif /* GL_SPHERE_H */
diff --git a/libc3/window/sdl2/sdl2_sprite.c b/libc3/window/sdl2/sdl2_sprite.c
index 76e7aa3..1885877 100644
--- a/libc3/window/sdl2/sdl2_sprite.c
+++ b/libc3/window/sdl2/sdl2_sprite.c
@@ -273,9 +273,10 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, gl_format, sprite->w, sprite->h,
- 0, gl_format, gl_type, data);
- //glGenerateMipmap(GL_TEXTURE_2D);
+ //glTexImage2D(GL_TEXTURE_2D, 0, gl_format, sprite->w, sprite->h,
+ // 0, gl_format, gl_type, data);
+ gluBuild2DMipmaps(GL_TEXTURE_2D, gl_internal_format, sprite->w,
+ sprite->h, gl_format, gl_type, data);
gl_error = glGetError();
if (gl_error != GL_NO_ERROR) {
warnx("sdl2_sprite_init: %s: glTexImage2D: %s\n",
diff --git a/libc3/window/sdl2/types.h b/libc3/window/sdl2/types.h
index 3b39dfb..974fa4e 100644
--- a/libc3/window/sdl2/types.h
+++ b/libc3/window/sdl2/types.h
@@ -73,10 +73,9 @@ typedef bool (*f_window_sdl2_sequence_render) (s_sequence *seq,
void *context);
/* 1 */
-struct gl_cylinder {
- uw segments_u;
- uw segments_v;
- s_gl_3d *vertex;
+struct gl_2d {
+ f64 x;
+ f64 y;
};
struct gl_3d {
@@ -85,8 +84,15 @@ struct gl_3d {
f64 z;
};
+struct gl_cylinder {
+ uw segments_u;
+ uw segments_v;
+ s_gl_3d *vertex;
+};
+
struct gl_sphere {
- uw segments;
+ uw segments_u;
+ uw segments_v;
s_gl_3d *vertex;
};