Skip to content

Instantly share code, notes, and snippets.

@emanueleaina
Created December 18, 2012 19:16
Show Gist options
  • Save emanueleaina/4331002 to your computer and use it in GitHub Desktop.
Save emanueleaina/4331002 to your computer and use it in GitHub Desktop.
Experiment with setting an ortographic projection matrix on the framebuffer from a container Actor.
#define COGL_ENABLE_EXPERIMENTAL_API
#include <stdlib.h>
#include <cogl/cogl.h>
#include <clutter/clutter.h>
/* TrContainerActor *
********************/
typedef struct _TrContainerActor TrContainerActor;
#define TR_TYPE_CONTAINER_ACTOR (tr_container_actor_get_type ())
#define TR_CONTAINER_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TR_TYPE_CONTAINER_ACTOR, TrContainerActor))
#define TR_IS_CONTAINER_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TR_TYPE_CONTAINER_ACTOR))
#define TR_CONTAINER_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TR_TYPE_CONTAINER_ACTOR, TrContainerActorClass))
#define TR_IS_CONTAINER_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TR_TYPE_CONTAINER_ACTOR))
#define TR_CONTAINER_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TR_TYPE_CONTAINER_ACTOR, TrContainerActorClass))
typedef struct _TrContainerActorPrivate TrContainerActorPrivate;
typedef struct _TrContainerActorClass TrContainerActorClass;
struct _TrContainerActor
{
ClutterActor parent_instance;
TrContainerActorPrivate *priv;
};
struct _TrContainerActorClass
{
ClutterActorClass parent_instance;
};
enum _TrProjectionType
{
PROJECTION_PERSPECTIVE,
PROJECTION_ORTHOGRAPHIC
};
typedef enum _TrProjectionType TrProjectionType;
struct _TrContainerActorPrivate
{
TrProjectionType projection_type;
};
G_DEFINE_TYPE (TrContainerActor, tr_container_actor, CLUTTER_TYPE_ACTOR)
static void
tr_container_actor_apply_transform (ClutterActor *actor,
CoglMatrix *transform)
{
CLUTTER_ACTOR_CLASS (tr_container_actor_parent_class)->apply_transform (actor, transform);
}
static void
tr_container_actor_paint (ClutterActor *actor)
{
CoglMatrix saved_projection;
CoglFramebuffer *fb;
fb = cogl_get_draw_framebuffer ();
cogl_framebuffer_get_projection_matrix (fb, &saved_projection);
{
float viewport[4];
cogl_framebuffer_get_viewport4fv (fb, viewport);
g_print ("viewport:%.2fx%.2f+%.2f+%.2f size:%dx%d\n", viewport[2], viewport[3], viewport[0], viewport[1], cogl_framebuffer_get_width (fb), cogl_framebuffer_get_height (fb));
switch (TR_CONTAINER_ACTOR(actor)->priv->projection_type)
{
case PROJECTION_PERSPECTIVE:
cogl_framebuffer_perspective (fb, 90, viewport[2]/ viewport[3], 0.1, 10.0);
CLUTTER_ACTOR_CLASS (tr_container_actor_parent_class)->paint (actor);
break;
case PROJECTION_ORTHOGRAPHIC:
cogl_framebuffer_orthographic (fb, viewport[0], viewport[1], viewport[2], viewport[3], -100.0, 100.0);
cogl_framebuffer_push_matrix (fb);
cogl_framebuffer_identity_matrix (fb);
CLUTTER_ACTOR_CLASS (tr_container_actor_parent_class)->paint (actor);
cogl_framebuffer_pop_matrix (fb);
break;
}
}
cogl_framebuffer_set_projection_matrix (fb, &saved_projection);
}
static void
tr_container_actor_class_init (TrContainerActorClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
g_type_class_add_private (klass, sizeof (TrContainerActorPrivate));
actor_class->apply_transform = tr_container_actor_apply_transform;
actor_class->paint = tr_container_actor_paint;
}
static void
tr_container_actor_init (TrContainerActor *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TR_TYPE_CONTAINER_ACTOR,
TrContainerActorPrivate);
}
ClutterActor *
tr_container_actor_new (void)
{
return g_object_new (TR_TYPE_CONTAINER_ACTOR, NULL);
}
/* TrActor *
***********/
typedef struct _TrActor TrActor;
#define TR_TYPE_ACTOR (tr_actor_get_type ())
#define TR_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TR_TYPE_ACTOR, TrActor))
#define TR_IS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TR_TYPE_ACTOR))
#define TR_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TR_TYPE_ACTOR, TrActorClass))
#define TR_IS_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TR_TYPE_ACTOR))
#define TR_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TR_TYPE_ACTOR, TrActorClass))
typedef struct _TrActorPrivate TrActorPrivate;
typedef struct _TrActorClass TrActorClass;
struct _TrActor
{
ClutterActor parent_instance;
TrActorPrivate *priv;
};
struct _TrActorClass
{
ClutterActorClass parent_instance;
};
struct _TrActorPrivate
{
gint _placeholder; // Prevents the private struct from being 0-sized
};
G_DEFINE_TYPE (TrActor, tr_actor, CLUTTER_TYPE_ACTOR)
static void
tr_actor_apply_transform (ClutterActor *actor,
CoglMatrix *transform)
{
CLUTTER_ACTOR_CLASS (tr_actor_parent_class)->apply_transform (actor, transform);
}
static void
tr_actor_paint (ClutterActor *actor)
{
CLUTTER_ACTOR_CLASS (tr_actor_parent_class)->paint (actor);
}
static void
tr_actor_class_init (TrActorClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
g_type_class_add_private (klass, sizeof (TrActorPrivate));
actor_class->apply_transform = tr_actor_apply_transform;
actor_class->paint = tr_actor_paint;
}
static void
tr_actor_init (TrActor *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TR_TYPE_ACTOR,
TrActorPrivate);
}
ClutterActor *
tr_actor_new (void)
{
return g_object_new (TR_TYPE_ACTOR, NULL);
}
/* main *
********/
static gboolean
on_key_press (ClutterActor *stage G_GNUC_UNUSED,
ClutterEvent *event,
gpointer data)
{
guint key_symbol;
ClutterActor *actor = CLUTTER_ACTOR (data);
key_symbol = clutter_event_get_key_symbol (event);
if (key_symbol == CLUTTER_KEY_space)
{
TrContainerActor *container = TR_CONTAINER_ACTOR (clutter_actor_get_parent (actor));
if (container->priv->projection_type == PROJECTION_PERSPECTIVE)
container->priv->projection_type = PROJECTION_ORTHOGRAPHIC;
else
container->priv->projection_type = PROJECTION_PERSPECTIVE;
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
}
else if (key_symbol == CLUTTER_KEY_Right)
{
float angle = clutter_actor_get_rotation_angle (actor, CLUTTER_Y_AXIS);
angle += 5;
clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, angle);
g_print ("angle:%.2f°\n", angle);
}
else if (key_symbol == CLUTTER_KEY_Left)
{
float angle = clutter_actor_get_rotation_angle (actor, CLUTTER_Y_AXIS);
angle -= 5;
clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, angle);
g_print ("angle:%.2f°\n", angle);
}
return CLUTTER_EVENT_STOP;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *container, *untransformed, *transformed, *info;
ClutterAction *pan;
if (argc < 1)
{
g_error ("Usage: %s", argv[0]);
return EXIT_FAILURE;
}
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
{
g_error ("Failed to initialize clutter\n");
return EXIT_FAILURE;
}
stage = clutter_stage_new ();
clutter_actor_set_name (stage, "stage");
pan = clutter_pan_action_new ();
clutter_actor_add_action (stage, pan);
container = tr_container_actor_new ();
clutter_actor_set_name (container, "container");
clutter_actor_add_child (stage, container);
/* Reference actor */
untransformed = tr_actor_new ();
clutter_actor_set_name (untransformed, "untransformed");
clutter_actor_set_position (untransformed, 20, 40);
clutter_actor_set_size (untransformed, 60, 90);
clutter_actor_set_background_color (untransformed, CLUTTER_COLOR_Blue);
clutter_actor_add_child (container, untransformed);
/* Transformed actor */
transformed = tr_actor_new ();
clutter_actor_set_name (transformed, "transformed");
clutter_actor_set_position (transformed, 20, 40);
clutter_actor_set_size (transformed, 60, 90);
clutter_actor_set_background_color (transformed, CLUTTER_COLOR_Red);
clutter_actor_add_child (container, transformed);
clutter_actor_set_pivot_point (transformed, 0.5, 0.5);
clutter_actor_set_rotation_angle (transformed, CLUTTER_Y_AXIS, 45);
info = clutter_text_new_with_text (NULL, "3d transformation experiments");
clutter_actor_add_child (stage, info);
clutter_actor_set_position (info, 12, 12);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), transformed);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment