/*! \param r Rectangle to remove overlaps with. */ void Atlas::Prune( const rect_t& r ) { for (auto it = unused.begin(); it!=unused.end(); it++ ) { if (rect_overlap(r, *it)) { it = unused.erase(it); it--; } } for (auto i = unused.begin(); i!=unused.end(); ++i ) for (auto j = i; j != unused.end(); ++j) { if ( i == j ) continue; if (rect_iscontained(*i, *j)) { i = unused.erase(i); i--; break; } if (rect_iscontained(*j, *i)) { j = unused.erase(j); j--; } } }
static struct PendNode * find_pending(struct PendNode *cptr) { struct PendNode *ptr; for (ptr = pendups.First; ptr != NULL; ptr = ptr->nextnode) { if (rect_overlap(ptr, cptr) == 0) continue; return (ptr); } return (NULL); }
/* Splits the atlas by removing the rectangle given from free space. \param r a rectangle to use as a splitting surface. */ void Atlas::Split( const rect_t& r ) { rect_t temp; for( auto r2 : unused ) { if (rect_overlap( r, r2 )) { if (r.x < r2.x + r2.w && r.x + r.w > r2.x) { if (r.y > r2.y && r.y < r2.y + r2.h) { temp = r2; temp.h = r.y - r2.y; if (temp.h > minsize) unused.push_front(temp); } if (r.y + r.h < r2.y + r2.h) { temp = r2; temp.y = r.y + r.h; temp.h = r2.y + r2.h - (r.y + r.h); if (temp.h > minsize) unused.push_front(temp); } } if (r.y < r2.y + r2.h && r.y + r.h > r2.y) { if (r.x > r2.x && r.x < r2.x + r2.w) { temp = r2; temp.w = r.x - r2.x; if (temp.w > minsize) unused.push_front(temp); } if (r.x + r.w < r2.x + r2.w) { temp = r2; temp.x = r.x + r.w; temp.w = r2.x + r2.w - (r.x + r.w); if (temp.w > minsize) unused.push_front(temp); } } } } }
void do_physics_to_it(body_t *body, rect_list_t *terr_rects, rect_list_t *plat_rects){ rect_t *start = rect_create(); rect_match_to(start, body->rect); rect_node_t *iter; body->flags &= ~BLOCKED_MASK; body->rect->x += body->vx; iter = terr_rects->head; while(iter != NULL){ if(rect_overlap(body->rect, iter->data)){ if(body->vx > 0 && rect_get_r_edge(body->rect) >= rect_get_l_edge(iter->data)){ body->vx = 0; rect_set_r_edge(body->rect, rect_get_l_edge(iter->data)); body->flags |= BLOCKED_R; }else if(body->vx < 0 && rect_get_l_edge(body->rect) <= rect_get_r_edge(iter->data)){ body->vx = 0; rect_set_l_edge(body->rect, rect_get_r_edge(iter->data)); body->flags |= BLOCKED_L; } break; } iter = iter->next; } body->rect->y += body->vy; iter = terr_rects->head; while(iter != NULL){ if(rect_overlap(body->rect, iter->data)){ if(body->vy > 0 && rect_get_b_edge(body->rect) >= rect_get_t_edge(iter->data)){ body->vy = 0; rect_set_b_edge(body->rect, rect_get_t_edge(iter->data)); body->flags |= BLOCKED_D; }else if(body->vy < 0 && rect_get_t_edge(body->rect) <= rect_get_b_edge(iter->data)){ body->vy = 0; rect_set_t_edge(body->rect, rect_get_b_edge(iter->data)); body->flags |= BLOCKED_U; } break; } iter = iter->next; } if(body->vy > 0 && !(body->flags & PLAT_DROP)){ iter = plat_rects->head; while(iter != NULL){ if(rect_overlap(body->rect, iter->data)){ if(rect_get_b_edge(start) <= rect_get_t_edge(iter->data)){ body->vy = 0; rect_set_b_edge(body->rect, rect_get_t_edge(iter->data)); body->flags |= BLOCKED_D; break; } } iter = iter->next; } } rect_delete(start); }
// chain function - this function does the actual processing static GstFlowReturn gst_bgfg_acmmm2003_chain(GstPad *pad, GstBuffer *buf) { GstBgFgACMMM2003 *filter; // sanity checks g_return_val_if_fail(pad != NULL, GST_FLOW_ERROR); g_return_val_if_fail(buf != NULL, GST_FLOW_ERROR); filter = GST_BGFG_ACMMM2003(GST_OBJECT_PARENT(pad)); filter->image->imageData = (gchar*) GST_BUFFER_DATA(buf); // the bg model must be initialized with a valid image; thus we delay its // creation until the chain function if (filter->model == NULL) { filter->model = cvCreateFGDStatModel(filter->image, NULL); ((CvFGDStatModel*)filter->model)->params.minArea = filter->min_area; ((CvFGDStatModel*)filter->model)->params.erode_iterations = filter->n_erode_iterations; ((CvFGDStatModel*)filter->model)->params.dilate_iterations = filter->n_dilate_iterations; return gst_pad_push(filter->srcpad, buf); } cvUpdateBGStatModel(filter->image, filter->model, -1); // send mask event, if requested if (filter->send_mask_events) { GstStructure *structure; GstEvent *event; GArray *data_array; IplImage *mask; // prepare and send custom event with the mask surface mask = filter->model->foreground; data_array = g_array_sized_new(FALSE, FALSE, sizeof(mask->imageData[0]), mask->imageSize); g_array_append_vals(data_array, mask->imageData, mask->imageSize); structure = gst_structure_new("bgfg-mask", "data", G_TYPE_POINTER, data_array, "width", G_TYPE_UINT, mask->width, "height", G_TYPE_UINT, mask->height, "depth", G_TYPE_UINT, mask->depth, "channels", G_TYPE_UINT, mask->nChannels, "timestamp", G_TYPE_UINT64, GST_BUFFER_TIMESTAMP(buf), NULL); event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, structure); gst_pad_push_event(filter->srcpad, event); g_array_unref(data_array); if (filter->display) { // shade the regions not selected by the acmmm2003 algorithm cvXorS(mask, CV_RGB(255, 255, 255), mask, NULL); cvSubS(filter->image, CV_RGB(191, 191, 191), filter->image, mask); cvXorS(mask, CV_RGB(255, 255, 255), mask, NULL); } } if (filter->send_roi_events) { CvSeq *contour; CvRect *bounding_rects; guint i, j, n_rects; // count # of contours, allocate array to store the bounding rectangles for (contour = filter->model->foreground_regions, n_rects = 0; contour != NULL; contour = contour->h_next, ++n_rects); bounding_rects = g_new(CvRect, n_rects); for (contour = filter->model->foreground_regions, i = 0; contour != NULL; contour = contour->h_next, ++i) bounding_rects[i] = cvBoundingRect(contour, 0); for (i = 0; i < n_rects; ++i) { // skip collapsed rectangles if ((bounding_rects[i].width == 0) || (bounding_rects[i].height == 0)) continue; for (j = (i + 1); j < n_rects; ++j) { // skip collapsed rectangles if ((bounding_rects[j].width == 0) || (bounding_rects[j].height == 0)) continue; if (rect_overlap(bounding_rects[i], bounding_rects[j])) { bounding_rects[i] = rect_collapse(bounding_rects[i], bounding_rects[j]); bounding_rects[j] = NULL_RECT; } } } for (i = 0; i < n_rects; ++i) { GstEvent *event; GstStructure *structure; CvRect r; // skip collapsed rectangles r = bounding_rects[i]; if ((r.width == 0) || (r.height == 0)) continue; structure = gst_structure_new("bgfg-roi", "x", G_TYPE_UINT, r.x, "y", G_TYPE_UINT, r.y, "width", G_TYPE_UINT, r.width, "height", G_TYPE_UINT, r.height, "timestamp", G_TYPE_UINT64, GST_BUFFER_TIMESTAMP(buf), NULL); event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, structure); gst_pad_send_event(filter->sinkpad, event); if (filter->verbose) GST_INFO("[roi] x: %d, y: %d, width: %d, height: %d\n", r.x, r.y, r.width, r.height); if (filter->display) cvRectangle(filter->image, cvPoint(r.x, r.y), cvPoint(r.x + r.width, r.y + r.height), CV_RGB(0, 0, 255), 1, 0, 0); } g_free(bounding_rects); } if (filter->display) gst_buffer_set_data(buf, (guchar*) filter->image->imageData, filter->image->imageSize); return gst_pad_push(filter->srcpad, buf); }
/* Can probably be made more efficient - like only checking one area */ static level_mask_t check_bg_collision(game_t *p_game, sprite_t *p_sprite, dir_t dir, point_t new_pt, point_t *p_overlap) { rect_t rect; int16_t x,y; rect = rect_add_pt(p_sprite->p_bounds[p_sprite->frame], new_pt); switch (dir) { case LEFT: rect.bottom_right.x = rect.top_left.x + TILE_W; rect.bottom_right.y-=TILE_H; break; case RIGHT: rect.top_left.x = rect.bottom_right.x - TILE_W; rect.bottom_right.y-=TILE_H; /* FIXME! Better with allow left/right */ break; case UP: rect.bottom_right.y = rect.top_left.y + TILE_W; break; case DOWN: rect.top_left.y = rect.bottom_right.y - TILE_W; break; } #ifndef NDEBUG { rect_t rect2 = rect_add_pt(p_sprite->p_bounds[p_sprite->frame], p_sprite->pt); draw_rect(p_game, rect2, vRGB(255,255,255)); } #endif draw_rect(p_game, rect, vRGB(255,0,0)); for (y = rect.top_left.y/TILE_H; y <= rect.bottom_right.y/TILE_H; y++) { for (x = rect.top_left.x/TILE_W; x <= rect.bottom_right.x/TILE_W; x++) { level_mask_t tile = tile_at(p_game, pt(x,y)); if (tile > 1) { rect_t tile_rect = rect_add_pt(tile_bounds[tile-1], pt_to_sprite(pt(x,y))); draw_rect(p_game, tile_rect, vRGB(0,255,0)); if (rect_overlap(tile_rect, rect, p_overlap)) { assert(tile != 0); #ifndef NDEBUG DbgPrintf(" %d:%d Tile %d rect %d:%d -> %d:%d (overlap %d,%d)\n\n", dir, p_sprite->state, tile, tile_rect.top_left.x,tile_rect.top_left.y, tile_rect.bottom_right.x, tile_rect.bottom_right.y, p_overlap->x, p_overlap->y ); vFlipScreen(0); #endif return tile; } } } } /* TMP! */ DbgPrintf("\n"); #ifndef NDEBUG vFlipScreen(0); #endif return 0; }