/** * crank_make_mesh_sphere_uv_p3: * @cogl_context: A CoglContext. * @uc: Number of vertices in u-direction. * @vc: Number of vertices in v-direction. This excludes two vertices at bottom * and top. * * Constructs a #CoglPrimivive for a sphere. * This only contains a position information. * * Returns: (transfer full): A #CoglPrimitive for a sphere. */ CoglPrimitive* crank_make_mesh_sphere_uv_p3 (CoglContext *cogl_context, const guint uc, const guint vc) { CoglPrimitive *primitive; CoglIndices *indices; CoglVertexP3 *vdata; TriIndices *idata; guint lvdata; guint lidata; vdata = crank_make_v_p3_sphere_uv (uc, vc, &lvdata); idata = crank_make_indices_sphere_uv (uc, vc, &lidata); indices = cogl_indices_new (cogl_context, COGL_INDICES_TYPE_UNSIGNED_SHORT, idata, lidata * 3); primitive = cogl_primitive_new_p3 (cogl_context, COGL_VERTICES_MODE_TRIANGLES, lvdata, vdata); cogl_primitive_set_indices (primitive, indices, lidata * 3); cogl_object_unref (indices); g_free (vdata); g_free (idata); return primitive; }
static void _cogl_path_build_fill_attribute_buffer (CoglPath *path) { CoglPathTesselator tess; unsigned int path_start = 0; CoglPathData *data = path->data; int i; /* If we've already got a vbo then we don't need to do anything */ if (data->fill_attribute_buffer) return; tess.primitive_type = FALSE; /* Generate a vertex for each point on the path */ tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex)); g_array_set_size (tess.vertices, data->path_nodes->len); for (i = 0; i < data->path_nodes->len; i++) { CoglPathNode *node = &g_array_index (data->path_nodes, CoglPathNode, i); CoglPathTesselatorVertex *vertex = &g_array_index (tess.vertices, CoglPathTesselatorVertex, i); vertex->x = node->x; vertex->y = node->y; /* Add texture coordinates so that a texture would be drawn to fit the bounding box of the path and then cropped by the path */ if (data->path_nodes_min.x == data->path_nodes_max.x) vertex->s = 0.0f; else vertex->s = ((node->x - data->path_nodes_min.x) / (data->path_nodes_max.x - data->path_nodes_min.x)); if (data->path_nodes_min.y == data->path_nodes_max.y) vertex->t = 0.0f; else vertex->t = ((node->y - data->path_nodes_min.y) / (data->path_nodes_max.y - data->path_nodes_min.y)); } tess.indices_type = _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len); _cogl_path_tesselator_allocate_indices_array (&tess); tess.glu_tess = gluNewTess (); if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD) gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); else gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); /* All vertices are on the xy-plane */ gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0); gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA, _cogl_path_tesselator_begin); gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA, _cogl_path_tesselator_vertex); gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA, _cogl_path_tesselator_end); gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA, _cogl_path_tesselator_combine); gluTessBeginPolygon (tess.glu_tess, &tess); while (path_start < data->path_nodes->len) { CoglPathNode *node = &g_array_index (data->path_nodes, CoglPathNode, path_start); gluTessBeginContour (tess.glu_tess); for (i = 0; i < node->path_size; i++) { double vertex[3] = { node[i].x, node[i].y, 0.0 }; gluTessVertex (tess.glu_tess, vertex, GINT_TO_POINTER (i + path_start)); } gluTessEndContour (tess.glu_tess); path_start += node->path_size; } gluTessEndPolygon (tess.glu_tess); gluDeleteTess (tess.glu_tess); data->fill_attribute_buffer = cogl_attribute_buffer_new (data->context, sizeof (CoglPathTesselatorVertex) * tess.vertices->len, tess.vertices->data); g_array_free (tess.vertices, TRUE); data->fill_attributes[0] = cogl_attribute_new (data->fill_attribute_buffer, "cogl_position_in", sizeof (CoglPathTesselatorVertex), G_STRUCT_OFFSET (CoglPathTesselatorVertex, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); data->fill_attributes[1] = cogl_attribute_new (data->fill_attribute_buffer, "cogl_tex_coord0_in", sizeof (CoglPathTesselatorVertex), G_STRUCT_OFFSET (CoglPathTesselatorVertex, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); data->fill_vbo_indices = cogl_indices_new (data->context, tess.indices_type, tess.indices->data, tess.indices->len); data->fill_vbo_n_indices = tess.indices->len; g_array_free (tess.indices, TRUE); }
static void clutter_deform_effect_init_arrays (ClutterDeformEffect *self) { ClutterDeformEffectPrivate *priv = self->priv; gint x, y, direction, n_indices; CoglAttribute *attributes[3]; guint16 *static_indices; CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglIndices *indices; guint16 *idx; int i; clutter_deform_effect_free_arrays (self); n_indices = ((2 + 2 * priv->x_tiles) * priv->y_tiles + (priv->y_tiles - 1)); static_indices = g_new (guint16, n_indices); #define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) /* compute all the triangles from the various tiles */ direction = 1; idx = static_indices; idx[0] = MESH_INDEX (0, 0); idx[1] = MESH_INDEX (0, 1); idx += 2; for (y = 0; y < priv->y_tiles; y++) { for (x = 0; x < priv->x_tiles; x++) { if (direction) { idx[0] = MESH_INDEX (x + 1, y); idx[1] = MESH_INDEX (x + 1, y + 1); } else { idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); } idx += 2; } if (y == (priv->y_tiles - 1)) break; if (direction) { idx[0] = MESH_INDEX (priv->x_tiles, y + 1); idx[1] = MESH_INDEX (priv->x_tiles, y + 1); idx[2] = MESH_INDEX (priv->x_tiles, y + 2); } else { idx[0] = MESH_INDEX (0, y + 1); idx[1] = MESH_INDEX (0, y + 1); idx[2] = MESH_INDEX (0, y + 2); } idx += 3; direction = !direction; } #undef MESH_INDEX indices = cogl_indices_new (ctx, COGL_INDICES_TYPE_UNSIGNED_SHORT, static_indices, n_indices); g_free (static_indices); priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1); priv->buffer = cogl_attribute_buffer_new (ctx, sizeof (CoglVertexP3T2C4) * priv->n_vertices, NULL); /* The application is expected to continuously modify the vertices so we should give a hint to Cogl about that */ cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer), COGL_BUFFER_UPDATE_HINT_DYNAMIC); attributes[0] = cogl_attribute_new (priv->buffer, "cogl_position_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, x), 3, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (priv->buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[2] = cogl_attribute_new (priv->buffer, "cogl_color_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP, priv->n_vertices, attributes, 3 /* n_attributes */); cogl_primitive_set_indices (priv->primitive, indices, n_indices); if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES)) { priv->lines_primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, priv->n_vertices, attributes, 2 /* n_attributes */); cogl_primitive_set_indices (priv->lines_primitive, indices, n_indices); } cogl_object_unref (indices); for (i = 0; i < 3; i++) cogl_object_unref (attributes[i]); priv->is_dirty = TRUE; }
CoglPrimitive * rut_camera_create_frustum_primitive (RutCamera *camera) { RutVertex4 vertices[8] = { /* near plane in projection space */ {-1, -1, -1, 1, }, { 1, -1, -1, 1, }, { 1, 1, -1, 1, }, {-1, 1, -1, 1, }, /* far plane in projection space */ {-1, -1, 1, 1, }, { 1, -1, 1, 1, }, { 1, 1, 1, 1, }, {-1, 1, 1, 1, } }; const CoglMatrix *projection_inv; CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[1]; CoglPrimitive *primitive; CoglIndices *indices; unsigned char indices_data[24] = { 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7 }; int i; projection_inv = rut_camera_get_inverse_projection (camera); for (i = 0; i < 8; i++) { cogl_matrix_transform_point (projection_inv, &vertices[i].x, &vertices[i].y, &vertices[i].z, &vertices[i].w); vertices[i].x /= vertices[i].w; vertices[i].y /= vertices[i].w; vertices[i].z /= vertices[i].w; vertices[i].w /= 1.0f; } attribute_buffer = cogl_attribute_buffer_new (rut_cogl_context, 8 * sizeof (RutVertex4), vertices); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (RutVertex4), offsetof (RutVertex4, x), 3, COGL_ATTRIBUTE_TYPE_FLOAT); indices = cogl_indices_new (rut_cogl_context, COGL_INDICES_TYPE_UNSIGNED_BYTE, indices_data, G_N_ELEMENTS (indices_data)); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINES, 8, attributes, 1); cogl_primitive_set_indices (primitive, indices, G_N_ELEMENTS(indices_data)); cogl_object_unref (attribute_buffer); cogl_object_unref (attributes[0]); cogl_object_unref (indices); return primitive; }
CoglIndices * cogl_get_rectangle_indices (CoglContext *ctx, int n_rectangles) { int n_indices = n_rectangles * 6; /* Check if the largest index required will fit in a byte array... */ if (n_indices <= 256 / 4 * 6) { /* Generate the byte array if we haven't already */ if (ctx->rectangle_byte_indices == NULL) { uint8_t *byte_array = g_malloc (256 / 4 * 6 * sizeof (uint8_t)); uint8_t *p = byte_array; int i, vert_num = 0; for (i = 0; i < 256 / 4; i++) { *(p++) = vert_num + 0; *(p++) = vert_num + 1; *(p++) = vert_num + 2; *(p++) = vert_num + 0; *(p++) = vert_num + 2; *(p++) = vert_num + 3; vert_num += 4; } ctx->rectangle_byte_indices = cogl_indices_new (ctx, COGL_INDICES_TYPE_UNSIGNED_BYTE, byte_array, 256 / 4 * 6); g_free (byte_array); } return ctx->rectangle_byte_indices; } else { if (ctx->rectangle_short_indices_len < n_indices) { uint16_t *short_array; uint16_t *p; int i, vert_num = 0; if (ctx->rectangle_short_indices != NULL) cogl_object_unref (ctx->rectangle_short_indices); /* Pick a power of two >= MAX (512, n_indices) */ if (ctx->rectangle_short_indices_len == 0) ctx->rectangle_short_indices_len = 512; while (ctx->rectangle_short_indices_len < n_indices) ctx->rectangle_short_indices_len *= 2; /* Over-allocate to generate a whole number of quads */ p = short_array = g_malloc ((ctx->rectangle_short_indices_len + 5) / 6 * 6 * sizeof (uint16_t)); /* Fill in the complete quads */ for (i = 0; i < ctx->rectangle_short_indices_len; i += 6) { *(p++) = vert_num + 0; *(p++) = vert_num + 1; *(p++) = vert_num + 2; *(p++) = vert_num + 0; *(p++) = vert_num + 2; *(p++) = vert_num + 3; vert_num += 4; } ctx->rectangle_short_indices = cogl_indices_new (ctx, COGL_INDICES_TYPE_UNSIGNED_SHORT, short_array, ctx->rectangle_short_indices_len); g_free (short_array); } return ctx->rectangle_short_indices; } }
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGtk3Cogl_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); cogl_framebuffer_orthographic(g_Framebuffer, 0, 0, io.DisplaySize.x, io.DisplaySize.y, -1, 1); CoglContext *context = cogl_framebuffer_get_context(g_Framebuffer); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; int idx_buffer_offset = 0; CoglAttributeBuffer *vertices = cogl_attribute_buffer_new(context, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), cmd_list->VtxBuffer.Data); #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) CoglAttribute *attrs[3] = { cogl_attribute_new(vertices, "cogl_position_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, pos), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_tex_coord0_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, uv), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_color_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, col), 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE) }; #undef OFFSETOF CoglPrimitive *primitive = cogl_primitive_new_with_attributes(COGL_VERTICES_MODE_TRIANGLES, cmd_list->VtxBuffer.Size, attrs, 3); CoglIndices *indices = cogl_indices_new(context, sizeof(ImDrawIdx) == 2 ? COGL_INDICES_TYPE_UNSIGNED_SHORT : COGL_INDICES_TYPE_UNSIGNED_INT, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; cogl_indices_set_offset(indices, sizeof(ImDrawIdx) * idx_buffer_offset); cogl_primitive_set_indices(primitive, indices, pcmd->ElemCount); if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { bool has_texture = pcmd->TextureId != NULL; CoglPipeline *pipeline = has_texture ? (cogl_is_pipeline(pcmd->TextureId) ? (CoglPipeline *) pcmd->TextureId : g_ImagePipeline) : g_ColorPipeline; if (has_texture && pipeline == g_ImagePipeline) { cogl_pipeline_set_layer_texture(g_ImagePipeline, 0, COGL_TEXTURE(pcmd->TextureId)); } cogl_framebuffer_push_scissor_clip(g_Framebuffer, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); cogl_primitive_draw(primitive, g_Framebuffer, pipeline); cogl_framebuffer_pop_clip(g_Framebuffer); } idx_buffer_offset += pcmd->ElemCount; } for (int i = 0; i < 3; i++) cogl_object_unref(attrs[i]); cogl_object_unref(primitive); cogl_object_unref(vertices); cogl_object_unref(indices); } }
static gboolean mash_ply_loader_load (MashDataLoader *data_loader, MashDataFlags flags, const gchar *filename, GError **error) { CoglContext *context; CoglIndices *indices; MashPlyLoader *self = MASH_PLY_LOADER (data_loader); MashPlyLoaderPrivate *priv; MashPlyLoaderData data; gchar *display_name; gboolean ret; priv = self->priv; context = es_get_cogl_context (); data.error = NULL; data.n_vertex_bytes = 0; data.available_props = 0; data.got_props = 0; data.vertices = g_byte_array_new (); data.faces = NULL; data.min_vertex.x = G_MAXFLOAT; data.min_vertex.y = G_MAXFLOAT; data.min_vertex.z = G_MAXFLOAT; data.max_vertex.x = -G_MAXFLOAT; data.max_vertex.y = -G_MAXFLOAT; data.max_vertex.z = -G_MAXFLOAT; data.flags = flags; display_name = g_filename_display_name (filename); if ((data.ply = ply_open (filename, mash_ply_loader_error_cb, &data)) == NULL) mash_ply_loader_check_unknown_error (&data); else { if (!ply_read_header (data.ply)) mash_ply_loader_check_unknown_error (&data); else { int i; for (i = 0; i < G_N_ELEMENTS (mash_ply_loader_properties); i++) if (ply_set_read_cb (data.ply, "vertex", mash_ply_loader_properties[i].name, mash_ply_loader_vertex_read_cb, &data, i)) { data.prop_map[i] = data.n_vertex_bytes; data.n_vertex_bytes += mash_ply_loader_properties[i].size; data.available_props |= 1 << i; } /* Align the size of a vertex to 32 bits */ data.n_vertex_bytes = (data.n_vertex_bytes + 3) & ~(guint) 3; if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) != MASH_PLY_LOADER_VERTEX_PROPS) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing the vertex properties", display_name); else if (!ply_set_read_cb (data.ply, "face", "vertex_indices", mash_ply_loader_face_read_cb, &data, i)) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing face property " "'vertex_indices'", display_name); else if (mash_ply_loader_get_indices_type (&data, &data.error) && !ply_read (data.ply)) mash_ply_loader_check_unknown_error (&data); } ply_close (data.ply); } if (data.error) { g_propagate_error (error, data.error); ret = FALSE; } else if (data.faces->len < 3) { g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_INVALID, "No faces found in %s", display_name); ret = FALSE; } else { CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[4]; int n_attributes = 0, i; /* Get rid of the old primitive (if any) */ mash_ply_loader_free_primitive (self); /* Create a new attribute buffer for the vertices */ attribute_buffer = cogl_attribute_buffer_new (context, data.vertices->len, data.vertices->data); /* And describe the attributes */ if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) == MASH_PLY_LOADER_VERTEX_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_position_in", data.n_vertex_bytes, data.prop_map[0], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_NORMAL_PROPS) == MASH_PLY_LOADER_NORMAL_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_normal_in", data.n_vertex_bytes, data.prop_map[3], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_TEX_COORD_PROPS) == MASH_PLY_LOADER_TEX_COORD_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord0_in", data.n_vertex_bytes, data.prop_map[6], 2, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_COLOR_PROPS) == MASH_PLY_LOADER_COLOR_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_color_in", data.n_vertex_bytes, data.prop_map[8], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, data.vertices->len, attributes, n_attributes); for (i = 0; i < n_attributes; i++) cogl_object_unref (attributes[i]); indices = cogl_indices_new (context, data.indices_type, data.faces->data, data.faces->len); cogl_primitive_set_indices (priv->primitive, indices, data.faces->len); cogl_object_unref (indices); priv->min_vertex = data.min_vertex; priv->max_vertex = data.max_vertex; ret = TRUE; } g_free (display_name); g_byte_array_free (data.vertices, TRUE); if (data.faces) g_array_free (data.faces, TRUE); return ret; }