diff options
author | Robert Bragg <robert@linux.intel.com> | 2011-05-11 16:37:09 +0100 |
---|---|---|
committer | Robert Bragg <robert@linux.intel.com> | 2011-06-27 21:13:51 +0100 |
commit | 98709062fd6fbf03c6a34cbbadcd97a5f9961c96 (patch) | |
tree | 8ef73c3841bcfada7284f585dea8e2b860510536 | |
parent | 8b3f73f1b056e32f4cba894ea733d4eee945fd98 (diff) | |
download | cogl-98709062fd6fbf03c6a34cbbadcd97a5f9961c96.tar.gz |
Adds another example that draws a 3D crate
Based on the Cogl example we had on wiki.clutter-project.org this shows
how to use the primitive API to draw a simple spinning crate.
-rw-r--r-- | examples/Makefile.am | 9 | ||||
-rw-r--r-- | examples/crate.c | 276 | ||||
-rw-r--r-- | examples/crate.jpg | bin | 0 -> 171588 bytes |
3 files changed, 284 insertions, 1 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am index ea69bc83..67128a98 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -8,7 +8,8 @@ INCLUDES = \ AM_CFLAGS = \ $(COGL_DEP_CFLAGS) \ $(COGL_EXTRA_CFLAGS) \ - -DCOGL_ENABLE_EXPERIMENTAL_2_0_API + -DCOGL_ENABLE_EXPERIMENTAL_2_0_API \ + -DCOGL_EXAMPLES_DATA=\""$(abs_top_srcdir)/examples/"\" AM_CPPFLAGS = \ -DG_DISABLE_SINGLE_INCLUDES \ @@ -24,6 +25,12 @@ noinst_PROGRAMS = hello hello_SOURCES = hello.c hello_LDADD = $(common_ldadd) +if BUILD_COGL_PANGO +noinst_PROGRAMS += crate +crate_SOURCES = crate.c +crate_LDADD = $(common_ldadd) $(top_builddir)/cogl-pango/libcogl-pango.la +endif + if X11_TESTS noinst_PROGRAMS += x11-foreign x11_foreign_SOURCES = x11-foreign.c diff --git a/examples/crate.c b/examples/crate.c new file mode 100644 index 00000000..46ea7d96 --- /dev/null +++ b/examples/crate.c @@ -0,0 +1,276 @@ +#include <cogl/cogl.h> +#include <cogl-pango/cogl-pango.h> + +/* The state for this example... */ +typedef struct _Data +{ + int framebuffer_width; + int framebuffer_height; + + CoglMatrix view; + + CoglPrimitive *prim; + CoglHandle texture; + CoglPipeline *crate_pipeline; + + /* The cube continually rotates around each axis. */ + float rotate_x; + float rotate_y; + float rotate_z; + + CoglPangoFontMap *pango_font_map; + PangoContext *pango_context; + PangoFontDescription *pango_font_desc; + + PangoLayout *hello_label; + int hello_label_width; + int hello_label_height; + +} Data; + +/* A static identity matrix initialized for convenience. */ +static CoglMatrix identity; +/* static colors initialized for convenience. */ +static CoglColor black; +static CoglColor white; + +/* A cube modelled as a list of triangles. Potentially this could be + * done more efficiently as a triangle strip or using a separate index + * array, but this way is pretty simple, if a little verbose. */ +CoglVertexP3T2 vertices[] = +{ + /* Front face */ + { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 1.0f, 1.0f}, + { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f}, + + { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f}, + + /* Back face */ + { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f}, + { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f}, + + { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 0.0f}, + + /* Top face */ + { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f}, + { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f}, + + { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f}, + + /* Bottom face */ + { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f}, + { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f}, + + { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f}, + { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f}, + { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f}, + + /* Right face */ + { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f}, + { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 1.0f}, + + { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 1.0f}, + { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f}, + + /* Left face */ + { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 0.0f}, + { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f}, + { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 1.0f}, + + { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 0.0f}, + { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 1.0f}, + { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f} +}; + +static void +paint (Data *data) +{ + cogl_clear (&black, COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_DEPTH); + + cogl_push_matrix (); + + cogl_translate (data->framebuffer_width / 2, data->framebuffer_height / 2, 0); + + cogl_scale (75, 75, 75); + + /* Rotate the cube separately around each axis. + * + * Note: Cogl matrix manipulation follows the same rules as for + * OpenGL. We use column-major matrices and - if you consider the + * transformations happening to the model - then they are combined + * in reverse order which is why the rotation is done last, since + * we want it to be a rotation around the origin, before it is + * scaled and translated. + */ + cogl_rotate (data->rotate_x++, 0, 0, 1); + cogl_rotate (data->rotate_y++, 0, 1, 0); + cogl_rotate (data->rotate_z++, 1, 0, 0); + + /* Since the box is made of multiple triangles that will overlap + * when drawn and we don't control the order they are drawn in, we + * enable depth testing to make sure that triangles that shouldn't + * be visible get culled by the GPU. + * + * Note: we are planning to deprecate this API and instead depth + * state would be set on a CoglMaterial, something like: + * cogl_pipeline_set_depth_test_enabled (pipeline, TRUE); + * but for now this is how depth testing can be enabled... */ + cogl_set_depth_test_enabled (TRUE); + + /* Whenever you draw something with Cogl using geometry defined by + * one of cogl_rectangle, cogl_polygon, cogl_path or + * cogl_vertex_buffer then you have a current pipeline that defines + * how that geometry should be processed. + * + * Here we are making our crate pipeline current which will sample + * the crate texture when fragment processing. */ + cogl_set_source (data->crate_pipeline); + + /* Give Cogl some geometry to draw. */ + cogl_primitive_draw (data->prim); + + cogl_set_depth_test_enabled (FALSE); + + cogl_pop_matrix (); + + /* And finally render our Pango layouts... */ + + cogl_pango_render_layout (data->hello_label, + (data->framebuffer_width / 2) - + (data->hello_label_width / 2), + (data->framebuffer_height / 2) - + (data->hello_label_height / 2), + &white, 0); +} + +int +main (int argc, char **argv) +{ + CoglContext *ctx; + CoglOnscreen *onscreen; + CoglFramebuffer *fb; + GError *error = NULL; + Data data; + PangoRectangle hello_label_size; + float fovy, aspect, z_near, z_2d, z_far; + + g_type_init (); + + ctx = cogl_context_new (NULL, &error); + if (!ctx) { + fprintf (stderr, "Failed to create context: %s\n", error->message); + return 1; + } + + data.framebuffer_width = 640; + data.framebuffer_height = 480; + onscreen = cogl_onscreen_new (ctx, data.framebuffer_width, data.framebuffer_height); + /* Eventually there will be an implicit allocate on first use so this + * will become optional... */ + fb = COGL_FRAMEBUFFER (onscreen); + if (!cogl_framebuffer_allocate (fb, &error)) { + fprintf (stderr, "Failed to allocate framebuffer: %s\n", error->message); + return 1; + } + + cogl_onscreen_show (onscreen); + + cogl_push_framebuffer (fb); + cogl_set_viewport (0, 0, data.framebuffer_width, data.framebuffer_height); + + fovy = 60; /* y-axis field of view */ + aspect = (float)data.framebuffer_width/(float)data.framebuffer_height; + z_near = 0.1; /* distance to near clipping plane */ + z_2d = 1000; /* position to 2d plane */ + z_far = 2000; /* distance to far clipping plane */ + + cogl_perspective (fovy, aspect, z_near, z_far); + + /* Since the pango renderer emits geometry in pixel/device coordinates + * and the anti aliasing is implemented with the assumption that the + * geometry *really* does end up pixel aligned, we setup a modelview + * matrix so that for geometry in the plane z = 0 we exactly map x + * coordinates in the range [0,stage_width] and y coordinates in the + * range [0,stage_height] to the framebuffer extents with (0,0) being + * the top left. + * + * This is roughly what Clutter does for a ClutterStage, but this + * demonstrates how it is done manually using Cogl. + */ + cogl_matrix_init_identity (&data.view); + cogl_matrix_view_2d_in_perspective (&data.view, fovy, aspect, z_near, z_2d, + data.framebuffer_width, + data.framebuffer_height); + cogl_set_modelview_matrix (&data.view); + cogl_pop_framebuffer (); + + /* Initialize some convenient constants */ + cogl_matrix_init_identity (&identity); + cogl_color_set_from_4ub (&black, 0x00, 0x00, 0x00, 0xff); + cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff); + + data.prim = cogl_primitive_new_p3t2 (COGL_VERTICES_MODE_TRIANGLES, + G_N_ELEMENTS (vertices), + vertices); + + /* Load a jpeg crate texture from a file */ + printf ("crate.jpg (CC by-nc-nd http://bit.ly/9kP45T) ShadowRunner27 http://bit.ly/m1YXLh\n"); + data.texture = cogl_texture_new_from_file (COGL_EXAMPLES_DATA "crate.jpg", + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_ANY, + NULL); + if (!data.texture) + g_error ("Failed to load texture"); + + /* a CoglMaterial conceptually describes all the state for vertex + * processing, fragment processing and blending geometry. When + * drawing the geometry for the crate this pipeline says to sample a + * single texture during fragment processing... */ + data.crate_pipeline = cogl_pipeline_new (); + cogl_pipeline_set_layer_texture (data.crate_pipeline, 0, data.texture); + + /* Setup a Pango font map and context */ + + data.pango_font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new()); + + cogl_pango_font_map_set_use_mipmapping (data.pango_font_map, TRUE); + + data.pango_context = cogl_pango_font_map_create_context (data.pango_font_map); + + data.pango_font_desc = pango_font_description_new (); + pango_font_description_set_family (data.pango_font_desc, "Sans"); + pango_font_description_set_size (data.pango_font_desc, 30 * PANGO_SCALE); + + /* Setup the "Hello Cogl" text */ + + data.hello_label = pango_layout_new (data.pango_context); + pango_layout_set_font_description (data.hello_label, data.pango_font_desc); + pango_layout_set_text (data.hello_label, "Hello Cogl", -1); + + pango_layout_get_extents (data.hello_label, NULL, &hello_label_size); + data.hello_label_width = PANGO_PIXELS (hello_label_size.width); + data.hello_label_height = PANGO_PIXELS (hello_label_size.height); + + cogl_push_framebuffer (fb); + + while (1) + { + paint (&data); + cogl_framebuffer_swap_buffers (fb); + } + + return 0; +} + diff --git a/examples/crate.jpg b/examples/crate.jpg Binary files differnew file mode 100644 index 00000000..2807459f --- /dev/null +++ b/examples/crate.jpg |